Search bar skeleton
This commit is contained in:
84
app/src/main/java/xyz/quaver/pupil/networking/GalleryInfo.kt
Normal file
84
app/src/main/java/xyz/quaver/pupil/networking/GalleryInfo.kt
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
package xyz.quaver.pupil.networking
|
||||||
|
|
||||||
|
import kotlinx.serialization.SerialName
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
interface TagLike {
|
||||||
|
fun toTag(): SearchQuery.Tag
|
||||||
|
}
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class Artist(val artist: String): TagLike {
|
||||||
|
override fun toTag() = SearchQuery.Tag("artist", artist)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class Group(val group: String): TagLike {
|
||||||
|
override fun toTag() = SearchQuery.Tag("group", group)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class Series(val series: String): TagLike {
|
||||||
|
override fun toTag() = SearchQuery.Tag("series", series)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class Character(val character: String): TagLike {
|
||||||
|
override fun toTag() = SearchQuery.Tag("character", character)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class GalleryTag(
|
||||||
|
val tag: String,
|
||||||
|
val female: String? = null,
|
||||||
|
val male: String? = null
|
||||||
|
): TagLike {
|
||||||
|
override fun toTag() = SearchQuery.Tag(
|
||||||
|
if (female.isNullOrEmpty() && male.isNullOrEmpty()) {
|
||||||
|
"tag"
|
||||||
|
} else if (male.isNullOrEmpty()) {
|
||||||
|
"female"
|
||||||
|
} else {
|
||||||
|
"male"
|
||||||
|
},
|
||||||
|
tag
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class Language(
|
||||||
|
@SerialName("galleryid") val galleryID: String,
|
||||||
|
val url: String,
|
||||||
|
@SerialName("language_localname") val localLanguageName: String,
|
||||||
|
val name: String
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class GalleryFiles(
|
||||||
|
@SerialName("haswebp") val hasWebP: Int = 0,
|
||||||
|
@SerialName("hasavif") val hasAVIF: Int = 0,
|
||||||
|
@SerialName("hasjxl") val hasJXL: Int = 0,
|
||||||
|
val height: Int,
|
||||||
|
val width: Int,
|
||||||
|
val hash: String,
|
||||||
|
val name: String,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class GalleryInfo(
|
||||||
|
val id: String,
|
||||||
|
val title: String,
|
||||||
|
@SerialName("japanese_title") val japaneseTitle: String? = null,
|
||||||
|
val language: String? = null,
|
||||||
|
val type: String,
|
||||||
|
val date: String,
|
||||||
|
val artists: List<Artist>? = null,
|
||||||
|
val groups: List<Group>? = null,
|
||||||
|
@SerialName("parodys") val series: List<Series>? = null,
|
||||||
|
val tags: List<GalleryTag>? = null,
|
||||||
|
val related: List<Int> = emptyList(),
|
||||||
|
val languages: List<Language> = emptyList(),
|
||||||
|
val characters: List<Character>? = null,
|
||||||
|
@SerialName("scene_indexes") val sceneIndices: List<Int>? = emptyList(),
|
||||||
|
val files: List<GalleryFiles> = emptyList()
|
||||||
|
)
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
package xyz.quaver.pupil.networking
|
package xyz.quaver.pupil.networking
|
||||||
|
|
||||||
import androidx.collection.mutableIntSetOf
|
|
||||||
import io.ktor.client.HttpClient
|
import io.ktor.client.HttpClient
|
||||||
import io.ktor.client.call.body
|
import io.ktor.client.call.body
|
||||||
import io.ktor.client.engine.okhttp.OkHttp
|
import io.ktor.client.engine.okhttp.OkHttp
|
||||||
@@ -12,6 +11,8 @@ import kotlinx.coroutines.Dispatchers
|
|||||||
import kotlinx.coroutines.async
|
import kotlinx.coroutines.async
|
||||||
import kotlinx.coroutines.coroutineScope
|
import kotlinx.coroutines.coroutineScope
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
import kotlinx.serialization.SerialName
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
import xyz.quaver.pupil.hitomi.max_node_size
|
import xyz.quaver.pupil.hitomi.max_node_size
|
||||||
import java.nio.ByteBuffer
|
import java.nio.ByteBuffer
|
||||||
import java.nio.IntBuffer
|
import java.nio.IntBuffer
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ sealed interface SearchQuery {
|
|||||||
data class Tag(
|
data class Tag(
|
||||||
val namespace: String?,
|
val namespace: String?,
|
||||||
val tag: String
|
val tag: String
|
||||||
): SearchQuery {
|
): SearchQuery, TagLike {
|
||||||
companion object {
|
companion object {
|
||||||
fun parseTag(tag: String): Tag {
|
fun parseTag(tag: String): Tag {
|
||||||
val splitTag = tag.split(':', limit = 1)
|
val splitTag = tag.split(':', limit = 1)
|
||||||
@@ -18,6 +18,8 @@ sealed interface SearchQuery {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun toString() = if (namespace == null) tag else "$namespace:$tag"
|
override fun toString() = if (namespace == null) tag else "$namespace:$tag"
|
||||||
|
|
||||||
|
override fun toTag() = this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -50,7 +50,8 @@ class MainActivity : BaseActivity() {
|
|||||||
windowSize = windowSize,
|
windowSize = windowSize,
|
||||||
displayFeatures = displayFeatures,
|
displayFeatures = displayFeatures,
|
||||||
uiState = uiState,
|
uiState = uiState,
|
||||||
navigateToDestination = viewModel::navigateToDestination
|
navigateToDestination = viewModel::navigateToDestination,
|
||||||
|
closeDetailScreen = viewModel::closeDetailScreen
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
package xyz.quaver.pupil.ui.composable
|
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun GalleryList(
|
|
||||||
|
|
||||||
) {
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -27,7 +27,8 @@ fun MainApp(
|
|||||||
windowSize: WindowSizeClass,
|
windowSize: WindowSizeClass,
|
||||||
displayFeatures: List<DisplayFeature>,
|
displayFeatures: List<DisplayFeature>,
|
||||||
uiState: MainUIState,
|
uiState: MainUIState,
|
||||||
navigateToDestination: (MainDestination) -> Unit
|
navigateToDestination: (MainDestination) -> Unit,
|
||||||
|
closeDetailScreen: () -> Unit
|
||||||
) {
|
) {
|
||||||
val navigationType: NavigationType
|
val navigationType: NavigationType
|
||||||
val contentType: ContentType
|
val contentType: ContentType
|
||||||
@@ -79,9 +80,9 @@ fun MainApp(
|
|||||||
displayFeatures,
|
displayFeatures,
|
||||||
navigationContentPosition,
|
navigationContentPosition,
|
||||||
uiState,
|
uiState,
|
||||||
navigateToDestination
|
navigateToDestination,
|
||||||
|
closeDetailScreen = closeDetailScreen
|
||||||
)
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@@ -91,7 +92,8 @@ private fun MainNavigationWrapper(
|
|||||||
displayFeatures: List<DisplayFeature>,
|
displayFeatures: List<DisplayFeature>,
|
||||||
navigationContentPosition: NavigationContentPosition,
|
navigationContentPosition: NavigationContentPosition,
|
||||||
uiState: MainUIState,
|
uiState: MainUIState,
|
||||||
navigateToDestination: (MainDestination) -> Unit
|
navigateToDestination: (MainDestination) -> Unit,
|
||||||
|
closeDetailScreen: () -> Unit
|
||||||
) {
|
) {
|
||||||
val drawerState = rememberDrawerState(initialValue = DrawerValue.Closed)
|
val drawerState = rememberDrawerState(initialValue = DrawerValue.Closed)
|
||||||
val coroutineScope = rememberCoroutineScope()
|
val coroutineScope = rememberCoroutineScope()
|
||||||
@@ -117,7 +119,8 @@ private fun MainNavigationWrapper(
|
|||||||
navigationContentPosition = navigationContentPosition,
|
navigationContentPosition = navigationContentPosition,
|
||||||
uiState = uiState,
|
uiState = uiState,
|
||||||
navigateToDestination = navigateToDestination,
|
navigateToDestination = navigateToDestination,
|
||||||
onDrawerClicked = openDrawer
|
onDrawerClicked = openDrawer,
|
||||||
|
closeDetailScreen = closeDetailScreen
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -143,7 +146,8 @@ private fun MainNavigationWrapper(
|
|||||||
navigationContentPosition = navigationContentPosition,
|
navigationContentPosition = navigationContentPosition,
|
||||||
uiState = uiState,
|
uiState = uiState,
|
||||||
navigateToDestination = navigateToDestination,
|
navigateToDestination = navigateToDestination,
|
||||||
onDrawerClicked = openDrawer
|
onDrawerClicked = openDrawer,
|
||||||
|
closeDetailScreen = closeDetailScreen
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -157,7 +161,8 @@ fun MainContent(
|
|||||||
navigationContentPosition: NavigationContentPosition,
|
navigationContentPosition: NavigationContentPosition,
|
||||||
uiState: MainUIState,
|
uiState: MainUIState,
|
||||||
navigateToDestination: (MainDestination) -> Unit,
|
navigateToDestination: (MainDestination) -> Unit,
|
||||||
onDrawerClicked: () -> Unit
|
onDrawerClicked: () -> Unit,
|
||||||
|
closeDetailScreen: () -> Unit
|
||||||
) {
|
) {
|
||||||
Row(modifier = Modifier.fillMaxSize()) {
|
Row(modifier = Modifier.fillMaxSize()) {
|
||||||
AnimatedVisibility(visible = navigationType == NavigationType.NAVIGATION_RAIL) {
|
AnimatedVisibility(visible = navigationType == NavigationType.NAVIGATION_RAIL) {
|
||||||
@@ -173,7 +178,16 @@ fun MainContent(
|
|||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.background(MaterialTheme.colorScheme.inverseOnSurface)
|
.background(MaterialTheme.colorScheme.inverseOnSurface)
|
||||||
) {
|
) {
|
||||||
Box(modifier = Modifier.weight(1f))
|
Box(
|
||||||
|
modifier = Modifier.weight(1f)
|
||||||
|
) {
|
||||||
|
MainScreen(
|
||||||
|
contentType = contentType,
|
||||||
|
displayFeatures = displayFeatures,
|
||||||
|
uiState = uiState,
|
||||||
|
closeDetailScreen = closeDetailScreen
|
||||||
|
)
|
||||||
|
}
|
||||||
AnimatedVisibility(visible = navigationType == NavigationType.BOTTOM_NAVIGATION) {
|
AnimatedVisibility(visible = navigationType == NavigationType.BOTTOM_NAVIGATION) {
|
||||||
BottomNavigationBar(
|
BottomNavigationBar(
|
||||||
selectedDestination = uiState.currentDestination,
|
selectedDestination = uiState.currentDestination,
|
||||||
|
|||||||
204
app/src/main/java/xyz/quaver/pupil/ui/composable/MainScreen.kt
Normal file
204
app/src/main/java/xyz/quaver/pupil/ui/composable/MainScreen.kt
Normal file
@@ -0,0 +1,204 @@
|
|||||||
|
package xyz.quaver.pupil.ui.composable
|
||||||
|
|
||||||
|
import androidx.activity.compose.BackHandler
|
||||||
|
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.clickable
|
||||||
|
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||||
|
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.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.height
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.safeDrawingPadding
|
||||||
|
import androidx.compose.foundation.layout.wrapContentHeight
|
||||||
|
import androidx.compose.foundation.lazy.LazyListState
|
||||||
|
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
||||||
|
import androidx.compose.material.icons.filled.ArrowBack
|
||||||
|
import androidx.compose.material3.Card
|
||||||
|
import androidx.compose.material3.CardDefaults
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.IconButton
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableIntStateOf
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.unit.Dp
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.window.layout.DisplayFeature
|
||||||
|
import com.google.accompanist.adaptive.HorizontalTwoPaneStrategy
|
||||||
|
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.ui.viewmodel.MainUIState
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun SearchBar(
|
||||||
|
contentType: ContentType,
|
||||||
|
query: SearchQuery?,
|
||||||
|
onQueryChange: (SearchQuery) -> Unit,
|
||||||
|
onSearch: () -> Unit,
|
||||||
|
topOffset: Int,
|
||||||
|
onTopOffsetChange: (Int) -> Unit,
|
||||||
|
content: @Composable () -> Unit
|
||||||
|
) {
|
||||||
|
var focused by remember { mutableStateOf(false) }
|
||||||
|
val scrimAlpha: Float by animateFloatAsState(if (focused && contentType == ContentType.SINGLE_PANE) 0.3f else 0f, label = "skrim alpha")
|
||||||
|
|
||||||
|
val interactionSource = remember { MutableInteractionSource() }
|
||||||
|
|
||||||
|
if (focused) {
|
||||||
|
BackHandler {
|
||||||
|
focused = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LaunchedEffect(query) {
|
||||||
|
focused = false
|
||||||
|
}
|
||||||
|
|
||||||
|
BoxWithConstraints(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.background(Color.Black.copy(alpha = scrimAlpha))
|
||||||
|
.clickable(
|
||||||
|
interactionSource = interactionSource,
|
||||||
|
indication = null
|
||||||
|
) {
|
||||||
|
focused = false
|
||||||
|
}
|
||||||
|
.safeDrawingPadding()
|
||||||
|
.padding(16.dp)
|
||||||
|
) {
|
||||||
|
val height: Dp by animateDpAsState(if (focused) maxHeight else 60.dp, label = "searchbar height")
|
||||||
|
|
||||||
|
Card(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.height(height)
|
||||||
|
.clickable(
|
||||||
|
interactionSource = interactionSource,
|
||||||
|
indication = null
|
||||||
|
) {
|
||||||
|
focused = true
|
||||||
|
},
|
||||||
|
shape = RoundedCornerShape(30.dp),
|
||||||
|
elevation = if (focused) CardDefaults.cardElevation(
|
||||||
|
defaultElevation = 4.dp
|
||||||
|
) else CardDefaults.cardElevation()
|
||||||
|
) {
|
||||||
|
Box {
|
||||||
|
androidx.compose.animation.AnimatedVisibility(query == null && !focused, enter = fadeIn(), exit = fadeOut()) {
|
||||||
|
Text(
|
||||||
|
modifier = Modifier
|
||||||
|
.height(60.dp)
|
||||||
|
.wrapContentHeight()
|
||||||
|
.padding(horizontal = 16.dp),
|
||||||
|
text = stringResource(id = R.string.search_hint),
|
||||||
|
color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.7f)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
androidx.compose.animation.AnimatedVisibility(focused, enter = fadeIn(), exit = fadeOut()) {
|
||||||
|
Box(Modifier.fillMaxSize().padding(8.dp)) {
|
||||||
|
IconButton(
|
||||||
|
modifier = Modifier.align(Alignment.TopStart),
|
||||||
|
onClick = {
|
||||||
|
focused = false
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.AutoMirrored.Filled.ArrowBack,
|
||||||
|
contentDescription = "close search bar"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun MainScreen(
|
||||||
|
contentType: ContentType,
|
||||||
|
displayFeatures: List<DisplayFeature>,
|
||||||
|
uiState: MainUIState,
|
||||||
|
closeDetailScreen: () -> Unit
|
||||||
|
) {
|
||||||
|
LaunchedEffect(contentType) {
|
||||||
|
if (contentType == ContentType.SINGLE_PANE && !uiState.isDetailOnlyOpen) {
|
||||||
|
closeDetailScreen()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val galleryLazyListState = rememberLazyListState()
|
||||||
|
|
||||||
|
if (contentType == ContentType.DUAL_PANE) {
|
||||||
|
TwoPane(
|
||||||
|
first = {
|
||||||
|
GalleryList(
|
||||||
|
contentType = contentType,
|
||||||
|
galleryLazyListState = galleryLazyListState
|
||||||
|
)
|
||||||
|
},
|
||||||
|
second = {
|
||||||
|
|
||||||
|
},
|
||||||
|
strategy = HorizontalTwoPaneStrategy(splitFraction = 0.5f, gapWidth = 16.dp),
|
||||||
|
displayFeatures = displayFeatures
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
GalleryList(
|
||||||
|
contentType = contentType,
|
||||||
|
galleryLazyListState = galleryLazyListState
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun GalleryList(
|
||||||
|
contentType: ContentType,
|
||||||
|
galleries: List<GalleryInfo> = emptyList(),
|
||||||
|
openedGallery: GalleryInfo? = null,
|
||||||
|
query: SearchQuery? = null,
|
||||||
|
onQueryChange: (SearchQuery) -> Unit = {},
|
||||||
|
onSearch: () -> Unit = { },
|
||||||
|
selectedGalleryIds: Set<Int> = emptySet(),
|
||||||
|
toggleGallerySelection: (Int) -> Unit = {},
|
||||||
|
galleryLazyListState: LazyListState,
|
||||||
|
navigateToDetails: (GalleryInfo, ContentType) -> Unit = { gi, ct -> }
|
||||||
|
) {
|
||||||
|
var topOffset by remember { mutableIntStateOf(0) }
|
||||||
|
|
||||||
|
SearchBar(
|
||||||
|
contentType = contentType,
|
||||||
|
query = query,
|
||||||
|
onQueryChange = onQueryChange,
|
||||||
|
onSearch = onSearch,
|
||||||
|
topOffset = topOffset,
|
||||||
|
onTopOffsetChange = { topOffset = it },
|
||||||
|
) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ package xyz.quaver.pupil.ui.viewmodel
|
|||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
import xyz.quaver.pupil.networking.GalleryInfo
|
||||||
import xyz.quaver.pupil.networking.SearchQuery
|
import xyz.quaver.pupil.networking.SearchQuery
|
||||||
import xyz.quaver.pupil.ui.composable.MainDestination
|
import xyz.quaver.pupil.ui.composable.MainDestination
|
||||||
import xyz.quaver.pupil.ui.composable.mainDestinations
|
import xyz.quaver.pupil.ui.composable.mainDestinations
|
||||||
@@ -16,10 +17,22 @@ class MainViewModel : ViewModel() {
|
|||||||
currentDestination = destination
|
currentDestination = destination
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun closeDetailScreen() {
|
||||||
|
_uiState.value = _uiState.value.copy(
|
||||||
|
isDetailOnlyOpen = false
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun navigateToDetail() {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data class MainUIState(
|
data class MainUIState(
|
||||||
val currentDestination: MainDestination = mainDestinations.first(),
|
val currentDestination: MainDestination = mainDestinations.first(),
|
||||||
val query: SearchQuery? = null,
|
val query: SearchQuery? = null,
|
||||||
val loading: Boolean = true
|
val loading: Boolean = true,
|
||||||
|
val openedGallery: GalleryInfo? = null,
|
||||||
|
val isDetailOnlyOpen: Boolean = false
|
||||||
)
|
)
|
||||||
Reference in New Issue
Block a user