From efc40ce458100116a7c25f89e74c2be66b52a499 Mon Sep 17 00:00:00 2001 From: tom5079 <7948651+tom5079@users.noreply.github.com> Date: Sun, 25 Feb 2024 23:27:23 -0800 Subject: [PATCH] queryeditor wip --- app/build.gradle | 4 +- .../pupil/networking/HitomiHttpClient.kt | 2 - .../quaver/pupil/networking/SearchQuery.kt | 29 +- .../quaver/pupil/ui/composable/MainScreen.kt | 213 +++++++++++++- .../quaver/pupil/ui/composable/QueryEditor.kt | 266 ++++++++++++++++++ .../java/xyz/quaver/pupil/ui/theme/Color.kt | 81 ++++++ app/src/main/res/values-ja/strings.xml | 3 + app/src/main/res/values-ko/strings.xml | 3 + app/src/main/res/values/strings.xml | 7 +- 9 files changed, 588 insertions(+), 20 deletions(-) create mode 100644 app/src/main/java/xyz/quaver/pupil/ui/composable/QueryEditor.kt diff --git a/app/build.gradle b/app/build.gradle index fc9814c5..35a8584c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -79,7 +79,7 @@ dependencies { implementation "androidx.biometric:biometric:1.1.0" implementation "androidx.work:work-runtime-ktx:2.9.0" - implementation platform("androidx.compose:compose-bom:2024.02.00") + implementation platform("androidx.compose:compose-bom:2024.02.01") implementation "androidx.compose.material3:material3" implementation "androidx.compose.material3:material3-window-size-class" @@ -87,7 +87,7 @@ dependencies { implementation 'androidx.compose.ui:ui' implementation 'androidx.compose.ui:ui-tooling-preview' debugImplementation 'androidx.compose.ui:ui-tooling' - androidTestImplementation 'androidx.compose.ui:ui-test-junit4' + androidTestImplementation 'androidx.compose.ui:ui-test-junit4:1.6.1' debugImplementation 'androidx.compose.ui:ui-test-manifest' implementation 'androidx.compose.material:material-icons-extended' implementation 'androidx.activity:activity-compose:1.8.2' diff --git a/app/src/main/java/xyz/quaver/pupil/networking/HitomiHttpClient.kt b/app/src/main/java/xyz/quaver/pupil/networking/HitomiHttpClient.kt index 14c2af48..965cd8fc 100644 --- a/app/src/main/java/xyz/quaver/pupil/networking/HitomiHttpClient.kt +++ b/app/src/main/java/xyz/quaver/pupil/networking/HitomiHttpClient.kt @@ -11,8 +11,6 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.async import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.withContext -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable import xyz.quaver.pupil.hitomi.max_node_size import java.nio.ByteBuffer import java.nio.IntBuffer diff --git a/app/src/main/java/xyz/quaver/pupil/networking/SearchQuery.kt b/app/src/main/java/xyz/quaver/pupil/networking/SearchQuery.kt index c1a77c1e..108d2a95 100644 --- a/app/src/main/java/xyz/quaver/pupil/networking/SearchQuery.kt +++ b/app/src/main/java/xyz/quaver/pupil/networking/SearchQuery.kt @@ -1,8 +1,35 @@ package xyz.quaver.pupil.networking +import androidx.compose.ui.tooling.preview.PreviewParameterProvider + +class SearchQueryPreviewParameterProvider: PreviewParameterProvider { + override val values = sequenceOf( + SearchQuery.And(listOf( + SearchQuery.Or(listOf( + SearchQuery.And(listOf( + SearchQuery.Tag("language", "korean"), + SearchQuery.Tag("female", "unusual pupil"), + SearchQuery.Tag("female", "collar") + )), + SearchQuery.And(listOf( + SearchQuery.Tag("language", "japanese"), + SearchQuery.Tag("female", "unusual pupil"), + SearchQuery.Tag("female", "collar") + )) + )), + SearchQuery.Not( + SearchQuery.And(listOf( + SearchQuery.Tag("male", "yaoi"), + SearchQuery.Tag("group", "zenmai kourogi") + )) + ) + )) + ) +} + sealed interface SearchQuery { data class Tag( - val namespace: String?, + val namespace: String? = null, val tag: String ): SearchQuery, TagLike { companion object { diff --git a/app/src/main/java/xyz/quaver/pupil/ui/composable/MainScreen.kt b/app/src/main/java/xyz/quaver/pupil/ui/composable/MainScreen.kt index a4d5eb09..e0cb27cd 100644 --- a/app/src/main/java/xyz/quaver/pupil/ui/composable/MainScreen.kt +++ b/app/src/main/java/xyz/quaver/pupil/ui/composable/MainScreen.kt @@ -1,38 +1,63 @@ package xyz.quaver.pupil.ui.composable import androidx.activity.compose.BackHandler +import androidx.compose.animation.AnimatedContent import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.core.animateDpAsState import androidx.compose.animation.core.animateFloatAsState import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut import androidx.compose.foundation.background +import androidx.compose.foundation.border import androidx.compose.foundation.clickable +import androidx.compose.foundation.horizontalScroll import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.BoxScope import androidx.compose.foundation.layout.BoxWithConstraints -import androidx.compose.foundation.layout.ColumnScope -import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.heightIn import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.safeDrawingPadding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.wrapContentHeight import androidx.compose.foundation.lazy.LazyListState import androidx.compose.foundation.lazy.rememberLazyListState +import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.filled.ArrowBack -import androidx.compose.material.icons.filled.ArrowBack +import androidx.compose.material.icons.filled.AddCircleOutline +import androidx.compose.material.icons.filled.Book +import androidx.compose.material.icons.filled.Brush +import androidx.compose.material.icons.filled.Face +import androidx.compose.material.icons.filled.Female +import androidx.compose.material.icons.filled.Folder +import androidx.compose.material.icons.filled.Group +import androidx.compose.material.icons.filled.LocalOffer +import androidx.compose.material.icons.filled.Male +import androidx.compose.material.icons.filled.RemoveCircleOutline +import androidx.compose.material.icons.filled.Translate import androidx.compose.material3.Card +import androidx.compose.material3.CardColors import androidx.compose.material3.CardDefaults +import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Icon import androidx.compose.material3.IconButton +import androidx.compose.material3.LocalContentColor +import androidx.compose.material3.LocalTextStyle import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableIntStateOf @@ -41,8 +66,11 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import androidx.window.layout.DisplayFeature @@ -51,8 +79,154 @@ import com.google.accompanist.adaptive.TwoPane import xyz.quaver.pupil.R import xyz.quaver.pupil.networking.GalleryInfo import xyz.quaver.pupil.networking.SearchQuery +import xyz.quaver.pupil.networking.SearchQueryPreviewParameterProvider +import xyz.quaver.pupil.ui.theme.Blue300 +import xyz.quaver.pupil.ui.theme.Blue600 +import xyz.quaver.pupil.ui.theme.Gray300 +import xyz.quaver.pupil.ui.theme.Pink600 +import xyz.quaver.pupil.ui.theme.Red300 +import xyz.quaver.pupil.ui.theme.Yellow400 import xyz.quaver.pupil.ui.viewmodel.MainUIState +private val iconMap = mapOf( + "female" to Icons.Default.Female, + "male" to Icons.Default.Male, + "artist" to Icons.Default.Brush, + "group" to Icons.Default.Group, + "character" to Icons.Default.Face, + "series" to Icons.Default.Book, + "type" to Icons.Default.Folder, + "language" to Icons.Default.Translate, + "tag" to Icons.Default.LocalOffer +) + +@Composable +fun TagChipIcon(tag: SearchQuery.Tag) { + val icon = iconMap[tag.namespace ?: "tag"] + + if (icon != null) + Icon( + icon, + contentDescription = "icon", + modifier = Modifier + .padding(4.dp) + .size(24.dp) + ) + else + Spacer(Modifier.width(16.dp)) +} + +@Composable +fun TagChip( + tag: SearchQuery.Tag, + isFavorite: Boolean = false, + enabled: Boolean = true, + onClick: (SearchQuery.Tag) -> Unit = { }, + leftIcon: @Composable (SearchQuery.Tag) -> Unit = { tag -> TagChipIcon(tag) }, + rightIcon: @Composable (SearchQuery.Tag) -> Unit = { _ -> Spacer(Modifier.width(16.dp)) }, + content: @Composable (SearchQuery.Tag) -> Unit = { tag -> Text(tag.tag) }, +) { + val surfaceColor = if (isFavorite) Yellow400 else when (tag.namespace) { + "male" -> Blue600 + "female" -> Pink600 + else -> MaterialTheme.colorScheme.surface + } + + val contentColor = + if (surfaceColor == MaterialTheme.colorScheme.surface) + MaterialTheme.colorScheme.onSurface + else + Color.White + + val inner = @Composable { + CompositionLocalProvider( + LocalContentColor provides contentColor, + LocalTextStyle provides MaterialTheme.typography.bodyMedium + ) { + Row( + verticalAlignment = Alignment.CenterVertically + ) { + leftIcon(tag) + content(tag) + rightIcon(tag) + } + } + } + + val modifier = Modifier.height(32.dp) + val shape = RoundedCornerShape(16.dp) + + if (enabled) + Surface( + modifier = modifier, + shape = shape, + color = surfaceColor, + onClick = { onClick(tag) }, + content = inner + ) + else + Surface( + modifier, + shape = shape, + color = surfaceColor, + content = inner + ) +} + +@Preview +@Composable +fun QueryView( + @PreviewParameter(SearchQueryPreviewParameterProvider::class) query: SearchQuery?, + topLevel: Boolean = true +) { + val modifier = if (topLevel) { + Modifier + } else { + Modifier.border(width = 0.5.dp, color = LocalContentColor.current, shape = CardDefaults.shape) + } + + when (query) { + is SearchQuery.Tag -> { + TagChip( + query, + enabled = false + ) + } + is SearchQuery.Or -> { + Row( + modifier = modifier.padding(vertical=2.dp, horizontal=4.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(4.dp), + ) { + query.queries.forEachIndexed { index, subquery -> + if (index != 0) { Text("+") } + QueryView(subquery, topLevel = false) + } + } + } + is SearchQuery.And -> { + Row( + horizontalArrangement = Arrangement.spacedBy(4.dp), + verticalAlignment = Alignment.CenterVertically + ) { + query.queries.forEach { subquery -> + QueryView(subquery, topLevel = false) + } + } + } + is SearchQuery.Not -> { + Row( + modifier = modifier.padding(vertical=2.dp, horizontal=4.dp), + horizontalArrangement = Arrangement.spacedBy(4.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Text("-") + QueryView(query.query, topLevel = false) + } + } + } +} + @Composable fun SearchBar( contentType: ContentType, @@ -63,7 +237,7 @@ fun SearchBar( onTopOffsetChange: (Int) -> Unit, content: @Composable () -> Unit ) { - var focused by remember { mutableStateOf(false) } + var focused by remember { mutableStateOf(true) } val scrimAlpha: Float by animateFloatAsState(if (focused && contentType == ContentType.SINGLE_PANE) 0.3f else 0f, label = "skrim alpha") val interactionSource = remember { MutableInteractionSource() } @@ -74,10 +248,6 @@ fun SearchBar( } } - LaunchedEffect(query) { - focused = false - } - BoxWithConstraints( modifier = Modifier .fillMaxSize() @@ -102,7 +272,8 @@ fun SearchBar( indication = null ) { focused = true - }, + } + .clip(RoundedCornerShape(30.dp)), shape = RoundedCornerShape(30.dp), elevation = if (focused) CardDefaults.cardElevation( defaultElevation = 4.dp @@ -119,10 +290,22 @@ fun SearchBar( color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.7f) ) } + androidx.compose.animation.AnimatedVisibility(query != null && !focused, enter = fadeIn(), exit = fadeOut()) { + Row( + modifier = Modifier + .heightIn(min = 60.dp) + .horizontalScroll(rememberScrollState()), + verticalAlignment = Alignment.CenterVertically + ) { + QueryView(query!!) + } + } androidx.compose.animation.AnimatedVisibility(focused, enter = fadeIn(), exit = fadeOut()) { - Box(Modifier.fillMaxSize().padding(8.dp)) { + Column( + Modifier + .fillMaxSize() + .padding(top = 8.dp, start = 8.dp, end = 8.dp)) { IconButton( - modifier = Modifier.align(Alignment.TopStart), onClick = { focused = false } @@ -132,6 +315,10 @@ fun SearchBar( contentDescription = "close search bar" ) } + QueryEditor( + query = query, + onQueryChange = onQueryChange + ) } } } @@ -181,7 +368,7 @@ fun GalleryList( contentType: ContentType, galleries: List = emptyList(), openedGallery: GalleryInfo? = null, - query: SearchQuery? = null, + query: SearchQuery? = SearchQueryPreviewParameterProvider().values.first(), onQueryChange: (SearchQuery) -> Unit = {}, onSearch: () -> Unit = { }, selectedGalleryIds: Set = emptySet(), diff --git a/app/src/main/java/xyz/quaver/pupil/ui/composable/QueryEditor.kt b/app/src/main/java/xyz/quaver/pupil/ui/composable/QueryEditor.kt new file mode 100644 index 00000000..01e88f2b --- /dev/null +++ b/app/src/main/java/xyz/quaver/pupil/ui/composable/QueryEditor.kt @@ -0,0 +1,266 @@ +package xyz.quaver.pupil.ui.composable + +import androidx.compose.animation.AnimatedContent +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.verticalScroll +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.AddCircleOutline +import androidx.compose.material.icons.filled.RemoveCircleOutline +import androidx.compose.material3.Card +import androidx.compose.material3.CardColors +import androidx.compose.material3.HorizontalDivider +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateListOf +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.runtime.toMutableStateList +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp +import xyz.quaver.pupil.R +import xyz.quaver.pupil.networking.SearchQuery +import xyz.quaver.pupil.ui.theme.Blue300 +import xyz.quaver.pupil.ui.theme.Gray300 +import xyz.quaver.pupil.ui.theme.Red300 + +@Composable +fun NewQueryChip(currentQuery: SearchQuery) { + var opened by remember { mutableStateOf(false) } + + @Composable + fun NewQueryRow( + icon: ImageVector = Icons.Default.AddCircleOutline, + text: String, + onClick: () -> Unit + ) { + Row( + modifier = Modifier + .height(32.dp) + .clickable(onClick = onClick), + verticalAlignment = Alignment.CenterVertically + ) { + Icon( + modifier = Modifier + .padding(8.dp) + .size(16.dp), + imageVector = icon, + contentDescription = text + ) + Text( + modifier = Modifier.padding(end = 16.dp), + text = text, + style = MaterialTheme.typography.bodyMedium + ) + } + } + + Surface(shape = RoundedCornerShape(16.dp)) { + AnimatedContent(targetState = opened, label = "add new query") { targetOpened -> + if (targetOpened) { + Column { + NewQueryRow( + icon = Icons.Default.RemoveCircleOutline, + text = stringResource(android.R.string.cancel) + ) { + opened = false + } + HorizontalDivider() + NewQueryRow(text = stringResource(R.string.search_add_query_item_tag)) { + + } + if (currentQuery !is SearchQuery.And) { + HorizontalDivider() + NewQueryRow(text = "AND") { + + } + } + if (currentQuery !is SearchQuery.Or) { + HorizontalDivider() + NewQueryRow(text = "OR") { + + } + } + if (currentQuery !is SearchQuery.Not) { + HorizontalDivider() + NewQueryRow(text = "NOT") { + + } + } + } + } else { + NewQueryRow(text = stringResource(R.string.search_add_query_item)) { + opened = true + } + } + } + } +} + +@Composable +fun QueryEditorQueryView( + query: SearchQuery?, + onQueryAdd: (SearchQuery) -> Unit +) { + when (query) { + is SearchQuery.Tag -> { + TagChip( + query, + enabled = false, + rightIcon = { + Icon( + modifier = Modifier + .padding(8.dp) + .size(16.dp), + imageVector = Icons.Default.RemoveCircleOutline, + contentDescription = stringResource(R.string.search_remove_query_item_description) + ) + } + ) + } + is SearchQuery.Or -> { + Card( + colors = CardColors( + containerColor = Blue300, + contentColor = Color.Black, + disabledContainerColor = Blue300, + disabledContentColor = Color.Black + ) + ) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(8.dp), + verticalArrangement = Arrangement.spacedBy(8.dp), + horizontalAlignment = Alignment.Start, + ) { + Row( + modifier = Modifier.fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween + ) { + Text("OR", modifier = Modifier.padding(horizontal = 8.dp), style = MaterialTheme.typography.labelMedium) + Icon( + modifier = Modifier.size(16.dp), + imageVector = Icons.Default.RemoveCircleOutline, + contentDescription = stringResource(xyz.quaver.pupil.R.string.search_remove_query_item_description) + ) + } + query.queries.forEachIndexed { index, subquery -> + if (index != 0) { Text("+", modifier = Modifier.padding(horizontal = 8.dp)) } + QueryEditorQueryView(subquery, onQueryAdd) + } + NewQueryChip(query) { + + } + } + } + } + is SearchQuery.And -> { + Card( + colors = CardColors( + containerColor = Gray300, + contentColor = Color.Black, + disabledContainerColor = Gray300, + disabledContentColor = Color.Black + ) + ) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(8.dp), + verticalArrangement = Arrangement.spacedBy(8.dp), + horizontalAlignment = Alignment.Start, + ) { + Row( + modifier = Modifier.fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween + ) { + Text("AND", modifier = Modifier.padding(horizontal = 8.dp), style = MaterialTheme.typography.labelMedium) + Icon( + modifier = Modifier.size(16.dp), + imageVector = Icons.Default.RemoveCircleOutline, + contentDescription = stringResource(xyz.quaver.pupil.R.string.search_remove_query_item_description) + ) + } + query.queries.forEach { subquery -> + QueryEditorQueryView(subquery, onQueryAdd) + } + NewQueryChip(query) { + + } + } + } + } + is SearchQuery.Not -> { + Card( + colors = CardColors( + containerColor = Red300, + contentColor = Color.Black, + disabledContainerColor = Red300, + disabledContentColor = Color.Black + ) + ) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(8.dp), + verticalArrangement = Arrangement.spacedBy(8.dp), + horizontalAlignment = Alignment.Start, + ) { + Row( + modifier = Modifier.fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween + ) { + Text("-", modifier = Modifier.padding(horizontal = 8.dp), style = MaterialTheme.typography.labelMedium) + Icon( + modifier = Modifier.size(16.dp), + imageVector = Icons.Default.RemoveCircleOutline, + contentDescription = stringResource(xyz.quaver.pupil.R.string.search_remove_query_item_description) + ) + } + QueryEditorQueryView(query.query, onQueryAdd) + } + } + } + } +} + +@Composable +fun QueryEditor( + query: SearchQuery?, + onQueryChange: (SearchQuery) -> Unit, +) { + Column( + modifier = Modifier.verticalScroll(rememberScrollState()) + ) { + if (query != null) { + QueryEditorQueryView(query = query) { + + } + } else { + NewQueryChip(null) { + + } + } + } +} diff --git a/app/src/main/java/xyz/quaver/pupil/ui/theme/Color.kt b/app/src/main/java/xyz/quaver/pupil/ui/theme/Color.kt index 802b4d5f..e88ef385 100644 --- a/app/src/main/java/xyz/quaver/pupil/ui/theme/Color.kt +++ b/app/src/main/java/xyz/quaver/pupil/ui/theme/Color.kt @@ -65,3 +65,84 @@ val md_theme_dark_scrim = Color(0xFF000000) val seed = Color(0xFF4FC3F7) + +val Gray50 = Color(0xFFF9FAFB) +val Gray100 = Color(0xFFF3F4F6) +val Gray200 = Color(0xFFE5E7EB) +val Gray300 = Color(0xFFD1D5DB) +val Gray400 = Color(0xFF9CA3AF) +val Gray500 = Color(0xFF6B7280) +val Gray600 = Color(0xFF4B5563) +val Gray700 = Color(0xFF374151) +val Gray800 = Color(0xFF1F2937) +val Gray900 = Color(0xFF111827) +val Red50 = Color(0xFFFEF2F2) +val Red100 = Color(0xFFFEE2E2) +val Red200 = Color(0xFFFECACA) +val Red300 = Color(0xFFFCA5A5) +val Red400 = Color(0xFFF87171) +val Red500 = Color(0xFFEF4444) +val Red600 = Color(0xFFDC2626) +val Red700 = Color(0xFFB91C1C) +val Red800 = Color(0xFF991B1B) +val Red900 = Color(0xFF7F1D1D) +val Yellow50 = Color(0xFFFFFBEB) +val Yellow100 = Color(0xFFFEF3C7) +val Yellow200 = Color(0xFFFDE68A) +val Yellow300 = Color(0xFFFCD34D) +val Yellow400 = Color(0xFFFBBF24) +val Yellow500 = Color(0xFFF59E0B) +val Yellow600 = Color(0xFFD97706) +val Yellow700 = Color(0xFFB45309) +val Yellow800 = Color(0xFF92400E) +val Yellow900 = Color(0xFF78350F) +val Green50 = Color(0xFFECFDF5) +val Green100 = Color(0xFFD1FAE5) +val Green200 = Color(0xFFA7F3D0) +val Green300 = Color(0xFF6EE7B7) +val Green400 = Color(0xFF34D399) +val Green500 = Color(0xFF10B981) +val Green600 = Color(0xFF059669) +val Green700 = Color(0xFF047857) +val Green800 = Color(0xFF065F46) +val Green900 = Color(0xFF064E3B) +val Blue50 = Color(0xFFEFF6FF) +val Blue100 = Color(0xFFDBEAFE) +val Blue200 = Color(0xFFBFDBFE) +val Blue300 = Color(0xFF93C5FD) +val Blue400 = Color(0xFF60A5FA) +val Blue500 = Color(0xFF3B82F6) +val Blue600 = Color(0xFF2563EB) +val Blue700 = Color(0xFF1D4ED8) +val Blue800 = Color(0xFF1E40AF) +val Blue900 = Color(0xFF1E3A8A) +val Indigo50 = Color(0xFFEEF2FF) +val Indigo100 = Color(0xFFE0E7FF) +val Indigo200 = Color(0xFFC7D2FE) +val Indigo300 = Color(0xFFA5B4FC) +val Indigo400 = Color(0xFF818CF8) +val Indigo500 = Color(0xFF6366F1) +val Indigo600 = Color(0xFF4F46E5) +val Indigo700 = Color(0xFF4338CA) +val Indigo800 = Color(0xFF3730A3) +val Indigo900 = Color(0xFF312E81) +val Purple50 = Color(0xFFF5F3FF) +val Purple100 = Color(0xFFEDE9FE) +val Purple200 = Color(0xFFDDD6FE) +val Purple300 = Color(0xFFC4B5FD) +val Purple400 = Color(0xFFA78BFA) +val Purple500 = Color(0xFF8B5CF6) +val Purple600 = Color(0xFF7C3AED) +val Purple700 = Color(0xFF6D28D9) +val Purple800 = Color(0xFF5B21B6) +val Purple900 = Color(0xFF4C1D95) +val Pink50 = Color(0xFFFDF2F8) +val Pink100 = Color(0xFFFCE7F3) +val Pink200 = Color(0xFFFBCFE8) +val Pink300 = Color(0xFFF9A8D4) +val Pink400 = Color(0xFFF472B6) +val Pink500 = Color(0xFFEC4899) +val Pink600 = Color(0xFFDB2777) +val Pink700 = Color(0xFFBE185D) +val Pink800 = Color(0xFF9D174D) +val Pink900 = Color(0xFF831843) \ No newline at end of file diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 004b8675..9cda1c27 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -79,6 +79,7 @@ ロックファイルが破損されています。Pupilを再再インストールしてください。 ダークモード 夜にシコりたい方々へ + 追加 ギャラリー情報 アーティスト キャラクター @@ -161,4 +162,6 @@ ネットワーク ダウンロードデータベースを再構築 メニューを閉じる + 検索構文を除去 + タグ \ No newline at end of file diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index 76f53fa9..376159d7 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -77,6 +77,7 @@ 잠금 파일이 손상되었습니다! 앱을 재설치 해 주시기 바랍니다. 다크 모드 딥 다크한 모오드 + 추가 갤러리 정보 작가 캐릭터 @@ -161,4 +162,6 @@ 네트워크 다운로드 데이터베이스 복구 메뉴 닫기 + 검색 구문 제거 + 태그 \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 7a256c22..5e2bcd72 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -66,8 +66,6 @@ Email me! Discord - Thin Mode - Sort Newest Popular @@ -95,6 +93,10 @@ Show histories Show favorite tags + Add + Tag + Remove query item + Details Thumbnails Related Galleries @@ -253,5 +255,6 @@ %1$d/%2$d Importing completed Ah Shit, Here we go again + Thin Mode