diff --git a/api/anilist/src/main/graphql/fragments/User.graphql b/api/anilist/src/main/graphql/fragments/User.graphql index e5d027725..9b27d82e3 100644 --- a/api/anilist/src/main/graphql/fragments/User.graphql +++ b/api/anilist/src/main/graphql/fragments/User.graphql @@ -6,6 +6,9 @@ fragment User on User { large } bannerImage + options { + profileColor + } statistics { anime { count diff --git a/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/sanitize/media/Media.kt b/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/sanitize/media/Media.kt index 0284c742f..858ce0e50 100644 --- a/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/sanitize/media/Media.kt +++ b/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/sanitize/media/Media.kt @@ -1,6 +1,5 @@ package com.imashnake.animite.api.anilist.sanitize.media -import android.graphics.Color import android.util.Log import androidx.compose.runtime.Immutable import androidx.compose.runtime.Stable @@ -49,7 +48,7 @@ data class Media( /** @see MediaQuery.Media.coverImage */ val coverImage: String?, /** @see MediaQuery.CoverImage.color */ - val color: Int, + val color: String, /** @see MediaQuery.Media.title */ val title: String?, /** @see MediaQuery.Media.description */ @@ -584,7 +583,7 @@ data class Media( id = query.id, bannerImage = query.bannerImage, coverImage = query.coverImage?.extraLarge ?: query.coverImage?.large ?: query.coverImage?.medium, - color = query.coverImage?.color?.let { Color.parseColor(it) } ?: Color.TRANSPARENT, + color = query.coverImage?.color ?: "#00000000", title = when (language) { Language.DEFAULT -> query.title?.userPreferred Language.ROMAJI -> query.title?.romaji diff --git a/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/sanitize/profile/Viewer.kt b/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/sanitize/profile/Viewer.kt index 5338f1478..3918e63b0 100644 --- a/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/sanitize/profile/Viewer.kt +++ b/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/sanitize/profile/Viewer.kt @@ -8,10 +8,10 @@ import com.imashnake.animite.api.anilist.sanitize.media.Media import com.imashnake.animite.api.anilist.sanitize.media.Media.Language import com.imashnake.animite.api.anilist.sanitize.media.Media.Small.Type import com.imashnake.animite.api.anilist.sanitize.profile.User.ListNames.Companion.sanitize +import com.imashnake.animite.api.anilist.sanitize.profile.User.ProfileColors.Companion.toHexString import com.imashnake.animite.api.anilist.type.MediaType import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.toImmutableList -import kotlin.collections.indexOf import kotlin.time.Duration.Companion.minutes import kotlin.time.DurationUnit @@ -41,6 +41,8 @@ data class User( val avatar: String?, /** @see User.bannerImage */ val banner: String?, + /** @see User.Options.profileColor */ + val color: String?, // region About /** User Stats */ @@ -170,6 +172,7 @@ data class User( description = query.about, avatar = query.avatar?.large, banner = query.bannerImage, + color = query.options?.profileColor?.toHexString(), stats = listOfNotNull( query.statistics?.anime?.count?.toString()?.let { Stat("TOTAL\nANIME", it) @@ -202,6 +205,36 @@ data class User( ).toImmutableList() ) + /** Profile highlight color (blue, purple, pink, orange, red, green, gray) */ + enum class ProfileColors { + BLUE, PURPLE, PINK, ORANGE, RED, GREEN, GRAY; + + companion object { + fun safeValueOf(rawValue: String): ProfileColors? = try { + ProfileColors.valueOf(rawValue) + } catch (e: IllegalArgumentException) { + Log.e(EXCEPTION_TAG, "safeValueOf: $e; Profile color $rawValue doesn't exist!.") + null + } + + internal fun String?.toHexString(): String { + val color = when(this?.let { ProfileColors.safeValueOf(it.uppercase()) }) { + BLUE -> "#007BA7" + PURPLE -> "#E0AFFF" + PINK -> "#F2BDCD" + ORANGE -> "#F2B949" + RED -> "#FA5053" + GREEN -> "#0BDA51" + GRAY -> "#D9D9D9" + null -> "#FF8DA1" + } + Log.d("whatiscolor", "toHexString: $color") + + return color + } + } + } + enum class Favouritables { Anime, Manga, diff --git a/api/preferences/src/commonMain/kotlin/com/imashnake/animite/api/preferences/PreferencesRepository.kt b/api/preferences/src/commonMain/kotlin/com/imashnake/animite/api/preferences/PreferencesRepository.kt index 8c063bf5c..d0b7f87e0 100644 --- a/api/preferences/src/commonMain/kotlin/com/imashnake/animite/api/preferences/PreferencesRepository.kt +++ b/api/preferences/src/commonMain/kotlin/com/imashnake/animite/api/preferences/PreferencesRepository.kt @@ -19,6 +19,7 @@ private const val IS_AMOLED = false private const val IS_NSFW_ENABLED = false private const val DEFAULT_LANGUAGE_KEY = "DEFAULT" private const val SHOW_USER_DESCRIPTION = true +private const val USE_PROFILE_COLOR = true private const val IS_DEV_OPTIONS_ENABLED = false /** @@ -156,6 +157,12 @@ class PreferencesRepository internal constructor( dataStore.setValue(showUserDescriptionKey, showUserDescription) } + private val useProfileColorKey = booleanPreferencesKey("use_profile_color") + val useProfileColor = dataStore.getValue(useProfileColorKey, USE_PROFILE_COLOR) + suspend fun setUseProfileColor(useProfileColor: Boolean) { + dataStore.setValue(useProfileColorKey, useProfileColor) + } + // region developer options private val isDevOptionsEnabledKey = booleanPreferencesKey("dev_options_enabled") val isDevOptionsEnabled = dataStore.getValue(isDevOptionsEnabledKey, IS_DEV_OPTIONS_ENABLED) diff --git a/app/src/main/kotlin/com/imashnake/animite/MainActivity.kt b/app/src/main/kotlin/com/imashnake/animite/MainActivity.kt index 2ec1324ce..aebe46b88 100644 --- a/app/src/main/kotlin/com/imashnake/animite/MainActivity.kt +++ b/app/src/main/kotlin/com/imashnake/animite/MainActivity.kt @@ -223,6 +223,8 @@ fun MainScreen( onNavigateToSettings = navController::navigate, showUserDescription = showUserDescription, deviceScreenCornerRadius = deviceScreenCornerRadius, + useDarkTheme = useDarkTheme, + isAmoled = isAmoled, sharedTransitionScope = this@SharedTransitionLayout, animatedVisibilityScope = this, ) diff --git a/media/src/main/kotlin/com/imashnake/animite/media/MediaPageViewModel.kt b/media/src/main/kotlin/com/imashnake/animite/media/MediaPageViewModel.kt index 6803fa5e0..a9253578e 100644 --- a/media/src/main/kotlin/com/imashnake/animite/media/MediaPageViewModel.kt +++ b/media/src/main/kotlin/com/imashnake/animite/media/MediaPageViewModel.kt @@ -3,6 +3,7 @@ package com.imashnake.animite.media import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.setValue +import androidx.core.graphics.toColorInt import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope @@ -56,7 +57,7 @@ class MediaPageViewModel @Inject constructor( uiState = uiState.copy( bannerImage = media?.bannerImage, coverImage = media?.coverImage, - color = media?.color, + color = media?.color?.toColorInt(), description = media?.description, nextAiring = media?.nextAiring, info = media?.info, diff --git a/media/src/main/kotlin/com/imashnake/animite/media/MediaThemeUtil.kt b/media/src/main/kotlin/com/imashnake/animite/media/MediaThemeUtil.kt index 079d1c4d7..92204d29a 100644 --- a/media/src/main/kotlin/com/imashnake/animite/media/MediaThemeUtil.kt +++ b/media/src/main/kotlin/com/imashnake/animite/media/MediaThemeUtil.kt @@ -9,6 +9,7 @@ import com.imashnake.animite.media.ext.modify import com.materialkolor.PaletteStyle import com.materialkolor.rememberDynamicColorScheme +// TODO: Move this to core:ui and reuse in profile screen. /** * Remembers a new Material3 [ColorScheme] based on the given color, or falls back to the default * color scheme. diff --git a/profile/src/main/kotlin/com/imashnake/animite/profile/ProfileScreen.kt b/profile/src/main/kotlin/com/imashnake/animite/profile/ProfileScreen.kt index f49db61b5..e5a5c8ab6 100644 --- a/profile/src/main/kotlin/com/imashnake/animite/profile/ProfileScreen.kt +++ b/profile/src/main/kotlin/com/imashnake/animite/profile/ProfileScreen.kt @@ -78,6 +78,7 @@ import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.DpOffset import androidx.compose.ui.unit.dp import androidx.compose.ui.util.fastForEachIndexed +import androidx.core.graphics.toColorInt import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel import coil3.compose.AsyncImage import com.imashnake.animite.api.anilist.sanitize.profile.User @@ -91,6 +92,7 @@ import com.imashnake.animite.core.ui.ext.crossfadeModel import com.imashnake.animite.core.ui.ext.horizontalOnly import com.imashnake.animite.core.ui.ext.maxHeight import com.imashnake.animite.media.MediaPage +import com.imashnake.animite.media.rememberColorSchemeFor import com.imashnake.animite.profile.tabs.AboutTab import com.imashnake.animite.profile.tabs.FavouritesTab import com.imashnake.animite.profile.tabs.MediaTab @@ -118,6 +120,8 @@ fun ProfileScreen( onNavigateToSettings: (SettingsPage) -> Unit, showUserDescription: Boolean, deviceScreenCornerRadius: Int, + useDarkTheme: Boolean, + isAmoled: Boolean, sharedTransitionScope: SharedTransitionScope, animatedVisibilityScope: AnimatedVisibilityScope, contentWindowInsets: WindowInsets = WindowInsets.systemBars.union(WindowInsets.displayCutout), @@ -135,6 +139,7 @@ fun ProfileScreen( val allPaddingValues = insetPaddingValues + navigationComponentPaddingValues val isLoggedIn by viewModel.isLoggedIn.collectAsState(initial = false) + val useProfileColor by viewModel.useProfileColor.collectAsState(initial = true) val viewerAvatar by viewModel.viewerAvatar.collectAsState(initial = "") val viewer by viewModel.viewer.collectAsState() val viewerAnimeLists by viewModel.viewerAnimeLists.collectAsState() @@ -160,132 +165,152 @@ fun ProfileScreen( when { isLoggedIn -> when { data.all { it is Resource.Success } -> viewer.data?.run { - LaunchedEffect(avatar) { - if (viewerAvatar != avatar) viewModel.saveViewerAvatar(avatar) - } - - var isRefreshing by remember { mutableStateOf(false) } - val pullToRefreshState = rememberPullToRefreshState() - PullToRefreshBox( - isRefreshing = isRefreshing, - onRefresh = { viewModel.refresh { isRefreshing = it } }, - state = pullToRefreshState, + MaterialTheme( + colorScheme = if (useProfileColor) { + rememberColorSchemeFor( + color = color?.toColorInt(), + useDarkTheme = useDarkTheme, + isAmoled = isAmoled + ) + } else MaterialTheme.colorScheme ) { - NestedScrollBannerLayout( - banner = { ratio, modifier -> - Box(Modifier.background(MaterialTheme.colorScheme.surfaceContainer)) { - AsyncImage( - model = crossfadeModel(banner), - contentDescription = null, - alpha = 1.2f * ratio - 0.2f, - modifier = modifier, - contentScale = ContentScale.Crop - ) - AsyncImage( - model = crossfadeModel(avatar), - contentDescription = "Avatar", - modifier = Modifier - .align(Alignment.BottomStart) - .padding(start = LocalPaddings.current.large) - .padding(allPaddingValues.horizontalOnly) - .wrapContentSize() - .maxHeight(100.dp) - .clip( - RoundedCornerShape( - topStart = LocalPaddings.current.small, - topEnd = LocalPaddings.current.small, + LaunchedEffect(avatar) { + if (viewerAvatar != avatar) viewModel.saveViewerAvatar(avatar) + } + + var isRefreshing by remember { mutableStateOf(false) } + val pullToRefreshState = rememberPullToRefreshState() + PullToRefreshBox( + isRefreshing = isRefreshing, + onRefresh = { viewModel.refresh { isRefreshing = it } }, + state = pullToRefreshState, + ) { + NestedScrollBannerLayout( + banner = { ratio, modifier -> + Box(Modifier.background(MaterialTheme.colorScheme.surfaceContainer)) { + AsyncImage( + model = crossfadeModel(banner), + contentDescription = null, + alpha = 1.2f * ratio - 0.2f, + modifier = modifier, + contentScale = ContentScale.Crop + ) + AsyncImage( + model = crossfadeModel(avatar), + contentDescription = "Avatar", + modifier = Modifier + .align(Alignment.BottomStart) + .padding(start = LocalPaddings.current.large) + .padding(allPaddingValues.horizontalOnly) + .wrapContentSize() + .maxHeight(100.dp) + .clip( + RoundedCornerShape( + topStart = LocalPaddings.current.small, + topEnd = LocalPaddings.current.small, + ) ) + .graphicsLayer { alpha = 1.5f * ratio - 0.5f }, + ) + } + }, + bannerElevatedContent = { ratio -> + SettingsAndMore( + onNavigateToSettings = onNavigateToSettings, + logOut = { isLogOutDialogShown = true }, + expanded = isDropdownExpanded, + setExpanded = { isDropdownExpanded = it }, + modifier = Modifier + .align(Alignment.TopEnd) + .padding(allPaddingValues.copy(bottom = 0.dp)) + .padding( + start = LocalPaddings.current.large, + bottom = LocalPaddings.current.large, + end = LocalPaddings.current.large ) - .graphicsLayer { alpha = 1.5f * ratio - 0.5f }, + .padding(top = LocalPaddings.current.large * ratio) ) - } - }, - bannerElevatedContent = { ratio -> - SettingsAndMore( - onNavigateToSettings = onNavigateToSettings, - logOut = { isLogOutDialogShown = true }, - expanded = isDropdownExpanded, - setExpanded = { isDropdownExpanded = it }, - modifier = Modifier - .align(Alignment.TopEnd) - .padding(allPaddingValues.copy(bottom = 0.dp)) - .padding( - start = LocalPaddings.current.large, - bottom = LocalPaddings.current.large, - end = LocalPaddings.current.large - ) - .padding(top = LocalPaddings.current.large * ratio) - ) - }, - content = { - Column(verticalArrangement = Arrangement.spacedBy(LocalPaddings.current.ultraTiny)) { + }, + content = { Column( - modifier = Modifier - .padding(horizontal = LocalPaddings.current.large) - .padding(allPaddingValues.horizontalOnly) + verticalArrangement = Arrangement.spacedBy( + LocalPaddings.current.ultraTiny + ) ) { - Text( - text = name, - color = MaterialTheme.colorScheme.onBackground, - style = MaterialTheme.typography.titleLarge, - overflow = TextOverflow.Ellipsis, + Column( modifier = Modifier - .clip(RoundedCornerShape(LocalPaddings.current.small)) - .clickable { showUserDescriptionSheet = true } + .padding(horizontal = LocalPaddings.current.large) + .padding(allPaddingValues.horizontalOnly) + ) { + Text( + text = name, + color = MaterialTheme.colorScheme.onBackground, + style = MaterialTheme.typography.titleLarge, + overflow = TextOverflow.Ellipsis, + modifier = Modifier + .clip(RoundedCornerShape(LocalPaddings.current.small)) + .clickable { + showUserDescriptionSheet = true + } + ) + } + UserTabs( + user = this@run, + animeCollection = viewerAnimeLists.data, + mangaCollection = viewerMangaLists.data, + onNavigateToMediaItem = onNavigateToMediaItem, + showUserDescription = showUserDescription, + onUserDescriptionClick = { + showUserDescriptionSheet = true + }, + sharedTransitionScope = sharedTransitionScope, + animatedVisibilityScope = animatedVisibilityScope, + contentPadding = navigationComponentPaddingValues + insetPaddingValues, ) } - UserTabs( - user = this@run, - animeCollection = viewerAnimeLists.data, - mangaCollection = viewerMangaLists.data, - onNavigateToMediaItem = onNavigateToMediaItem, - showUserDescription = showUserDescription, - onUserDescriptionClick = { showUserDescriptionSheet = true }, - sharedTransitionScope = sharedTransitionScope, - animatedVisibilityScope = animatedVisibilityScope, - contentPadding = navigationComponentPaddingValues + insetPaddingValues, - ) - } - }, - contentBackgroundColor = MaterialTheme.colorScheme.surfaceContainer, - contentPadding = PaddingValues(top = LocalPaddings.current.large / 2) - ) - } - - if (showUserDescriptionSheet) { - BottomSheet( - sheetState = userDescriptionSheetState, - onDismissRequest = { showUserDescriptionSheet = false }, - deviceScreenCornerRadiusDp = deviceScreenCornerRadiusDp, - contentPadding = PaddingValues( - horizontal = LocalPaddings.current.large, - vertical = LocalPaddings.current.medium - ), - modifier = Modifier, - ) { paddingValues, modifier -> - Column(modifier) { - Text( - text = this@run.name, - color = MaterialTheme.colorScheme.onBackground, - style = MaterialTheme.typography.titleLarge, - modifier = Modifier - .fillMaxWidth() - .background(MaterialTheme.colorScheme.surfaceContainerHighest) - .padding(paddingValues) - ) + }, + contentBackgroundColor = MaterialTheme.colorScheme.surfaceContainer, + contentPadding = PaddingValues(top = LocalPaddings.current.large / 2) + ) + } - this@run.description?.let { - UserDescriptionMarkdown( - content = it, - modifier = Modifier.padding(paddingValues) + if (showUserDescriptionSheet) { + BottomSheet( + sheetState = userDescriptionSheetState, + onDismissRequest = { showUserDescriptionSheet = false }, + deviceScreenCornerRadiusDp = deviceScreenCornerRadiusDp, + contentPadding = PaddingValues( + horizontal = LocalPaddings.current.large, + vertical = LocalPaddings.current.medium + ), + modifier = Modifier, + ) { paddingValues, modifier -> + Column(modifier) { + Text( + text = this@run.name, + color = MaterialTheme.colorScheme.onBackground, + style = MaterialTheme.typography.titleLarge, + modifier = Modifier + .fillMaxWidth() + .background(MaterialTheme.colorScheme.surfaceContainerHighest) + .padding(paddingValues) ) + + this@run.description?.let { + UserDescriptionMarkdown( + content = it, + modifier = Modifier.padding(paddingValues) + ) + } } } } } } + else -> ProgressIndicatorScreen(Modifier.padding(allPaddingValues)) } + else -> { SettingsIcon( onNavigateToSettings = onNavigateToSettings, diff --git a/profile/src/main/kotlin/com/imashnake/animite/profile/ProfileViewModel.kt b/profile/src/main/kotlin/com/imashnake/animite/profile/ProfileViewModel.kt index 1be8d39f6..089dde3fc 100644 --- a/profile/src/main/kotlin/com/imashnake/animite/profile/ProfileViewModel.kt +++ b/profile/src/main/kotlin/com/imashnake/animite/profile/ProfileViewModel.kt @@ -45,6 +45,8 @@ class ProfileViewModel @Inject constructor( .accessToken .map { !it.isNullOrEmpty() } + val useProfileColor = preferencesRepository.useProfileColor.filterNotNull() + val viewer = combine( flow = refreshTrigger.onStart { emit(Unit) }, flow2 = preferencesRepository.language.filterNotNull(), diff --git a/settings/src/main/kotlin/com/imashnake/animite/settings/SettingsPage.kt b/settings/src/main/kotlin/com/imashnake/animite/settings/SettingsPage.kt index bf359b497..ac178eb9f 100644 --- a/settings/src/main/kotlin/com/imashnake/animite/settings/SettingsPage.kt +++ b/settings/src/main/kotlin/com/imashnake/animite/settings/SettingsPage.kt @@ -110,6 +110,7 @@ private const val PRIVACY_POLICY = "https://imashnake.deno.dev/animite.html" private const val SYSTEM_DAY_PART = "SYSTEM" private const val ANIMITE = "Animite" +// TODO: What a hodgepodge, do something. @OptIn(ExperimentalMaterial3ExpressiveApi::class, ExperimentalMaterial3Api::class) @Composable fun SettingsPage( @@ -132,6 +133,7 @@ fun SettingsPage( val isNsfwEnabled by viewModel.isNsfwEnabled.collectAsState(initial = false) val showUserDescription by viewModel.showUserDescription.collectAsState(initial = true) + val useProfileColor by viewModel.useProfileColor.collectAsState(initial = true) val selectedLanguage by viewModel.language.collectAsState(initial = Media.Language.DEFAULT.name) val listSize by viewModel.listSize.collectAsState(initial = 10) @@ -174,7 +176,7 @@ fun SettingsPage( orientation = Item.Orientation.VERTICAL ), Item( - icon = R.drawable.palette, + icon = R.drawable.paint_brush, label = R.string.palette, orientation = Item.Orientation.HORIZONTAL ), @@ -546,6 +548,11 @@ fun SettingsPage( label = R.string.show_description, orientation = Item.Orientation.HORIZONTAL ), + Item( + icon = R.drawable.palette, + label = R.string.profile_color, + orientation = Item.Orientation.HORIZONTAL + ), ), onItemClick = { index -> when (index) { @@ -557,6 +564,14 @@ fun SettingsPage( } else HapticFeedbackType.ToggleOn ) } + 1 -> { + viewModel.setUseProfileColor(!useProfileColor) + haptic.performHapticFeedback( + hapticFeedbackType = if (useProfileColor) { + HapticFeedbackType.ToggleOff + } else HapticFeedbackType.ToggleOn + ) + } } }, onItemLongClick = {}, @@ -586,6 +601,30 @@ fun SettingsPage( }, ) } + 1 -> { + // TODO: Add color options and mutate. + Switch( + checked = useProfileColor, + onCheckedChange = { + viewModel.setUseProfileColor(it) + haptic.performHapticFeedback( + hapticFeedbackType = if (!it) { + HapticFeedbackType.ToggleOff + } else HapticFeedbackType.ToggleOn + ) + }, + thumbContent = { + if (useProfileColor) { + Icon( + imageVector = ImageVector.vectorResource(R.drawable.fill_bucket), + contentDescription = null, + modifier = Modifier.size(SwitchDefaults.IconSize), + tint = MaterialTheme.colorScheme.primary + ) + } + }, + ) + } } } } diff --git a/settings/src/main/kotlin/com/imashnake/animite/settings/SettingsViewModel.kt b/settings/src/main/kotlin/com/imashnake/animite/settings/SettingsViewModel.kt index a556741b9..feab5647a 100644 --- a/settings/src/main/kotlin/com/imashnake/animite/settings/SettingsViewModel.kt +++ b/settings/src/main/kotlin/com/imashnake/animite/settings/SettingsViewModel.kt @@ -43,6 +43,7 @@ class SettingsViewModel @Inject constructor( } val animeListsIndices = preferencesRepository.animeListsIndices.filterNotNull() val showUserDescription = preferencesRepository.showUserDescription.filterNotNull() + val useProfileColor = preferencesRepository.useProfileColor.filterNotNull() val mangaList = preferencesRepository.mangaListsIndices.map { indices -> indices?.map { @@ -88,6 +89,10 @@ class SettingsViewModel @Inject constructor( preferencesRepository.setShowUserDescription(showUserDescription) } + fun setUseProfileColor(useProfileColor: Boolean) = viewModelScope.launch(Dispatchers.IO) { + preferencesRepository.setUseProfileColor(useProfileColor) + } + fun setDevOptions(enabled: Boolean) = viewModelScope.launch(Dispatchers.IO) { preferencesRepository.setDevOptionsEnabled(enabled) } diff --git a/settings/src/main/res/drawable/fill_bucket.xml b/settings/src/main/res/drawable/fill_bucket.xml new file mode 100644 index 000000000..6a948631b --- /dev/null +++ b/settings/src/main/res/drawable/fill_bucket.xml @@ -0,0 +1,24 @@ + + + + diff --git a/settings/src/main/res/drawable/paint_brush.xml b/settings/src/main/res/drawable/paint_brush.xml new file mode 100644 index 000000000..a735be5ba --- /dev/null +++ b/settings/src/main/res/drawable/paint_brush.xml @@ -0,0 +1,24 @@ + + + + diff --git a/settings/src/main/res/drawable/palette.xml b/settings/src/main/res/drawable/palette.xml index 79c65b1a6..2f72f78e4 100644 --- a/settings/src/main/res/drawable/palette.xml +++ b/settings/src/main/res/drawable/palette.xml @@ -1,9 +1,24 @@ + diff --git a/settings/src/main/res/values/strings.xml b/settings/src/main/res/values/strings.xml index 2398d3378..63ebb2775 100644 --- a/settings/src/main/res/values/strings.xml +++ b/settings/src/main/res/values/strings.xml @@ -22,6 +22,7 @@ Profile Show description + Set profile color About