From f39ec08f054a197ac04a476727ea189d31fb7bdd Mon Sep 17 00:00:00 2001 From: Kevin Schildhorn Date: Wed, 6 Dec 2023 15:36:06 -0500 Subject: [PATCH 1/5] Adding overlay --- .../fotopresenter/ui/SharedImage.kt | 4 +- shared/src/commonMain/kotlin/App.kt | 5 +- .../fotopresenter/data/DirectoryContents.kt | 3 + .../fotopresenter/ui/SharedImage.kt | 2 +- .../fotopresenter/ui/atoms/Padding.kt | 1 + .../ui/compose/DirectoryScreen.kt | 35 +++++++--- .../ui/compose/ImagePreviewOverlay.kt | 67 +++++++++++++++++++ .../ui/compose/directory/DirectoryGrid.kt | 5 +- .../compose/directory/PhotoDirectoryItem.kt | 2 +- .../ui/viewmodel/PhotoDirectoryViewModel.kt | 4 +- .../fotopresenter/ui/SharedImage.kt | 2 +- .../fotopresenter/ui/SharedImage.kt | 2 +- .../fotopresenter/ui/SharedImage.kt | 4 +- 13 files changed, 113 insertions(+), 23 deletions(-) create mode 100644 shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/ImagePreviewOverlay.kt diff --git a/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/SharedImage.kt b/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/SharedImage.kt index 6e73511a..c9a2b84d 100644 --- a/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/SharedImage.kt +++ b/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/SharedImage.kt @@ -6,11 +6,11 @@ import androidx.compose.ui.graphics.ImageBitmap import androidx.compose.ui.graphics.asImageBitmap import com.hierynomus.smbj.share.File -actual fun getBitmapFromFile(file: File): ImageBitmap? { +actual fun getBitmapFromFile(file: File, size:Int): ImageBitmap? { val options = BitmapFactory.Options() options.inSampleSize = 3 BitmapFactory.decodeStream(file.inputStream, null, options)?.let { - return Bitmap.createScaledBitmap(it, 200, 200, false).asImageBitmap() + return Bitmap.createScaledBitmap(it, size, size, false).asImageBitmap() } return null diff --git a/shared/src/commonMain/kotlin/App.kt b/shared/src/commonMain/kotlin/App.kt index e3919553..9e00e155 100644 --- a/shared/src/commonMain/kotlin/App.kt +++ b/shared/src/commonMain/kotlin/App.kt @@ -3,6 +3,7 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import com.kevinschildhorn.fotopresenter.ui.compose.DirectoryScreen +import com.kevinschildhorn.fotopresenter.ui.compose.ImagePreviewOverlay import com.kevinschildhorn.fotopresenter.ui.compose.LoginScreen import com.kevinschildhorn.fotopresenter.ui.compose.Screen import com.kevinschildhorn.fotopresenter.ui.viewmodel.DirectoryViewModel @@ -21,8 +22,8 @@ fun App( LoginScreen(loginViewModel) { currentScreen.value = Screen.DIRECTORY } - - Screen.DIRECTORY -> DirectoryScreen(directoryViewModel) + Screen.DIRECTORY -> DirectoryScreen(directoryViewModel) { + } } } } diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/DirectoryContents.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/DirectoryContents.kt index 9a7e483c..8d5db8ae 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/DirectoryContents.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/DirectoryContents.kt @@ -5,6 +5,9 @@ import com.kevinschildhorn.fotopresenter.ui.SharedImage interface DirectoryContent { val directory: NetworkDirectory + + val asImageDirectory: ImageDirectoryContent? + get() = this as? ImageDirectoryContent } data class FolderDirectoryContent( diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/SharedImage.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/SharedImage.kt index 1247e166..5aa71744 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/SharedImage.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/SharedImage.kt @@ -3,5 +3,5 @@ package com.kevinschildhorn.fotopresenter.ui import androidx.compose.ui.graphics.ImageBitmap expect class SharedImage { - fun getImageBitmap(): ImageBitmap? + fun getImageBitmap(size:Int): ImageBitmap? } diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/atoms/Padding.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/atoms/Padding.kt index ad2f8979..90d303aa 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/atoms/Padding.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/atoms/Padding.kt @@ -4,6 +4,7 @@ import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp enum class Padding(val rawValue: Int) { + IMAGE(50), EXTRA_LARGE(64), LARGE(32), STANDARD(20), diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/DirectoryScreen.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/DirectoryScreen.kt index 10cd9485..596d76cd 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/DirectoryScreen.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/DirectoryScreen.kt @@ -5,31 +5,48 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier +import com.kevinschildhorn.fotopresenter.data.ImageDirectoryContent import com.kevinschildhorn.fotopresenter.ui.atoms.Padding import com.kevinschildhorn.fotopresenter.ui.compose.directory.DirectoryGrid import com.kevinschildhorn.fotopresenter.ui.viewmodel.DirectoryViewModel @Composable -fun DirectoryScreen(viewModel: DirectoryViewModel) { +fun DirectoryScreen( + viewModel: DirectoryViewModel, + onImageSelected: (ImageDirectoryContent) -> Unit, +) { LaunchedEffect(Unit) { viewModel.refreshScreen() } val uiState by viewModel.uiState.collectAsState() - + var imageState: ImageDirectoryContent? by remember { mutableStateOf(null) } uiState.state.asComposable( modifier = - Modifier.padding( - horizontal = Padding.STANDARD.dp, - vertical = Padding.SMALL.dp, - ), + Modifier.padding( + horizontal = Padding.STANDARD.dp, + vertical = Padding.SMALL.dp, + ), ) DirectoryGrid( uiState.directoryContents, modifier = - Modifier - .padding(top = Padding.EXTRA_LARGE.dp), + Modifier + .padding(top = Padding.EXTRA_LARGE.dp), ) { - viewModel.changeDirectory(it) + it.asImageDirectory?.let { + imageState = it + onImageSelected(it) + } ?: run { + viewModel.changeDirectory(it.directory) + } + } + imageState?.let { + ImagePreviewOverlay(it){ + imageState = null + } } } diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/ImagePreviewOverlay.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/ImagePreviewOverlay.kt new file mode 100644 index 00000000..3788347a --- /dev/null +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/ImagePreviewOverlay.kt @@ -0,0 +1,67 @@ +package com.kevinschildhorn.fotopresenter.ui.compose + +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.material.CircularProgressIndicator +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.unit.dp +import com.kevinschildhorn.atomik.color.base.composeColor +import com.kevinschildhorn.fotopresenter.data.ImageDirectoryContent +import com.kevinschildhorn.fotopresenter.ui.atoms.FotoColors +import com.kevinschildhorn.fotopresenter.ui.atoms.Padding +import com.kevinschildhorn.fotopresenter.ui.compose.common.Overlay +import com.kevinschildhorn.fotopresenter.ui.state.State +import com.kevinschildhorn.fotopresenter.ui.viewmodel.PhotoDirectoryViewModel + +@Composable +fun ImagePreviewOverlay( + imageContent: ImageDirectoryContent, + viewModel: PhotoDirectoryViewModel = PhotoDirectoryViewModel(imageContent.image), + onDismiss: () -> Unit, +) { + val imageState by viewModel.imageState.collectAsState(State.IDLE) + val interactionSource = remember { MutableInteractionSource() } + + LaunchedEffect(Unit) { + viewModel.refreshImageBitmap(500) + } + + Overlay( + 5f, + modifier = Modifier + .background(FotoColors.shadow.composeColor) + .clickable( + interactionSource = interactionSource, + indication = null, + onClick = onDismiss, + ), + ) { + imageState.onSuccess { + Image( + bitmap = it, + contentDescription = null, + modifier = Modifier.fillMaxSize().padding(Padding.IMAGE.dp) + ) + }.onLoading { + CircularProgressIndicator( + modifier = Modifier.width(75.dp).align(Alignment.Center), + color = FotoColors.primary.composeColor, + ) + }.onError { + Text("Error") + } + } +} \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/directory/DirectoryGrid.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/directory/DirectoryGrid.kt index 10afb77e..ddfdddac 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/directory/DirectoryGrid.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/directory/DirectoryGrid.kt @@ -17,6 +17,7 @@ import androidx.compose.ui.hapticfeedback.HapticFeedbackType import androidx.compose.ui.platform.LocalHapticFeedback import androidx.compose.ui.unit.dp import androidx.compose.ui.zIndex +import com.kevinschildhorn.fotopresenter.data.DirectoryContent import com.kevinschildhorn.fotopresenter.data.DirectoryContents import com.kevinschildhorn.fotopresenter.data.FolderDirectoryContent import com.kevinschildhorn.fotopresenter.data.ImageDirectoryContent @@ -29,7 +30,7 @@ fun DirectoryGrid( directoryContent: DirectoryContents, gridSize: Int = 5, modifier: Modifier = Modifier, - onDirectoryPressed: (NetworkDirectory) -> Unit, + onDirectoryPressed: (DirectoryContent) -> Unit, ) { var actionSheetVisible by remember { mutableStateOf(false) } var contextMenuPhotoId by rememberSaveable { mutableStateOf(null) } @@ -45,7 +46,7 @@ fun DirectoryGrid( .padding(5.dp) .combinedClickable( onClick = { - onDirectoryPressed(content.directory) + onDirectoryPressed(content) }, onLongClick = { haptics.performHapticFeedback(HapticFeedbackType.LongPress) diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/directory/PhotoDirectoryItem.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/directory/PhotoDirectoryItem.kt index 2954ebea..b9a2b648 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/directory/PhotoDirectoryItem.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/directory/PhotoDirectoryItem.kt @@ -32,7 +32,7 @@ fun PhotoDirectoryItem( val imageState by viewModel.imageState.collectAsState(State.IDLE) LaunchedEffect(Unit) { - viewModel.refreshImageBitmap() + viewModel.refreshImageBitmap(200) } BaseDirectory(modifier) { imageState.onSuccess { diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/viewmodel/PhotoDirectoryViewModel.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/viewmodel/PhotoDirectoryViewModel.kt index 07211c74..c5b9ab64 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/viewmodel/PhotoDirectoryViewModel.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/viewmodel/PhotoDirectoryViewModel.kt @@ -14,11 +14,11 @@ class PhotoDirectoryViewModel(private val image: SharedImage?) : ViewModel() { private val _imageState: MutableStateFlow> = MutableStateFlow(State.IDLE) val imageState: StateFlow> = _imageState.asStateFlow() - fun refreshImageBitmap() { + fun refreshImageBitmap(size:Int) { var state: State = State.LOADING _imageState.update { state } viewModelScope.launch(Dispatchers.Default) { - image?.getImageBitmap()?.let { + image?.getImageBitmap(size)?.let { state = State.SUCCESS(it) _imageState.update { state } } ?: run { diff --git a/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/ui/SharedImage.kt b/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/ui/SharedImage.kt index 82317d70..b113824f 100644 --- a/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/ui/SharedImage.kt +++ b/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/ui/SharedImage.kt @@ -4,5 +4,5 @@ import androidx.compose.ui.graphics.ImageBitmap import androidx.compose.ui.res.loadImageBitmap import com.hierynomus.smbj.share.File -actual fun getBitmapFromFile(file: File): ImageBitmap? = +actual fun getBitmapFromFile(file: File, size:Int): ImageBitmap? = file.inputStream.buffered().use(::loadImageBitmap) diff --git a/shared/src/iosMain/kotlin/com/kevinschildhorn/fotopresenter/ui/SharedImage.kt b/shared/src/iosMain/kotlin/com/kevinschildhorn/fotopresenter/ui/SharedImage.kt index cf84f72d..0f22bd1e 100644 --- a/shared/src/iosMain/kotlin/com/kevinschildhorn/fotopresenter/ui/SharedImage.kt +++ b/shared/src/iosMain/kotlin/com/kevinschildhorn/fotopresenter/ui/SharedImage.kt @@ -3,5 +3,5 @@ package com.kevinschildhorn.fotopresenter.ui import androidx.compose.ui.graphics.ImageBitmap actual class SharedImage { - actual fun getImageBitmap(): ImageBitmap? = null + actual fun getImageBitmap(size:Int): ImageBitmap? = null } diff --git a/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/ui/SharedImage.kt b/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/ui/SharedImage.kt index e0efa64b..b2b1138b 100644 --- a/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/ui/SharedImage.kt +++ b/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/ui/SharedImage.kt @@ -4,7 +4,7 @@ import androidx.compose.ui.graphics.ImageBitmap import com.hierynomus.smbj.share.File actual open class SharedImage(val file: File) { - actual fun getImageBitmap(): ImageBitmap? = getBitmapFromFile(file) + actual fun getImageBitmap(size: Int): ImageBitmap? = getBitmapFromFile(file, size) } -expect fun getBitmapFromFile(file: File): ImageBitmap? +expect fun getBitmapFromFile(file: File, size: Int): ImageBitmap? From 2d29598dd675ca5d2898128ae29755a76bbd26ad Mon Sep 17 00:00:00 2001 From: Kevin Schildhorn Date: Thu, 7 Dec 2023 11:20:37 -0500 Subject: [PATCH 2/5] Renaming everything --- .../ui/compose/DirectoryPreviews.kt | 24 +++++----- .../fotopresenter/ui/compose/LoginPreviews.kt | 13 +++-- .../fotopresenter/data/Directory.kt | 31 ++++++++++++ .../fotopresenter/data/DirectoryContents.kt | 28 ----------- .../fotopresenter/{ui/state => data}/State.kt | 2 +- .../data/datasources/DirectoryDataSource.kt | 6 +-- .../data/datasources/ImageRemoteDataSource.kt | 4 +- ...irectory.kt => NetworkDirectoryDetails.kt} | 6 +-- .../data/network/NetworkHandler.kt | 2 +- .../data/repositories/DirectoryRepository.kt | 14 +++--- .../data/repositories/ImageRepository.kt | 4 +- .../RetrieveDirectoryContentsUseCase.kt | 8 ++-- .../ui/compose/DirectoryScreen.kt | 6 +-- .../ui/compose/ImagePreviewOverlay.kt | 7 ++- .../compose/{NavigationState.kt => Screen.kt} | 4 -- .../ui/compose/directory/DirectoryGrid.kt | 28 +++++------ ...{BaseDirectory.kt => DirectoryGridCell.kt} | 4 +- ...toryItem.kt => FolderDirectoryGridCell.kt} | 11 +++-- ...ctoryItem.kt => ImageDirectoryGridCell.kt} | 27 ++++------- .../{FotoCheckbox.kt => LoginCheckbox.kt} | 2 +- ...TextField.kt => LoginPasswordTextField.kt} | 25 +--------- .../ui/compose/login/LoginScreenForm.kt | 12 ++--- .../ui/compose/login/LoginTextField.kt | 33 +++++++++++++ .../ui/state/DirectoryScreenState.kt | 30 +++++++++++- .../ui/viewmodel/DirectoryViewModel.kt | 48 +++++++++++++++---- .../ui/viewmodel/PhotoDirectoryViewModel.kt | 2 +- .../datasources/ImageRemoteDataSourceTest.kt | 8 ++-- .../data/network/MockNetworkHandler.kt | 26 +++++----- .../data/repositories/ImageRepositoryTest.kt | 8 ++-- .../RetrieveDirectoryContentsUseCaseTest.kt | 4 +- .../fotopresenter/data/network/SMBJHandler.kt | 4 +- ...tory.kt => SMBJNetworkDirectoryDetails.kt} | 4 +- 32 files changed, 243 insertions(+), 192 deletions(-) create mode 100644 shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/Directory.kt delete mode 100644 shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/DirectoryContents.kt rename shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/{ui/state => data}/State.kt (95%) rename shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/network/{NetworkDirectory.kt => NetworkDirectoryDetails.kt} (87%) rename shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/{NavigationState.kt => Screen.kt} (61%) rename shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/directory/{BaseDirectory.kt => DirectoryGridCell.kt} (97%) rename shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/directory/{FolderDirectoryItem.kt => FolderDirectoryGridCell.kt} (84%) rename shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/directory/{PhotoDirectoryItem.kt => ImageDirectoryGridCell.kt} (68%) rename shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/login/{FotoCheckbox.kt => LoginCheckbox.kt} (97%) rename shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/login/{FotoTextField.kt => LoginPasswordTextField.kt} (63%) create mode 100644 shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/login/LoginTextField.kt rename shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/data/network/{SMBJNetworkDirectory.kt => SMBJNetworkDirectoryDetails.kt} (80%) diff --git a/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/DirectoryPreviews.kt b/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/DirectoryPreviews.kt index 1dfce8f4..045e0dba 100644 --- a/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/DirectoryPreviews.kt +++ b/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/DirectoryPreviews.kt @@ -4,17 +4,17 @@ import androidx.compose.foundation.layout.Column import androidx.compose.runtime.Composable import androidx.compose.ui.tooling.preview.Preview import com.kevinschildhorn.fotopresenter.data.DirectoryContents -import com.kevinschildhorn.fotopresenter.data.FolderDirectoryContent -import com.kevinschildhorn.fotopresenter.data.network.MockNetworkDirectory -import com.kevinschildhorn.fotopresenter.ui.compose.directory.BaseDirectory +import com.kevinschildhorn.fotopresenter.data.FolderDirectory +import com.kevinschildhorn.fotopresenter.data.network.MockNetworkDirectoryDetails +import com.kevinschildhorn.fotopresenter.ui.compose.directory.DirectoryGridCell import com.kevinschildhorn.fotopresenter.ui.compose.directory.DirectoryGrid -import com.kevinschildhorn.fotopresenter.ui.compose.directory.FolderDirectoryItem +import com.kevinschildhorn.fotopresenter.ui.compose.directory.FolderDirectoryGridCell @Preview @Composable fun BaseDirectoryPreview() { Column { - BaseDirectory() {} + DirectoryGridCell() {} } } @@ -22,7 +22,7 @@ fun BaseDirectoryPreview() { @Composable fun FolderDirectoryEmptyPreview() { Column { - FolderDirectoryItem("Folder") + FolderDirectoryGridCell("Folder") } } @@ -32,12 +32,12 @@ fun DirectoryGridPreview() { DirectoryGrid( DirectoryContents( folders = listOf( - FolderDirectoryContent(MockNetworkDirectory("Test 1", id = 1)), - FolderDirectoryContent(MockNetworkDirectory("Test 2", id = 2)), - FolderDirectoryContent(MockNetworkDirectory("Test 3", id = 3)), - FolderDirectoryContent(MockNetworkDirectory("Test 4", id = 4)), - FolderDirectoryContent(MockNetworkDirectory("Test 6", id = 5)), - FolderDirectoryContent(MockNetworkDirectory("Test 5", id = 6)), + FolderDirectory(MockNetworkDirectoryDetails("Test 1", id = 1)), + FolderDirectory(MockNetworkDirectoryDetails("Test 2", id = 2)), + FolderDirectory(MockNetworkDirectoryDetails("Test 3", id = 3)), + FolderDirectory(MockNetworkDirectoryDetails("Test 4", id = 4)), + FolderDirectory(MockNetworkDirectoryDetails("Test 6", id = 5)), + FolderDirectory(MockNetworkDirectoryDetails("Test 5", id = 6)), ), ), ) { diff --git a/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/LoginPreviews.kt b/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/LoginPreviews.kt index 3fcf39bc..a0d5a9a3 100644 --- a/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/LoginPreviews.kt +++ b/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/LoginPreviews.kt @@ -5,11 +5,10 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.tooling.preview.Preview import com.kevinschildhorn.fotopresenter.ui.compose.common.ErrorView import com.kevinschildhorn.fotopresenter.ui.compose.common.TitleView -import com.kevinschildhorn.fotopresenter.ui.compose.login.FotoPasswordTextField -import com.kevinschildhorn.fotopresenter.ui.compose.login.FotoTextField +import com.kevinschildhorn.fotopresenter.ui.compose.login.LoginPasswordTextField +import com.kevinschildhorn.fotopresenter.ui.compose.login.LoginTextField import com.kevinschildhorn.fotopresenter.ui.compose.login.LoginScreenForm import com.kevinschildhorn.fotopresenter.ui.state.LoginScreenState -import com.kevinschildhorn.fotopresenter.ui.state.State import com.kevinschildhorn.fotopresenter.ui.state.UiState @Preview @@ -28,10 +27,10 @@ fun ErrorViewPreview() { @Composable fun FotoTextFieldPreview() { Column { - FotoTextField("", {}, "Hint") - FotoTextField("Value", {}, "Hint") - FotoPasswordTextField("", {}, "Password") - FotoPasswordTextField("Value", {}, "Password") + LoginTextField("", {}, "Hint") + LoginTextField("Value", {}, "Hint") + LoginPasswordTextField("", {}, "Password") + LoginPasswordTextField("Value", {}, "Password") } } diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/Directory.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/Directory.kt new file mode 100644 index 00000000..166902ac --- /dev/null +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/Directory.kt @@ -0,0 +1,31 @@ +package com.kevinschildhorn.fotopresenter.data + +import com.kevinschildhorn.fotopresenter.data.network.NetworkDirectoryDetails +import com.kevinschildhorn.fotopresenter.ui.SharedImage + +interface Directory { + val details: NetworkDirectoryDetails + + val name: String + get() = details.name + + val id: Int + get() = details.id +} + +data class FolderDirectory( + override val details: NetworkDirectoryDetails, +) : Directory + +data class ImageDirectory( + override val details: NetworkDirectoryDetails, + val image: SharedImage? = null, +) : Directory + +data class DirectoryContents( + val folders: List = emptyList(), + val images: List = emptyList(), +) { + val allDirectories: List + get() = folders + images +} diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/DirectoryContents.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/DirectoryContents.kt deleted file mode 100644 index 8d5db8ae..00000000 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/DirectoryContents.kt +++ /dev/null @@ -1,28 +0,0 @@ -package com.kevinschildhorn.fotopresenter.data - -import com.kevinschildhorn.fotopresenter.data.network.NetworkDirectory -import com.kevinschildhorn.fotopresenter.ui.SharedImage - -interface DirectoryContent { - val directory: NetworkDirectory - - val asImageDirectory: ImageDirectoryContent? - get() = this as? ImageDirectoryContent -} - -data class FolderDirectoryContent( - override val directory: NetworkDirectory, -) : DirectoryContent - -data class ImageDirectoryContent( - override val directory: NetworkDirectory, - val image: SharedImage? = null, -) : DirectoryContent - -data class DirectoryContents( - val folders: List = emptyList(), - val images: List = emptyList(), -) { - val allDirectories: List - get() = folders + images -} diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/state/State.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/State.kt similarity index 95% rename from shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/state/State.kt rename to shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/State.kt index d608adef..96e86cc5 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/state/State.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/State.kt @@ -1,4 +1,4 @@ -package com.kevinschildhorn.fotopresenter.ui.state +package com.kevinschildhorn.fotopresenter.data import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/DirectoryDataSource.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/DirectoryDataSource.kt index cd817201..8efca7d5 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/DirectoryDataSource.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/DirectoryDataSource.kt @@ -1,6 +1,6 @@ package com.kevinschildhorn.fotopresenter.data.datasources -import com.kevinschildhorn.fotopresenter.data.network.NetworkDirectory +import com.kevinschildhorn.fotopresenter.data.network.NetworkDirectoryDetails import com.kevinschildhorn.fotopresenter.data.network.NetworkHandler import com.kevinschildhorn.fotopresenter.data.network.NetworkHandlerError import com.kevinschildhorn.fotopresenter.data.network.NetworkHandlerException @@ -18,14 +18,14 @@ class DirectoryDataSource(private val networkHandler: NetworkHandler) { throw NetworkHandlerException(NetworkHandlerError.DIRECTORY_NOT_FOUND) } - suspend fun getFolderDirectories(path: String): List { + suspend fun getFolderDirectories(path: String): List { if (!networkHandler.isConnected) throw NetworkHandlerException(NetworkHandlerError.NOT_CONNECTED) return networkHandler.getDirectoryContents(path).filter { it.fileName != "." }.filter { it.isDirectory } } - suspend fun getImageDirectories(path: String): List { + suspend fun getImageDirectories(path: String): List { if (!networkHandler.isConnected) throw NetworkHandlerException(NetworkHandlerError.NOT_CONNECTED) return networkHandler.getDirectoryContents(path).filter { it.fileName != "." diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/ImageRemoteDataSource.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/ImageRemoteDataSource.kt index 320deded..9a2418aa 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/ImageRemoteDataSource.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/ImageRemoteDataSource.kt @@ -1,6 +1,6 @@ package com.kevinschildhorn.fotopresenter.data.datasources -import com.kevinschildhorn.fotopresenter.data.network.NetworkDirectory +import com.kevinschildhorn.fotopresenter.data.network.NetworkDirectoryDetails import com.kevinschildhorn.fotopresenter.data.network.NetworkHandler import com.kevinschildhorn.fotopresenter.data.network.NetworkHandlerError import com.kevinschildhorn.fotopresenter.data.network.NetworkHandlerException @@ -12,7 +12,7 @@ Fetches Photos from a NAS **/ class ImageRemoteDataSource(private val networkHandler: NetworkHandler) { @Throws(NetworkHandlerException::class, CancellationException::class) - suspend fun getImage(directory: NetworkDirectory): SharedImage? { + suspend fun getImage(directory: NetworkDirectoryDetails): SharedImage? { if (!networkHandler.isConnected) throw NetworkHandlerException(NetworkHandlerError.NOT_CONNECTED) return networkHandler.openImage(directory.fullPath) } diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/network/NetworkDirectory.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/network/NetworkDirectoryDetails.kt similarity index 87% rename from shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/network/NetworkDirectory.kt rename to shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/network/NetworkDirectoryDetails.kt index be6636fa..45796551 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/network/NetworkDirectory.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/network/NetworkDirectoryDetails.kt @@ -1,6 +1,6 @@ package com.kevinschildhorn.fotopresenter.data.network -interface NetworkDirectory { +interface NetworkDirectoryDetails { val fullPath: String val id: Int @@ -23,7 +23,7 @@ interface NetworkDirectory { fileExtension == "bmp" } -class MockNetworkDirectory( +class MockNetworkDirectoryDetails( override val fullPath: String, override val id: Int, -) : NetworkDirectory +) : NetworkDirectoryDetails diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/network/NetworkHandler.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/network/NetworkHandler.kt index 9e28187e..17afa110 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/network/NetworkHandler.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/network/NetworkHandler.kt @@ -10,7 +10,7 @@ interface NetworkHandler { suspend fun disconnect() - suspend fun getDirectoryContents(path: String): List + suspend fun getDirectoryContents(path: String): List suspend fun openDirectory(path: String): String? diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/repositories/DirectoryRepository.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/repositories/DirectoryRepository.kt index 14837333..f84b3440 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/repositories/DirectoryRepository.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/repositories/DirectoryRepository.kt @@ -1,21 +1,21 @@ package com.kevinschildhorn.fotopresenter.data.repositories import com.kevinschildhorn.fotopresenter.data.DirectoryContents -import com.kevinschildhorn.fotopresenter.data.FolderDirectoryContent -import com.kevinschildhorn.fotopresenter.data.ImageDirectoryContent +import com.kevinschildhorn.fotopresenter.data.FolderDirectory +import com.kevinschildhorn.fotopresenter.data.ImageDirectory import com.kevinschildhorn.fotopresenter.data.datasources.DirectoryDataSource -import com.kevinschildhorn.fotopresenter.data.network.NetworkDirectory +import com.kevinschildhorn.fotopresenter.data.network.NetworkDirectoryDetails class DirectoryRepository( private val dataSource: DirectoryDataSource, ) { suspend fun getDirectoryContents(path: String): DirectoryContents { - val folderDirectories: List = dataSource.getFolderDirectories(path) - val imageDirectories: List = dataSource.getImageDirectories(path) + val folderDirectories: List = dataSource.getFolderDirectories(path) + val imageDirectories: List = dataSource.getImageDirectories(path) return DirectoryContents( - folders = folderDirectories.map { FolderDirectoryContent(it) }, - images = imageDirectories.map { ImageDirectoryContent(it) }, + folders = folderDirectories.map { FolderDirectory(it) }, + images = imageDirectories.map { ImageDirectory(it) }, ) } } diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/repositories/ImageRepository.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/repositories/ImageRepository.kt index b50e7fad..91a71238 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/repositories/ImageRepository.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/repositories/ImageRepository.kt @@ -1,11 +1,11 @@ package com.kevinschildhorn.fotopresenter.data.repositories import com.kevinschildhorn.fotopresenter.data.datasources.ImageRemoteDataSource -import com.kevinschildhorn.fotopresenter.data.network.NetworkDirectory +import com.kevinschildhorn.fotopresenter.data.network.NetworkDirectoryDetails import com.kevinschildhorn.fotopresenter.ui.SharedImage class ImageRepository( private val remoteDataSource: ImageRemoteDataSource, ) { - suspend fun getImage(directory: NetworkDirectory): SharedImage? = remoteDataSource.getImage(directory) + suspend fun getImage(directory: NetworkDirectoryDetails): SharedImage? = remoteDataSource.getImage(directory) } diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/domain/RetrieveDirectoryContentsUseCase.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/domain/RetrieveDirectoryContentsUseCase.kt index 62e3ddec..87ec5c84 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/domain/RetrieveDirectoryContentsUseCase.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/domain/RetrieveDirectoryContentsUseCase.kt @@ -2,8 +2,8 @@ package com.kevinschildhorn.fotopresenter.domain import co.touchlab.kermit.Logger import com.kevinschildhorn.fotopresenter.data.DirectoryContents -import com.kevinschildhorn.fotopresenter.data.ImageDirectoryContent -import com.kevinschildhorn.fotopresenter.data.network.NetworkDirectory +import com.kevinschildhorn.fotopresenter.data.ImageDirectory +import com.kevinschildhorn.fotopresenter.data.network.NetworkDirectoryDetails import com.kevinschildhorn.fotopresenter.data.repositories.DirectoryRepository import com.kevinschildhorn.fotopresenter.data.repositories.ImageRepository import com.kevinschildhorn.fotopresenter.ui.SharedImage @@ -24,10 +24,10 @@ class RetrieveDirectoryContentsUseCase( } } -private suspend fun DirectoryContents.updateImages(block: suspend (NetworkDirectory) -> SharedImage?): DirectoryContents = +private suspend fun DirectoryContents.updateImages(block: suspend (NetworkDirectoryDetails) -> SharedImage?): DirectoryContents = this.copy( images = images.map { - ImageDirectoryContent(it.directory, image = block(it.directory)) + ImageDirectory(it.details, image = block(it.details)) }, ) diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/DirectoryScreen.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/DirectoryScreen.kt index 596d76cd..369c519c 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/DirectoryScreen.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/DirectoryScreen.kt @@ -9,7 +9,7 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier -import com.kevinschildhorn.fotopresenter.data.ImageDirectoryContent +import com.kevinschildhorn.fotopresenter.data.ImageDirectory import com.kevinschildhorn.fotopresenter.ui.atoms.Padding import com.kevinschildhorn.fotopresenter.ui.compose.directory.DirectoryGrid import com.kevinschildhorn.fotopresenter.ui.viewmodel.DirectoryViewModel @@ -17,13 +17,13 @@ import com.kevinschildhorn.fotopresenter.ui.viewmodel.DirectoryViewModel @Composable fun DirectoryScreen( viewModel: DirectoryViewModel, - onImageSelected: (ImageDirectoryContent) -> Unit, + onImageSelected: (ImageDirectory) -> Unit, ) { LaunchedEffect(Unit) { viewModel.refreshScreen() } val uiState by viewModel.uiState.collectAsState() - var imageState: ImageDirectoryContent? by remember { mutableStateOf(null) } + var imageState: ImageDirectory? by remember { mutableStateOf(null) } uiState.state.asComposable( modifier = Modifier.padding( diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/ImagePreviewOverlay.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/ImagePreviewOverlay.kt index 3788347a..c8c5607c 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/ImagePreviewOverlay.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/ImagePreviewOverlay.kt @@ -16,19 +16,18 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import com.kevinschildhorn.atomik.color.base.composeColor -import com.kevinschildhorn.fotopresenter.data.ImageDirectoryContent +import com.kevinschildhorn.fotopresenter.data.ImageDirectory import com.kevinschildhorn.fotopresenter.ui.atoms.FotoColors import com.kevinschildhorn.fotopresenter.ui.atoms.Padding import com.kevinschildhorn.fotopresenter.ui.compose.common.Overlay -import com.kevinschildhorn.fotopresenter.ui.state.State +import com.kevinschildhorn.fotopresenter.data.State import com.kevinschildhorn.fotopresenter.ui.viewmodel.PhotoDirectoryViewModel @Composable fun ImagePreviewOverlay( - imageContent: ImageDirectoryContent, + imageContent: ImageDirectory, viewModel: PhotoDirectoryViewModel = PhotoDirectoryViewModel(imageContent.image), onDismiss: () -> Unit, ) { diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/NavigationState.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/Screen.kt similarity index 61% rename from shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/NavigationState.kt rename to shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/Screen.kt index 726f329e..dafddcdc 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/NavigationState.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/Screen.kt @@ -1,9 +1,5 @@ package com.kevinschildhorn.fotopresenter.ui.compose -class NavigationState { - val screen: Screen = Screen.LOGIN -} - enum class Screen { LOGIN, DIRECTORY, diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/directory/DirectoryGrid.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/directory/DirectoryGrid.kt index ddfdddac..1f680550 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/directory/DirectoryGrid.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/directory/DirectoryGrid.kt @@ -17,20 +17,18 @@ import androidx.compose.ui.hapticfeedback.HapticFeedbackType import androidx.compose.ui.platform.LocalHapticFeedback import androidx.compose.ui.unit.dp import androidx.compose.ui.zIndex -import com.kevinschildhorn.fotopresenter.data.DirectoryContent -import com.kevinschildhorn.fotopresenter.data.DirectoryContents -import com.kevinschildhorn.fotopresenter.data.FolderDirectoryContent -import com.kevinschildhorn.fotopresenter.data.ImageDirectoryContent -import com.kevinschildhorn.fotopresenter.data.network.NetworkDirectory import com.kevinschildhorn.fotopresenter.ui.compose.common.ActionSheet +import com.kevinschildhorn.fotopresenter.ui.state.DirectoryGridState +import com.kevinschildhorn.fotopresenter.ui.state.FolderDirectoryGridCellState +import com.kevinschildhorn.fotopresenter.ui.state.ImageDirectoryGridCellState @OptIn(ExperimentalFoundationApi::class) @Composable fun DirectoryGrid( - directoryContent: DirectoryContents, + directoryContent: DirectoryGridState, gridSize: Int = 5, modifier: Modifier = Modifier, - onDirectoryPressed: (DirectoryContent) -> Unit, + onDirectoryPressed: (Int) -> Unit, ) { var actionSheetVisible by remember { mutableStateOf(false) } var contextMenuPhotoId by rememberSaveable { mutableStateOf(null) } @@ -40,29 +38,29 @@ fun DirectoryGrid( columns = GridCells.Fixed(gridSize), modifier = modifier.zIndex(0f), ) { - items(directoryContent.allDirectories, { it.directory.id }) { content -> + items(directoryContent.allStates, { it.id }) { state -> val directoryItemModifier = Modifier .padding(5.dp) .combinedClickable( onClick = { - onDirectoryPressed(content) + onDirectoryPressed(state.id) }, onLongClick = { haptics.performHapticFeedback(HapticFeedbackType.LongPress) - contextMenuPhotoId = content.directory.id + contextMenuPhotoId = state.id actionSheetVisible = true }, onLongClickLabel = "Action Sheet", ) - (content as? FolderDirectoryContent)?.let { folderContent -> - FolderDirectoryItem( - folderContent.directory.name, + (state as? FolderDirectoryGridCellState)?.let { folderContent -> + FolderDirectoryGridCell( + folderContent, modifier = directoryItemModifier, ) } - (content as? ImageDirectoryContent)?.let { imageContent -> - PhotoDirectoryItem( + (state as? ImageDirectoryGridCellState)?.let { imageContent -> + ImageDirectoryGridCell( imageContent, modifier = directoryItemModifier, ) diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/directory/BaseDirectory.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/directory/DirectoryGridCell.kt similarity index 97% rename from shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/directory/BaseDirectory.kt rename to shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/directory/DirectoryGridCell.kt index bf9b4f8c..77856eec 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/directory/BaseDirectory.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/directory/DirectoryGridCell.kt @@ -19,7 +19,7 @@ import com.kevinschildhorn.fotopresenter.ui.atoms.DirectoryAtoms import com.kevinschildhorn.fotopresenter.ui.atoms.FotoColors @Composable -fun BaseDirectory( +fun DirectoryGridCell( modifier: Modifier = Modifier, backgroundColor: Color = FotoColors.surface.composeColor, content: @Composable BoxScope.() -> Unit, @@ -35,7 +35,7 @@ fun BaseDirectory( } @Composable -fun DirectoryText( +fun DirectoryGridCellText( text: String, modifier: Modifier = Modifier, ) { diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/directory/FolderDirectoryItem.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/directory/FolderDirectoryGridCell.kt similarity index 84% rename from shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/directory/FolderDirectoryItem.kt rename to shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/directory/FolderDirectoryGridCell.kt index 674194dd..189d756d 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/directory/FolderDirectoryItem.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/directory/FolderDirectoryGridCell.kt @@ -12,15 +12,16 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import com.kevinschildhorn.atomik.color.base.composeColor import com.kevinschildhorn.fotopresenter.ui.atoms.DirectoryAtoms +import com.kevinschildhorn.fotopresenter.ui.state.FolderDirectoryGridCellState @Composable -fun FolderDirectoryItem( - folderName: String, +fun FolderDirectoryGridCell( + folderState: FolderDirectoryGridCellState, modifier: Modifier = Modifier, ) { val molecule: DirectoryAtoms.EmptyPhotoMolecule = DirectoryAtoms.emptyDirectory - BaseDirectory(modifier) { + DirectoryGridCell(modifier) { Column( modifier = Modifier @@ -36,8 +37,8 @@ fun FolderDirectoryItem( .fillMaxHeight(0.66f), tint = molecule.imageAtom.color.composeColor, ) - DirectoryText( - folderName, + DirectoryGridCellText( + folderState.name, modifier = Modifier.align(Alignment.CenterHorizontally), ) } diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/directory/PhotoDirectoryItem.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/directory/ImageDirectoryGridCell.kt similarity index 68% rename from shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/directory/PhotoDirectoryItem.kt rename to shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/directory/ImageDirectoryGridCell.kt index b9a2b648..5831c50b 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/directory/PhotoDirectoryItem.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/directory/ImageDirectoryGridCell.kt @@ -8,37 +8,26 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width import androidx.compose.material.CircularProgressIndicator import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import com.kevinschildhorn.atomik.color.base.composeColor -import com.kevinschildhorn.fotopresenter.data.ImageDirectoryContent import com.kevinschildhorn.fotopresenter.ui.atoms.FotoColors -import com.kevinschildhorn.fotopresenter.ui.state.State -import com.kevinschildhorn.fotopresenter.ui.viewmodel.PhotoDirectoryViewModel +import com.kevinschildhorn.fotopresenter.ui.state.ImageDirectoryGridCellState import compose.icons.EvaIcons import compose.icons.evaicons.Fill import compose.icons.evaicons.fill.QuestionMark @Composable -fun PhotoDirectoryItem( - imageContent: ImageDirectoryContent, +fun ImageDirectoryGridCell( + imageContent: ImageDirectoryGridCellState, modifier: Modifier = Modifier, - viewModel: PhotoDirectoryViewModel = PhotoDirectoryViewModel(imageContent.image), ) { - val imageState by viewModel.imageState.collectAsState(State.IDLE) - - LaunchedEffect(Unit) { - viewModel.refreshImageBitmap(200) - } - BaseDirectory(modifier) { - imageState.onSuccess { + DirectoryGridCell(modifier) { + imageContent.imageState.onSuccess { Image( bitmap = it, - contentDescription = "Image", + contentDescription = imageContent.name, modifier = Modifier.fillMaxSize().background(FotoColors.surface.composeColor), ) }.onError { @@ -53,8 +42,8 @@ fun PhotoDirectoryItem( contentDescription = "Question Mark", modifier = Modifier.align(Alignment.CenterHorizontally), ) - DirectoryText( - imageContent.directory.name, + DirectoryGridCellText( + imageContent.name, modifier = Modifier.align(Alignment.CenterHorizontally), ) } diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/login/FotoCheckbox.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/login/LoginCheckbox.kt similarity index 97% rename from shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/login/FotoCheckbox.kt rename to shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/login/LoginCheckbox.kt index a3c32004..f56f4d11 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/login/FotoCheckbox.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/login/LoginCheckbox.kt @@ -10,7 +10,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @Composable -fun FotoCheckbox( +fun LoginCheckbox( title: String, checked: Boolean, onCheckedChange: (Boolean) -> Unit, diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/login/FotoTextField.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/login/LoginPasswordTextField.kt similarity index 63% rename from shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/login/FotoTextField.kt rename to shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/login/LoginPasswordTextField.kt index 0ae01118..b58bac73 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/login/FotoTextField.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/login/LoginPasswordTextField.kt @@ -9,32 +9,9 @@ import com.kevinschildhorn.atomik.atomic.atoms.shape import com.kevinschildhorn.atomik.atomic.atoms.textStyle import com.kevinschildhorn.fotopresenter.ui.atoms.LoginScreenAtoms -@Composable -fun FotoTextField( - value: String, - onValueChange: (String) -> Unit, - placeholder: String, - modifier: Modifier = Modifier, -) { - val molecule = LoginScreenAtoms.textFieldMolecule - OutlinedTextField( - value = value, - onValueChange = onValueChange, - placeholder = { - Text( - placeholder, - style = molecule.hintTextAtom?.textStyle ?: molecule.textAtom.textStyle, - ) - }, - colors = molecule.colors(), - shape = molecule.shape, - textStyle = molecule.textAtom.textStyle, - modifier = modifier, - ) -} @Composable -fun FotoPasswordTextField( +fun LoginPasswordTextField( value: String, onValueChange: (String) -> Unit, placeholder: String, diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/login/LoginScreenForm.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/login/LoginScreenForm.kt index 76c5d7fc..842cff71 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/login/LoginScreenForm.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/login/LoginScreenForm.kt @@ -12,7 +12,7 @@ import com.kevinschildhorn.fotopresenter.ui.compose.common.ErrorView import com.kevinschildhorn.fotopresenter.ui.compose.common.FormColumn import com.kevinschildhorn.fotopresenter.ui.compose.common.PrimaryButton import com.kevinschildhorn.fotopresenter.ui.state.LoginScreenState -import com.kevinschildhorn.fotopresenter.ui.state.State +import com.kevinschildhorn.fotopresenter.data.State @Composable fun LoginScreenForm( @@ -34,25 +34,25 @@ fun LoginScreenForm( FormColumn( verticalPadding = Padding.STANDARD, ) { - FotoTextField( + LoginTextField( value = uiState.hostname, onValueChange = onHostnameChange, placeholder = "HostName*", modifier = Modifier.fillMaxWidth(), ) - FotoTextField( + LoginTextField( value = uiState.username, onValueChange = onUsernameChange, placeholder = "Username".required(), modifier = Modifier.fillMaxWidth(), ) - FotoPasswordTextField( + LoginPasswordTextField( value = uiState.password, onValueChange = onPasswordChange, placeholder = "Password".required(), modifier = Modifier.fillMaxWidth(), ) - FotoTextField( + LoginTextField( value = uiState.sharedFolder, onValueChange = onSharedFolderChange, placeholder = "Shared Folder".required(), @@ -62,7 +62,7 @@ fun LoginScreenForm( FormColumn( verticalPadding = Padding.NONE, ) { - FotoCheckbox( + LoginCheckbox( title = "Should autoConnect", checked = uiState.shouldAutoConnect, onCheckedChange = onShouldAutoConnectChange, diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/login/LoginTextField.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/login/LoginTextField.kt new file mode 100644 index 00000000..8fc4558c --- /dev/null +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/login/LoginTextField.kt @@ -0,0 +1,33 @@ +package com.kevinschildhorn.fotopresenter.ui.compose.login + +import androidx.compose.material.OutlinedTextField +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.kevinschildhorn.atomik.atomic.atoms.shape +import com.kevinschildhorn.atomik.atomic.atoms.textStyle +import com.kevinschildhorn.fotopresenter.ui.atoms.LoginScreenAtoms + +@Composable +fun LoginTextField( + value: String, + onValueChange: (String) -> Unit, + placeholder: String, + modifier: Modifier = Modifier, +) { + val molecule = LoginScreenAtoms.textFieldMolecule + OutlinedTextField( + value = value, + onValueChange = onValueChange, + placeholder = { + Text( + placeholder, + style = molecule.hintTextAtom?.textStyle ?: molecule.textAtom.textStyle, + ) + }, + colors = molecule.colors(), + shape = molecule.shape, + textStyle = molecule.textAtom.textStyle, + modifier = modifier, + ) +} \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/state/DirectoryScreenState.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/state/DirectoryScreenState.kt index 6019c869..d735ff20 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/state/DirectoryScreenState.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/state/DirectoryScreenState.kt @@ -1,9 +1,35 @@ package com.kevinschildhorn.fotopresenter.ui.state -import com.kevinschildhorn.fotopresenter.data.DirectoryContents +import androidx.compose.ui.graphics.ImageBitmap +import com.kevinschildhorn.fotopresenter.data.State data class DirectoryScreenState( val currentPath: String = "", - val directoryContents: DirectoryContents = DirectoryContents(emptyList(), emptyList()), + val directoryGridState: DirectoryGridState = DirectoryGridState(emptyList(), emptyList()), override val state: UiState = UiState.IDLE, ) : ScreenState + +data class DirectoryGridState( + val folderStates: List, + val imageStates: List, +) { + val allStates: List + get() = folderStates + imageStates +} + +data class FolderDirectoryGridCellState( + override val name: String, + override val id: Int, +):DirectoryGridCellState + +data class ImageDirectoryGridCellState( + val imageState: State, + override val name: String, + override val id: Int, +):DirectoryGridCellState + + +interface DirectoryGridCellState { + val name: String + val id: Int +} \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/viewmodel/DirectoryViewModel.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/viewmodel/DirectoryViewModel.kt index 9508b6d7..d4516530 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/viewmodel/DirectoryViewModel.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/viewmodel/DirectoryViewModel.kt @@ -1,12 +1,16 @@ package com.kevinschildhorn.fotopresenter.ui.viewmodel import co.touchlab.kermit.Logger -import com.kevinschildhorn.fotopresenter.data.network.NetworkDirectory +import com.kevinschildhorn.fotopresenter.data.DirectoryContents +import com.kevinschildhorn.fotopresenter.data.network.NetworkDirectoryDetails import com.kevinschildhorn.fotopresenter.data.network.NetworkHandlerException import com.kevinschildhorn.fotopresenter.domain.ChangeDirectoryUseCase import com.kevinschildhorn.fotopresenter.domain.RetrieveDirectoryContentsUseCase import com.kevinschildhorn.fotopresenter.extension.addPath +import com.kevinschildhorn.fotopresenter.ui.state.DirectoryGridState import com.kevinschildhorn.fotopresenter.ui.state.DirectoryScreenState +import com.kevinschildhorn.fotopresenter.ui.state.FolderDirectoryGridCellState +import com.kevinschildhorn.fotopresenter.ui.state.ImageDirectoryGridCellState import com.kevinschildhorn.fotopresenter.ui.state.UiState import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.MutableStateFlow @@ -16,13 +20,17 @@ import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import org.koin.core.component.KoinComponent import org.koin.core.component.inject +import com.kevinschildhorn.fotopresenter.data.State class DirectoryViewModel( private val logger: Logger, ) : ViewModel(), KoinComponent { + private val _uiState = MutableStateFlow(DirectoryScreenState()) val uiState: StateFlow = _uiState.asStateFlow() + private val _directoryContentsState = MutableStateFlow(DirectoryContents()) + private val currentPath: String get() = uiState.value.currentPath @@ -30,29 +38,34 @@ class DirectoryViewModel( updateDirectories() } - fun changeDirectory(directory: NetworkDirectory) { + fun changeDirectory(directory: NetworkDirectoryDetails) { + logger.i { "Changing Directory: ${directory.name}" } viewModelScope.launch(Dispatchers.Default) { val changeDirectoryUseCase: ChangeDirectoryUseCase by inject() try { + logger.i { "Getting New Path" } val newPath = changeDirectoryUseCase(currentPath.addPath(directory.name)) + logger.i { "New Path got: $newPath" } _uiState.update { it.copy(currentPath = newPath) } updateDirectories() } catch (e: NetworkHandlerException) { + logger.e(e) { "Error Occurred Getting new path" } _uiState.update { it.copy( state = - UiState.ERROR( - e.message ?: "An Unknown Network Error Occurred", - ), + UiState.ERROR( + e.message ?: "An Unknown Network Error Occurred", + ), ) } } catch (e: Exception) { + logger.e(e) { "Something went wrong" } _uiState.update { it.copy( state = - UiState.ERROR( - e.message ?: "Something Went Wrong", - ), + UiState.ERROR( + e.message ?: "Something Went Wrong", + ), ) } } @@ -60,16 +73,33 @@ class DirectoryViewModel( } private fun updateDirectories() { + logger.i { "Updating Directories" } _uiState.update { it.copy(state = UiState.LOADING) } viewModelScope.launch(Dispatchers.Default) { val retrieveDirectoryUseCase: RetrieveDirectoryContentsUseCase by inject() + logger.i { "Getting Directory Contents" } val directoryContents = retrieveDirectoryUseCase(currentPath) + logger.i { "Got Directory Contents: ${directoryContents.allDirectories.count()}" } + _directoryContentsState.update { directoryContents } _uiState.update { it.copy( - directoryContents = directoryContents, + directoryGridState = directoryContents.asDirectoryGridState, state = UiState.SUCCESS, ) } } } + + private val DirectoryContents.asDirectoryGridState: DirectoryGridState + get() = + DirectoryGridState( + folderStates = this.folders.map { FolderDirectoryGridCellState(it.name, it.id) }, + imageStates = this.images.map { + ImageDirectoryGridCellState( + State.IDLE, + it.name, + it.id + ) + } + ) } diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/viewmodel/PhotoDirectoryViewModel.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/viewmodel/PhotoDirectoryViewModel.kt index c5b9ab64..25c98431 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/viewmodel/PhotoDirectoryViewModel.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/viewmodel/PhotoDirectoryViewModel.kt @@ -2,7 +2,7 @@ package com.kevinschildhorn.fotopresenter.ui.viewmodel import androidx.compose.ui.graphics.ImageBitmap import com.kevinschildhorn.fotopresenter.ui.SharedImage -import com.kevinschildhorn.fotopresenter.ui.state.State +import com.kevinschildhorn.fotopresenter.data.State import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow diff --git a/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/ImageRemoteDataSourceTest.kt b/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/ImageRemoteDataSourceTest.kt index 5037a71f..8d738651 100644 --- a/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/ImageRemoteDataSourceTest.kt +++ b/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/ImageRemoteDataSourceTest.kt @@ -1,6 +1,6 @@ package com.kevinschildhorn.fotopresenter.data.datasources -import com.kevinschildhorn.fotopresenter.data.network.MockNetworkDirectory +import com.kevinschildhorn.fotopresenter.data.network.MockNetworkDirectoryDetails import com.kevinschildhorn.fotopresenter.data.network.MockNetworkHandler import com.kevinschildhorn.fotopresenter.data.network.NetworkHandlerError import com.kevinschildhorn.fotopresenter.data.network.NetworkHandlerException @@ -35,7 +35,7 @@ class ImageRemoteDataSourceTest { fun `get Image Success`() = runBlocking { val networkDirectory = - MockNetworkDirectory( + MockNetworkDirectoryDetails( fullPath = "Photos/Peeng.png", id = 1, ) @@ -50,7 +50,7 @@ class ImageRemoteDataSourceTest { fun `get Image Failure`() = runBlocking { val networkDirectory = - MockNetworkDirectory( + MockNetworkDirectoryDetails( fullPath = "Photos/nonExistant.png", id = 1, ) @@ -63,7 +63,7 @@ class ImageRemoteDataSourceTest { runBlocking { networkHandler.disconnect() try { - val image = dataSource.getImage(MockNetworkDirectory("", 1)) + val image = dataSource.getImage(MockNetworkDirectoryDetails("", 1)) fail("Should have thrown exception") } catch (e: NetworkHandlerException) { assertEquals(e.message, NetworkHandlerError.NOT_CONNECTED.message) diff --git a/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/data/network/MockNetworkHandler.kt b/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/data/network/MockNetworkHandler.kt index afb96bea..b08e304e 100644 --- a/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/data/network/MockNetworkHandler.kt +++ b/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/data/network/MockNetworkHandler.kt @@ -16,22 +16,22 @@ object MockNetworkHandler : NetworkHandler { private val networkContents = mapOf( "" to - listOf( - MockNetworkDirectory(fullPath = "NewDirectory", id = 1), - MockNetworkDirectory(fullPath = "Peeng.png", id = 2), - MockNetworkDirectory(fullPath = "Jaypeg.jpg", id = 3), - MockNetworkDirectory(fullPath = "textFile.txt", id = 4), + listOf( + MockNetworkDirectoryDetails(fullPath = "NewDirectory", id = 1), + MockNetworkDirectoryDetails(fullPath = "Peeng.png", id = 2), + MockNetworkDirectoryDetails(fullPath = "Jaypeg.jpg", id = 3), + MockNetworkDirectoryDetails(fullPath = "textFile.txt", id = 4), ), "Directories" to - listOf( - MockNetworkDirectory(fullPath = "Directories/NewDirectory", id = 1), - MockNetworkDirectory(fullPath = "Directories/NewDirectory2", id = 2), + listOf( + MockNetworkDirectoryDetails(fullPath = "Directories/NewDirectory", id = 1), + MockNetworkDirectoryDetails(fullPath = "Directories/NewDirectory2", id = 2), ), "Photos" to - listOf( - MockNetworkDirectory(fullPath = "Photos/Peeng.png", id = 2), - MockNetworkDirectory(fullPath = "Photos/Jaypeg.jpg", id = 3), - MockNetworkDirectory(fullPath = "Photos/textFile.txt", id = 4), + listOf( + MockNetworkDirectoryDetails(fullPath = "Photos/Peeng.png", id = 2), + MockNetworkDirectoryDetails(fullPath = "Photos/Jaypeg.jpg", id = 3), + MockNetworkDirectoryDetails(fullPath = "Photos/textFile.txt", id = 4), ), ) @@ -60,7 +60,7 @@ object MockNetworkHandler : NetworkHandler { connected = false } - override suspend fun getDirectoryContents(path: String): List { + override suspend fun getDirectoryContents(path: String): List { return networkContents[path] ?: emptyList() } diff --git a/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/data/repositories/ImageRepositoryTest.kt b/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/data/repositories/ImageRepositoryTest.kt index 24fe458a..02859e9d 100644 --- a/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/data/repositories/ImageRepositoryTest.kt +++ b/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/data/repositories/ImageRepositoryTest.kt @@ -1,6 +1,6 @@ package com.kevinschildhorn.fotopresenter.data.repositories -import com.kevinschildhorn.fotopresenter.data.network.MockNetworkDirectory +import com.kevinschildhorn.fotopresenter.data.network.MockNetworkDirectoryDetails import com.kevinschildhorn.fotopresenter.data.network.MockNetworkHandler import com.kevinschildhorn.fotopresenter.data.network.NetworkHandlerError import com.kevinschildhorn.fotopresenter.data.network.NetworkHandlerException @@ -46,7 +46,7 @@ class ImageRepositoryTest : KoinTest { try { val result = repository.getImage( - MockNetworkDirectory( + MockNetworkDirectoryDetails( fullPath = "Photos/Peeng.png", id = 1, ), @@ -61,7 +61,7 @@ class ImageRepositoryTest : KoinTest { runBlocking { val result = repository.getImage( - MockNetworkDirectory( + MockNetworkDirectoryDetails( fullPath = "Photos/nonExistant.png", id = 1, ), @@ -76,7 +76,7 @@ class ImageRepositoryTest : KoinTest { try { val result = repository.getImage( - MockNetworkDirectory( + MockNetworkDirectoryDetails( fullPath = "Photos/nonExistant.png", id = 1, ), diff --git a/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/domain/RetrieveDirectoryContentsUseCaseTest.kt b/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/domain/RetrieveDirectoryContentsUseCaseTest.kt index cbd54077..5b0f40aa 100644 --- a/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/domain/RetrieveDirectoryContentsUseCaseTest.kt +++ b/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/domain/RetrieveDirectoryContentsUseCaseTest.kt @@ -42,8 +42,8 @@ class RetrieveDirectoryContentsUseCaseTest : KoinTest { fun `receive directory content success`() = runBlocking { val result = useCase("") - assertTrue(result.images.first().directory.isAnImage) - assertTrue(result.folders.first().directory.isDirectory) + assertTrue(result.images.first().details.isAnImage) + assertTrue(result.folders.first().details.isDirectory) assertEquals(1, result.folders.count()) assertEquals(2, result.images.count()) assertEquals(3, result.allDirectories.count()) diff --git a/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/data/network/SMBJHandler.kt b/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/data/network/SMBJHandler.kt index 9762835f..50c3ab6a 100644 --- a/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/data/network/SMBJHandler.kt +++ b/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/data/network/SMBJHandler.kt @@ -49,9 +49,9 @@ object SMBJHandler : NetworkHandler { return true } - override suspend fun getDirectoryContents(path: String): List { + override suspend fun getDirectoryContents(path: String): List { return share?.list(path)?.map { - SMBJNetworkDirectory( + SMBJNetworkDirectoryDetails( it, fullPath = path.addPath(it.fileName), ) diff --git a/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/data/network/SMBJNetworkDirectory.kt b/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/data/network/SMBJNetworkDirectoryDetails.kt similarity index 80% rename from shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/data/network/SMBJNetworkDirectory.kt rename to shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/data/network/SMBJNetworkDirectoryDetails.kt index 33254181..a5a50bed 100644 --- a/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/data/network/SMBJNetworkDirectory.kt +++ b/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/data/network/SMBJNetworkDirectoryDetails.kt @@ -2,9 +2,9 @@ package com.kevinschildhorn.fotopresenter.data.network import com.hierynomus.msfscc.fileinformation.FileIdBothDirectoryInformation -class SMBJNetworkDirectory( +class SMBJNetworkDirectoryDetails( information: FileIdBothDirectoryInformation, override val fullPath: String, -) : NetworkDirectory { +) : NetworkDirectoryDetails { override val id: Int = information.fileId.toInt() } From 09d3ad0b5451d2c7958f3ce5c1119776587772ed Mon Sep 17 00:00:00 2001 From: Kevin Schildhorn Date: Thu, 7 Dec 2023 14:40:17 -0500 Subject: [PATCH 3/5] Moving code around --- .../ui/compose/DirectoryPreviews.kt | 25 ++++++------ .../SharedImageAndroid.kt} | 10 +++-- shared/src/commonMain/kotlin/App.kt | 3 +- .../fotopresenter/data/Directory.kt | 6 +-- .../data/datasources/ImageRemoteDataSource.kt | 2 +- .../data/network/NetworkHandler.kt | 2 +- .../data/repositories/ImageRepository.kt | 2 +- .../RetrieveDirectoryContentsUseCase.kt | 8 ++-- .../fotopresenter/ui/SharedImage.kt | 7 ---- .../ui/compose/DirectoryScreen.kt | 27 ++++++------- .../ui/compose/ImagePreviewOverlay.kt | 9 +---- .../ui/compose/directory/DirectoryGrid.kt | 11 +++++- .../directory/ImageDirectoryGridCell.kt | 2 + .../fotopresenter/ui/shared/SharedImage.kt | 22 +++++++++++ .../ui/state/DirectoryScreenState.kt | 32 ++++++++++++++-- .../ui/viewmodel/DirectoryViewModel.kt | 38 ++++++++++++++++++- .../ui/viewmodel/PhotoDirectoryViewModel.kt | 2 +- .../data/network/MockNetworkHandler.kt | 2 +- .../ui/{ => shared}/SharedImage.kt | 2 +- .../ui/{ => shared}/SharedImage.kt | 0 .../fotopresenter/data/network/SMBJHandler.kt | 2 +- .../fotopresenter/ui/SharedImage.kt | 1 + 22 files changed, 149 insertions(+), 66 deletions(-) rename shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/{SharedImage.kt => shared/SharedImageAndroid.kt} (50%) delete mode 100644 shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/SharedImage.kt create mode 100644 shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt rename shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/ui/{ => shared}/SharedImage.kt (83%) rename shared/src/iosMain/kotlin/com/kevinschildhorn/fotopresenter/ui/{ => shared}/SharedImage.kt (100%) diff --git a/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/DirectoryPreviews.kt b/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/DirectoryPreviews.kt index 045e0dba..21a2f908 100644 --- a/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/DirectoryPreviews.kt +++ b/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/DirectoryPreviews.kt @@ -5,10 +5,14 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.tooling.preview.Preview import com.kevinschildhorn.fotopresenter.data.DirectoryContents import com.kevinschildhorn.fotopresenter.data.FolderDirectory +import com.kevinschildhorn.fotopresenter.data.State import com.kevinschildhorn.fotopresenter.data.network.MockNetworkDirectoryDetails import com.kevinschildhorn.fotopresenter.ui.compose.directory.DirectoryGridCell import com.kevinschildhorn.fotopresenter.ui.compose.directory.DirectoryGrid import com.kevinschildhorn.fotopresenter.ui.compose.directory.FolderDirectoryGridCell +import com.kevinschildhorn.fotopresenter.ui.state.DirectoryGridState +import com.kevinschildhorn.fotopresenter.ui.state.FolderDirectoryGridCellState +import com.kevinschildhorn.fotopresenter.ui.state.ImageDirectoryGridCellState @Preview @Composable @@ -22,7 +26,7 @@ fun BaseDirectoryPreview() { @Composable fun FolderDirectoryEmptyPreview() { Column { - FolderDirectoryGridCell("Folder") + FolderDirectoryGridCell(FolderDirectoryGridCellState("Hello",0)) } } @@ -30,16 +34,15 @@ fun FolderDirectoryEmptyPreview() { @Composable fun DirectoryGridPreview() { DirectoryGrid( - DirectoryContents( - folders = listOf( - FolderDirectory(MockNetworkDirectoryDetails("Test 1", id = 1)), - FolderDirectory(MockNetworkDirectoryDetails("Test 2", id = 2)), - FolderDirectory(MockNetworkDirectoryDetails("Test 3", id = 3)), - FolderDirectory(MockNetworkDirectoryDetails("Test 4", id = 4)), - FolderDirectory(MockNetworkDirectoryDetails("Test 6", id = 5)), - FolderDirectory(MockNetworkDirectoryDetails("Test 5", id = 6)), + directoryContent = DirectoryGridState( + folderStates = listOf( + FolderDirectoryGridCellState("Hello",0), ), + imageStates = mutableListOf( + ImageDirectoryGridCellState(State.IDLE,"Hello", 1) + ) ), - ) { - } + onFolderPressed = {}, + onImageDirectoryPressed = {}, + ) } diff --git a/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/SharedImage.kt b/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImageAndroid.kt similarity index 50% rename from shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/SharedImage.kt rename to shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImageAndroid.kt index c9a2b84d..86a62a88 100644 --- a/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/SharedImage.kt +++ b/shared/src/androidMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImageAndroid.kt @@ -1,4 +1,4 @@ -package com.kevinschildhorn.fotopresenter.ui +package com.kevinschildhorn.fotopresenter.ui.shared import android.graphics.Bitmap import android.graphics.BitmapFactory @@ -6,11 +6,13 @@ import androidx.compose.ui.graphics.ImageBitmap import androidx.compose.ui.graphics.asImageBitmap import com.hierynomus.smbj.share.File -actual fun getBitmapFromFile(file: File, size:Int): ImageBitmap? { +actual fun getBitmapFromFile(file: File, size: Int): ImageBitmap? { val options = BitmapFactory.Options() - options.inSampleSize = 3 + options.inSampleSize = 2 BitmapFactory.decodeStream(file.inputStream, null, options)?.let { - return Bitmap.createScaledBitmap(it, size, size, false).asImageBitmap() + val dimensions = getScaledDimensions(it.width, it.height, size) + return Bitmap.createScaledBitmap(it, dimensions.first, dimensions.second, false) + .asImageBitmap() } return null diff --git a/shared/src/commonMain/kotlin/App.kt b/shared/src/commonMain/kotlin/App.kt index 9e00e155..b1dc0e05 100644 --- a/shared/src/commonMain/kotlin/App.kt +++ b/shared/src/commonMain/kotlin/App.kt @@ -22,8 +22,7 @@ fun App( LoginScreen(loginViewModel) { currentScreen.value = Screen.DIRECTORY } - Screen.DIRECTORY -> DirectoryScreen(directoryViewModel) { - } + Screen.DIRECTORY -> DirectoryScreen(directoryViewModel) } } } diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/Directory.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/Directory.kt index 166902ac..c13e1547 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/Directory.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/Directory.kt @@ -1,7 +1,7 @@ package com.kevinschildhorn.fotopresenter.data import com.kevinschildhorn.fotopresenter.data.network.NetworkDirectoryDetails -import com.kevinschildhorn.fotopresenter.ui.SharedImage +import com.kevinschildhorn.fotopresenter.ui.shared.SharedImage interface Directory { val details: NetworkDirectoryDetails @@ -23,8 +23,8 @@ data class ImageDirectory( ) : Directory data class DirectoryContents( - val folders: List = emptyList(), - val images: List = emptyList(), + val folders: List = emptyList(), + val images: List = emptyList(), ) { val allDirectories: List get() = folders + images diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/ImageRemoteDataSource.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/ImageRemoteDataSource.kt index 9a2418aa..e132203d 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/ImageRemoteDataSource.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/datasources/ImageRemoteDataSource.kt @@ -4,7 +4,7 @@ import com.kevinschildhorn.fotopresenter.data.network.NetworkDirectoryDetails import com.kevinschildhorn.fotopresenter.data.network.NetworkHandler import com.kevinschildhorn.fotopresenter.data.network.NetworkHandlerError import com.kevinschildhorn.fotopresenter.data.network.NetworkHandlerException -import com.kevinschildhorn.fotopresenter.ui.SharedImage +import com.kevinschildhorn.fotopresenter.ui.shared.SharedImage import kotlin.coroutines.cancellation.CancellationException /** diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/network/NetworkHandler.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/network/NetworkHandler.kt index 17afa110..df58dda5 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/network/NetworkHandler.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/network/NetworkHandler.kt @@ -1,7 +1,7 @@ package com.kevinschildhorn.fotopresenter.data.network import com.kevinschildhorn.fotopresenter.data.LoginCredentials -import com.kevinschildhorn.fotopresenter.ui.SharedImage +import com.kevinschildhorn.fotopresenter.ui.shared.SharedImage interface NetworkHandler { val isConnected: Boolean diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/repositories/ImageRepository.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/repositories/ImageRepository.kt index 91a71238..ddbc81b9 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/repositories/ImageRepository.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/repositories/ImageRepository.kt @@ -2,7 +2,7 @@ package com.kevinschildhorn.fotopresenter.data.repositories import com.kevinschildhorn.fotopresenter.data.datasources.ImageRemoteDataSource import com.kevinschildhorn.fotopresenter.data.network.NetworkDirectoryDetails -import com.kevinschildhorn.fotopresenter.ui.SharedImage +import com.kevinschildhorn.fotopresenter.ui.shared.SharedImage class ImageRepository( private val remoteDataSource: ImageRemoteDataSource, diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/domain/RetrieveDirectoryContentsUseCase.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/domain/RetrieveDirectoryContentsUseCase.kt index 87ec5c84..faf63d26 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/domain/RetrieveDirectoryContentsUseCase.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/domain/RetrieveDirectoryContentsUseCase.kt @@ -6,7 +6,7 @@ import com.kevinschildhorn.fotopresenter.data.ImageDirectory import com.kevinschildhorn.fotopresenter.data.network.NetworkDirectoryDetails import com.kevinschildhorn.fotopresenter.data.repositories.DirectoryRepository import com.kevinschildhorn.fotopresenter.data.repositories.ImageRepository -import com.kevinschildhorn.fotopresenter.ui.SharedImage +import com.kevinschildhorn.fotopresenter.ui.shared.SharedImage /** Retrieving Directories from Location @@ -27,7 +27,7 @@ class RetrieveDirectoryContentsUseCase( private suspend fun DirectoryContents.updateImages(block: suspend (NetworkDirectoryDetails) -> SharedImage?): DirectoryContents = this.copy( images = - images.map { - ImageDirectory(it.details, image = block(it.details)) - }, + images.map { + ImageDirectory(it.details, image = block(it.details)) + }, ) diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/SharedImage.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/SharedImage.kt deleted file mode 100644 index 5aa71744..00000000 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/SharedImage.kt +++ /dev/null @@ -1,7 +0,0 @@ -package com.kevinschildhorn.fotopresenter.ui - -import androidx.compose.ui.graphics.ImageBitmap - -expect class SharedImage { - fun getImageBitmap(size:Int): ImageBitmap? -} diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/DirectoryScreen.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/DirectoryScreen.kt index 369c519c..2df3221c 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/DirectoryScreen.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/DirectoryScreen.kt @@ -9,7 +9,9 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.ImageBitmap import com.kevinschildhorn.fotopresenter.data.ImageDirectory +import com.kevinschildhorn.fotopresenter.data.State import com.kevinschildhorn.fotopresenter.ui.atoms.Padding import com.kevinschildhorn.fotopresenter.ui.compose.directory.DirectoryGrid import com.kevinschildhorn.fotopresenter.ui.viewmodel.DirectoryViewModel @@ -17,13 +19,12 @@ import com.kevinschildhorn.fotopresenter.ui.viewmodel.DirectoryViewModel @Composable fun DirectoryScreen( viewModel: DirectoryViewModel, - onImageSelected: (ImageDirectory) -> Unit, ) { LaunchedEffect(Unit) { viewModel.refreshScreen() } val uiState by viewModel.uiState.collectAsState() - var imageState: ImageDirectory? by remember { mutableStateOf(null) } + uiState.state.asComposable( modifier = Modifier.padding( @@ -32,21 +33,21 @@ fun DirectoryScreen( ), ) DirectoryGrid( - uiState.directoryContents, + uiState.directoryGridState, modifier = Modifier .padding(top = Padding.EXTRA_LARGE.dp), - ) { - it.asImageDirectory?.let { - imageState = it - onImageSelected(it) - } ?: run { - viewModel.changeDirectory(it.directory) + onFolderPressed = { + uiState.selectedImage = State.IDLE + viewModel.changeDirectory(it) + }, + onImageDirectoryPressed = { + uiState.selectedImage = it } - } - imageState?.let { - ImagePreviewOverlay(it){ - imageState = null + ) + if(uiState.selectedImage != State.IDLE) { + ImagePreviewOverlay(uiState.selectedImage){ + uiState.selectedImage = State.IDLE } } } diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/ImagePreviewOverlay.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/ImagePreviewOverlay.kt index c8c5607c..584ac7c0 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/ImagePreviewOverlay.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/ImagePreviewOverlay.kt @@ -16,6 +16,7 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.ImageBitmap import androidx.compose.ui.unit.dp import com.kevinschildhorn.atomik.color.base.composeColor import com.kevinschildhorn.fotopresenter.data.ImageDirectory @@ -27,17 +28,11 @@ import com.kevinschildhorn.fotopresenter.ui.viewmodel.PhotoDirectoryViewModel @Composable fun ImagePreviewOverlay( - imageContent: ImageDirectory, - viewModel: PhotoDirectoryViewModel = PhotoDirectoryViewModel(imageContent.image), + imageState: State, onDismiss: () -> Unit, ) { - val imageState by viewModel.imageState.collectAsState(State.IDLE) val interactionSource = remember { MutableInteractionSource() } - LaunchedEffect(Unit) { - viewModel.refreshImageBitmap(500) - } - Overlay( 5f, modifier = Modifier diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/directory/DirectoryGrid.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/directory/DirectoryGrid.kt index 1f680550..dad3dc10 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/directory/DirectoryGrid.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/directory/DirectoryGrid.kt @@ -13,10 +13,12 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.ImageBitmap import androidx.compose.ui.hapticfeedback.HapticFeedbackType import androidx.compose.ui.platform.LocalHapticFeedback import androidx.compose.ui.unit.dp import androidx.compose.ui.zIndex +import com.kevinschildhorn.fotopresenter.data.State import com.kevinschildhorn.fotopresenter.ui.compose.common.ActionSheet import com.kevinschildhorn.fotopresenter.ui.state.DirectoryGridState import com.kevinschildhorn.fotopresenter.ui.state.FolderDirectoryGridCellState @@ -28,7 +30,8 @@ fun DirectoryGrid( directoryContent: DirectoryGridState, gridSize: Int = 5, modifier: Modifier = Modifier, - onDirectoryPressed: (Int) -> Unit, + onFolderPressed: (Int) -> Unit, + onImageDirectoryPressed: (State) -> Unit, ) { var actionSheetVisible by remember { mutableStateOf(false) } var contextMenuPhotoId by rememberSaveable { mutableStateOf(null) } @@ -44,7 +47,11 @@ fun DirectoryGrid( .padding(5.dp) .combinedClickable( onClick = { - onDirectoryPressed(state.id) + (state as? ImageDirectoryGridCellState)?.let { imageContent -> + onImageDirectoryPressed(imageContent.imageState) + } ?: run { + onFolderPressed(state.id) + } }, onLongClick = { haptics.performHapticFeedback(HapticFeedbackType.LongPress) diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/directory/ImageDirectoryGridCell.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/directory/ImageDirectoryGridCell.kt index 5831c50b..0a82b870 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/directory/ImageDirectoryGridCell.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/directory/ImageDirectoryGridCell.kt @@ -10,6 +10,7 @@ import androidx.compose.material.CircularProgressIndicator import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.unit.dp import com.kevinschildhorn.atomik.color.base.composeColor import com.kevinschildhorn.fotopresenter.ui.atoms.FotoColors @@ -28,6 +29,7 @@ fun ImageDirectoryGridCell( Image( bitmap = it, contentDescription = imageContent.name, + contentScale = ContentScale.Crop, modifier = Modifier.fillMaxSize().background(FotoColors.surface.composeColor), ) }.onError { diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt new file mode 100644 index 00000000..ce75a671 --- /dev/null +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt @@ -0,0 +1,22 @@ +package com.kevinschildhorn.fotopresenter.ui.shared + +import androidx.compose.ui.graphics.ImageBitmap + +expect class SharedImage { + fun getImageBitmap(size:Int): ImageBitmap? +} + +fun getScaledDimensions(width: Int, height: Int, minSize:Int): Pair { + val newWidth: Float + val newHeight: Float + if (height < width) { + newHeight = minSize.toFloat() + val ratio:Float = (newHeight / height) + newWidth = width * ratio + } else { + newWidth = minSize.toFloat() + val ratio:Float = (newWidth / width) + newHeight = height * ratio + } + return Pair(newWidth.toInt(), newHeight.toInt()) +} \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/state/DirectoryScreenState.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/state/DirectoryScreenState.kt index d735ff20..57f6be07 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/state/DirectoryScreenState.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/state/DirectoryScreenState.kt @@ -5,9 +5,27 @@ import com.kevinschildhorn.fotopresenter.data.State data class DirectoryScreenState( val currentPath: String = "", - val directoryGridState: DirectoryGridState = DirectoryGridState(emptyList(), emptyList()), + var directoryGridState: DirectoryGridState = DirectoryGridState(emptyList(), mutableListOf()), + var selectedImage: State = State.IDLE, override val state: UiState = UiState.IDLE, -) : ScreenState +) : ScreenState { + + fun copyImageState(id: Int, state: State): DirectoryScreenState { + val list = directoryGridState.imageStates.toMutableList() + val index = list.indexOfFirst { it.id == id } + if (index != -1) { + val element = list[index] + list[index] = element.copy( + imageState = state + ) + } + return this.copy( + directoryGridState = directoryGridState.copy( + imageStates = list + ) + ) + } +} data class DirectoryGridState( val folderStates: List, @@ -20,16 +38,22 @@ data class DirectoryGridState( data class FolderDirectoryGridCellState( override val name: String, override val id: Int, -):DirectoryGridCellState +) : DirectoryGridCellState data class ImageDirectoryGridCellState( val imageState: State, override val name: String, override val id: Int, -):DirectoryGridCellState +) : DirectoryGridCellState interface DirectoryGridCellState { val name: String val id: Int + + val isFolderGridCell: Boolean + get() = (this is FolderDirectoryGridCellState) + + val isImageGridCell: Boolean + get() = (this is ImageDirectoryGridCellState) } \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/viewmodel/DirectoryViewModel.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/viewmodel/DirectoryViewModel.kt index d4516530..8f5f1dc3 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/viewmodel/DirectoryViewModel.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/viewmodel/DirectoryViewModel.kt @@ -38,7 +38,13 @@ class DirectoryViewModel( updateDirectories() } - fun changeDirectory(directory: NetworkDirectoryDetails) { + fun changeDirectory(id: Int) { + _directoryContentsState.value.allDirectories.find { it.id == id }?.let { + changeDirectory(it.details) + } + } + + private fun changeDirectory(directory: NetworkDirectoryDetails) { logger.i { "Changing Directory: ${directory.name}" } viewModelScope.launch(Dispatchers.Default) { val changeDirectoryUseCase: ChangeDirectoryUseCase by inject() @@ -87,6 +93,34 @@ class DirectoryViewModel( state = UiState.SUCCESS, ) } + updatePhotos() + } + } + + private fun updatePhotos() { + _directoryContentsState.value.images.forEach { imageDirectory -> + viewModelScope.launch(Dispatchers.Default) { + + _uiState.update { + it.copyImageState( + imageDirectory.id, + state = State.LOADING + ) + } + + val newState = imageDirectory.image?.getImageBitmap(400)?.let { + State.SUCCESS(it) + } ?: State.ERROR("No Image Found") + + viewModelScope.launch(Dispatchers.Main) { + _uiState.update { + it.copyImageState( + imageDirectory.id, + state = newState + ) + } + } + } } } @@ -100,6 +134,6 @@ class DirectoryViewModel( it.name, it.id ) - } + }.toMutableList() ) } diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/viewmodel/PhotoDirectoryViewModel.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/viewmodel/PhotoDirectoryViewModel.kt index 25c98431..d8fc0d01 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/viewmodel/PhotoDirectoryViewModel.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/viewmodel/PhotoDirectoryViewModel.kt @@ -1,7 +1,7 @@ package com.kevinschildhorn.fotopresenter.ui.viewmodel import androidx.compose.ui.graphics.ImageBitmap -import com.kevinschildhorn.fotopresenter.ui.SharedImage +import com.kevinschildhorn.fotopresenter.ui.shared.SharedImage import com.kevinschildhorn.fotopresenter.data.State import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.MutableStateFlow diff --git a/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/data/network/MockNetworkHandler.kt b/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/data/network/MockNetworkHandler.kt index b08e304e..6c59dea2 100644 --- a/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/data/network/MockNetworkHandler.kt +++ b/shared/src/commonTest/kotlin/com/kevinschildhorn/fotopresenter/data/network/MockNetworkHandler.kt @@ -1,7 +1,7 @@ package com.kevinschildhorn.fotopresenter.data.network import com.kevinschildhorn.fotopresenter.data.LoginCredentials -import com.kevinschildhorn.fotopresenter.ui.SharedImage +import com.kevinschildhorn.fotopresenter.ui.shared.SharedImage object MockNetworkHandler : NetworkHandler { private val successLoginCredentials = diff --git a/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/ui/SharedImage.kt b/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt similarity index 83% rename from shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/ui/SharedImage.kt rename to shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt index b113824f..57d2d206 100644 --- a/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/ui/SharedImage.kt +++ b/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt @@ -1,4 +1,4 @@ -package com.kevinschildhorn.fotopresenter.ui +package com.kevinschildhorn.fotopresenter.ui.shared import androidx.compose.ui.graphics.ImageBitmap import androidx.compose.ui.res.loadImageBitmap diff --git a/shared/src/iosMain/kotlin/com/kevinschildhorn/fotopresenter/ui/SharedImage.kt b/shared/src/iosMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt similarity index 100% rename from shared/src/iosMain/kotlin/com/kevinschildhorn/fotopresenter/ui/SharedImage.kt rename to shared/src/iosMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt diff --git a/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/data/network/SMBJHandler.kt b/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/data/network/SMBJHandler.kt index 50c3ab6a..ca4fc64e 100644 --- a/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/data/network/SMBJHandler.kt +++ b/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/data/network/SMBJHandler.kt @@ -12,7 +12,7 @@ import com.hierynomus.smbj.session.Session import com.hierynomus.smbj.share.DiskShare import com.kevinschildhorn.fotopresenter.data.LoginCredentials import com.kevinschildhorn.fotopresenter.extension.addPath -import com.kevinschildhorn.fotopresenter.ui.SharedImage +import com.kevinschildhorn.fotopresenter.ui.shared.SharedImage object SMBJHandler : NetworkHandler { private val client = SMBClient() diff --git a/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/ui/SharedImage.kt b/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/ui/SharedImage.kt index b2b1138b..bffa53bf 100644 --- a/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/ui/SharedImage.kt +++ b/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/ui/SharedImage.kt @@ -8,3 +8,4 @@ actual open class SharedImage(val file: File) { } expect fun getBitmapFromFile(file: File, size: Int): ImageBitmap? + From 5a275ba6e8c60428fe5386e8a5a06de6198675c7 Mon Sep 17 00:00:00 2001 From: Kevin Schildhorn Date: Thu, 7 Dec 2023 14:41:05 -0500 Subject: [PATCH 4/5] formatting --- shared/src/commonMain/kotlin/App.kt | 1 - .../RetrieveDirectoryContentsUseCase.kt | 6 +-- .../ui/compose/DirectoryScreen.kt | 26 +++++------- .../ui/compose/ImagePreviewOverlay.kt | 25 +++++------ .../compose/login/LoginPasswordTextField.kt | 1 - .../ui/compose/login/LoginScreenForm.kt | 2 +- .../ui/compose/login/LoginTextField.kt | 2 +- .../fotopresenter/ui/shared/SharedImage.kt | 14 ++++--- .../ui/state/DirectoryScreenState.kt | 25 ++++++----- .../ui/viewmodel/DirectoryViewModel.kt | 42 +++++++++---------- .../ui/viewmodel/PhotoDirectoryViewModel.kt | 4 +- 11 files changed, 72 insertions(+), 76 deletions(-) diff --git a/shared/src/commonMain/kotlin/App.kt b/shared/src/commonMain/kotlin/App.kt index b1dc0e05..21381d8f 100644 --- a/shared/src/commonMain/kotlin/App.kt +++ b/shared/src/commonMain/kotlin/App.kt @@ -3,7 +3,6 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import com.kevinschildhorn.fotopresenter.ui.compose.DirectoryScreen -import com.kevinschildhorn.fotopresenter.ui.compose.ImagePreviewOverlay import com.kevinschildhorn.fotopresenter.ui.compose.LoginScreen import com.kevinschildhorn.fotopresenter.ui.compose.Screen import com.kevinschildhorn.fotopresenter.ui.viewmodel.DirectoryViewModel diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/domain/RetrieveDirectoryContentsUseCase.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/domain/RetrieveDirectoryContentsUseCase.kt index faf63d26..8b94f807 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/domain/RetrieveDirectoryContentsUseCase.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/domain/RetrieveDirectoryContentsUseCase.kt @@ -27,7 +27,7 @@ class RetrieveDirectoryContentsUseCase( private suspend fun DirectoryContents.updateImages(block: suspend (NetworkDirectoryDetails) -> SharedImage?): DirectoryContents = this.copy( images = - images.map { - ImageDirectory(it.details, image = block(it.details)) - }, + images.map { + ImageDirectory(it.details, image = block(it.details)) + }, ) diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/DirectoryScreen.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/DirectoryScreen.kt index 2df3221c..fa2239cd 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/DirectoryScreen.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/DirectoryScreen.kt @@ -5,21 +5,15 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.ImageBitmap -import com.kevinschildhorn.fotopresenter.data.ImageDirectory import com.kevinschildhorn.fotopresenter.data.State import com.kevinschildhorn.fotopresenter.ui.atoms.Padding import com.kevinschildhorn.fotopresenter.ui.compose.directory.DirectoryGrid import com.kevinschildhorn.fotopresenter.ui.viewmodel.DirectoryViewModel @Composable -fun DirectoryScreen( - viewModel: DirectoryViewModel, -) { +fun DirectoryScreen(viewModel: DirectoryViewModel) { LaunchedEffect(Unit) { viewModel.refreshScreen() } @@ -27,26 +21,26 @@ fun DirectoryScreen( uiState.state.asComposable( modifier = - Modifier.padding( - horizontal = Padding.STANDARD.dp, - vertical = Padding.SMALL.dp, - ), + Modifier.padding( + horizontal = Padding.STANDARD.dp, + vertical = Padding.SMALL.dp, + ), ) DirectoryGrid( uiState.directoryGridState, modifier = - Modifier - .padding(top = Padding.EXTRA_LARGE.dp), + Modifier + .padding(top = Padding.EXTRA_LARGE.dp), onFolderPressed = { uiState.selectedImage = State.IDLE viewModel.changeDirectory(it) }, onImageDirectoryPressed = { uiState.selectedImage = it - } + }, ) - if(uiState.selectedImage != State.IDLE) { - ImagePreviewOverlay(uiState.selectedImage){ + if (uiState.selectedImage != State.IDLE) { + ImagePreviewOverlay(uiState.selectedImage) { uiState.selectedImage = State.IDLE } } diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/ImagePreviewOverlay.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/ImagePreviewOverlay.kt index 584ac7c0..4d7bb0a2 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/ImagePreviewOverlay.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/ImagePreviewOverlay.kt @@ -10,8 +10,6 @@ import androidx.compose.foundation.layout.width import androidx.compose.material.CircularProgressIndicator import androidx.compose.material.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.Alignment @@ -19,12 +17,10 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.ImageBitmap import androidx.compose.ui.unit.dp import com.kevinschildhorn.atomik.color.base.composeColor -import com.kevinschildhorn.fotopresenter.data.ImageDirectory +import com.kevinschildhorn.fotopresenter.data.State import com.kevinschildhorn.fotopresenter.ui.atoms.FotoColors import com.kevinschildhorn.fotopresenter.ui.atoms.Padding import com.kevinschildhorn.fotopresenter.ui.compose.common.Overlay -import com.kevinschildhorn.fotopresenter.data.State -import com.kevinschildhorn.fotopresenter.ui.viewmodel.PhotoDirectoryViewModel @Composable fun ImagePreviewOverlay( @@ -35,19 +31,20 @@ fun ImagePreviewOverlay( Overlay( 5f, - modifier = Modifier - .background(FotoColors.shadow.composeColor) - .clickable( - interactionSource = interactionSource, - indication = null, - onClick = onDismiss, - ), + modifier = + Modifier + .background(FotoColors.shadow.composeColor) + .clickable( + interactionSource = interactionSource, + indication = null, + onClick = onDismiss, + ), ) { imageState.onSuccess { Image( bitmap = it, contentDescription = null, - modifier = Modifier.fillMaxSize().padding(Padding.IMAGE.dp) + modifier = Modifier.fillMaxSize().padding(Padding.IMAGE.dp), ) }.onLoading { CircularProgressIndicator( @@ -58,4 +55,4 @@ fun ImagePreviewOverlay( Text("Error") } } -} \ No newline at end of file +} diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/login/LoginPasswordTextField.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/login/LoginPasswordTextField.kt index b58bac73..66e8ca1a 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/login/LoginPasswordTextField.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/login/LoginPasswordTextField.kt @@ -9,7 +9,6 @@ import com.kevinschildhorn.atomik.atomic.atoms.shape import com.kevinschildhorn.atomik.atomic.atoms.textStyle import com.kevinschildhorn.fotopresenter.ui.atoms.LoginScreenAtoms - @Composable fun LoginPasswordTextField( value: String, diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/login/LoginScreenForm.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/login/LoginScreenForm.kt index 842cff71..ee2e5dfe 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/login/LoginScreenForm.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/login/LoginScreenForm.kt @@ -6,13 +6,13 @@ import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp +import com.kevinschildhorn.fotopresenter.data.State import com.kevinschildhorn.fotopresenter.extension.required import com.kevinschildhorn.fotopresenter.ui.atoms.Padding import com.kevinschildhorn.fotopresenter.ui.compose.common.ErrorView import com.kevinschildhorn.fotopresenter.ui.compose.common.FormColumn import com.kevinschildhorn.fotopresenter.ui.compose.common.PrimaryButton import com.kevinschildhorn.fotopresenter.ui.state.LoginScreenState -import com.kevinschildhorn.fotopresenter.data.State @Composable fun LoginScreenForm( diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/login/LoginTextField.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/login/LoginTextField.kt index 8fc4558c..c61b939d 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/login/LoginTextField.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/compose/login/LoginTextField.kt @@ -30,4 +30,4 @@ fun LoginTextField( textStyle = molecule.textAtom.textStyle, modifier = modifier, ) -} \ No newline at end of file +} diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt index ce75a671..a549381b 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt @@ -3,20 +3,24 @@ package com.kevinschildhorn.fotopresenter.ui.shared import androidx.compose.ui.graphics.ImageBitmap expect class SharedImage { - fun getImageBitmap(size:Int): ImageBitmap? + fun getImageBitmap(size: Int): ImageBitmap? } -fun getScaledDimensions(width: Int, height: Int, minSize:Int): Pair { +fun getScaledDimensions( + width: Int, + height: Int, + minSize: Int, +): Pair { val newWidth: Float val newHeight: Float if (height < width) { newHeight = minSize.toFloat() - val ratio:Float = (newHeight / height) + val ratio: Float = (newHeight / height) newWidth = width * ratio } else { newWidth = minSize.toFloat() - val ratio:Float = (newWidth / width) + val ratio: Float = (newWidth / width) newHeight = height * ratio } return Pair(newWidth.toInt(), newHeight.toInt()) -} \ No newline at end of file +} diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/state/DirectoryScreenState.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/state/DirectoryScreenState.kt index 57f6be07..122cdabe 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/state/DirectoryScreenState.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/state/DirectoryScreenState.kt @@ -9,20 +9,24 @@ data class DirectoryScreenState( var selectedImage: State = State.IDLE, override val state: UiState = UiState.IDLE, ) : ScreenState { - - fun copyImageState(id: Int, state: State): DirectoryScreenState { + fun copyImageState( + id: Int, + state: State, + ): DirectoryScreenState { val list = directoryGridState.imageStates.toMutableList() - val index = list.indexOfFirst { it.id == id } + val index = list.indexOfFirst { it.id == id } if (index != -1) { val element = list[index] - list[index] = element.copy( - imageState = state - ) + list[index] = + element.copy( + imageState = state, + ) } return this.copy( - directoryGridState = directoryGridState.copy( - imageStates = list - ) + directoryGridState = + directoryGridState.copy( + imageStates = list, + ), ) } } @@ -46,7 +50,6 @@ data class ImageDirectoryGridCellState( override val id: Int, ) : DirectoryGridCellState - interface DirectoryGridCellState { val name: String val id: Int @@ -56,4 +59,4 @@ interface DirectoryGridCellState { val isImageGridCell: Boolean get() = (this is ImageDirectoryGridCellState) -} \ No newline at end of file +} diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/viewmodel/DirectoryViewModel.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/viewmodel/DirectoryViewModel.kt index 8f5f1dc3..2b139e1f 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/viewmodel/DirectoryViewModel.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/viewmodel/DirectoryViewModel.kt @@ -2,6 +2,7 @@ package com.kevinschildhorn.fotopresenter.ui.viewmodel import co.touchlab.kermit.Logger import com.kevinschildhorn.fotopresenter.data.DirectoryContents +import com.kevinschildhorn.fotopresenter.data.State import com.kevinschildhorn.fotopresenter.data.network.NetworkDirectoryDetails import com.kevinschildhorn.fotopresenter.data.network.NetworkHandlerException import com.kevinschildhorn.fotopresenter.domain.ChangeDirectoryUseCase @@ -20,12 +21,10 @@ import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import org.koin.core.component.KoinComponent import org.koin.core.component.inject -import com.kevinschildhorn.fotopresenter.data.State class DirectoryViewModel( private val logger: Logger, ) : ViewModel(), KoinComponent { - private val _uiState = MutableStateFlow(DirectoryScreenState()) val uiState: StateFlow = _uiState.asStateFlow() @@ -59,9 +58,9 @@ class DirectoryViewModel( _uiState.update { it.copy( state = - UiState.ERROR( - e.message ?: "An Unknown Network Error Occurred", - ), + UiState.ERROR( + e.message ?: "An Unknown Network Error Occurred", + ), ) } } catch (e: Exception) { @@ -69,9 +68,9 @@ class DirectoryViewModel( _uiState.update { it.copy( state = - UiState.ERROR( - e.message ?: "Something Went Wrong", - ), + UiState.ERROR( + e.message ?: "Something Went Wrong", + ), ) } } @@ -100,23 +99,23 @@ class DirectoryViewModel( private fun updatePhotos() { _directoryContentsState.value.images.forEach { imageDirectory -> viewModelScope.launch(Dispatchers.Default) { - _uiState.update { it.copyImageState( imageDirectory.id, - state = State.LOADING + state = State.LOADING, ) } - val newState = imageDirectory.image?.getImageBitmap(400)?.let { - State.SUCCESS(it) - } ?: State.ERROR("No Image Found") + val newState = + imageDirectory.image?.getImageBitmap(400)?.let { + State.SUCCESS(it) + } ?: State.ERROR("No Image Found") viewModelScope.launch(Dispatchers.Main) { _uiState.update { it.copyImageState( imageDirectory.id, - state = newState + state = newState, ) } } @@ -128,12 +127,13 @@ class DirectoryViewModel( get() = DirectoryGridState( folderStates = this.folders.map { FolderDirectoryGridCellState(it.name, it.id) }, - imageStates = this.images.map { - ImageDirectoryGridCellState( - State.IDLE, - it.name, - it.id - ) - }.toMutableList() + imageStates = + this.images.map { + ImageDirectoryGridCellState( + State.IDLE, + it.name, + it.id, + ) + }.toMutableList(), ) } diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/viewmodel/PhotoDirectoryViewModel.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/viewmodel/PhotoDirectoryViewModel.kt index d8fc0d01..6cfcca84 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/viewmodel/PhotoDirectoryViewModel.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/viewmodel/PhotoDirectoryViewModel.kt @@ -1,8 +1,8 @@ package com.kevinschildhorn.fotopresenter.ui.viewmodel import androidx.compose.ui.graphics.ImageBitmap -import com.kevinschildhorn.fotopresenter.ui.shared.SharedImage import com.kevinschildhorn.fotopresenter.data.State +import com.kevinschildhorn.fotopresenter.ui.shared.SharedImage import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow @@ -14,7 +14,7 @@ class PhotoDirectoryViewModel(private val image: SharedImage?) : ViewModel() { private val _imageState: MutableStateFlow> = MutableStateFlow(State.IDLE) val imageState: StateFlow> = _imageState.asStateFlow() - fun refreshImageBitmap(size:Int) { + fun refreshImageBitmap(size: Int) { var state: State = State.LOADING _imageState.update { state } viewModelScope.launch(Dispatchers.Default) { From 646eb8ad6cdc78849487e671a014f1f193afc284 Mon Sep 17 00:00:00 2001 From: Kevin Schildhorn Date: Thu, 7 Dec 2023 14:42:52 -0500 Subject: [PATCH 5/5] Update SharedImage.kt --- .../fotopresenter/ui/{ => shared}/SharedImage.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/ui/{ => shared}/SharedImage.kt (84%) diff --git a/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/ui/SharedImage.kt b/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt similarity index 84% rename from shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/ui/SharedImage.kt rename to shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt index bffa53bf..8abc7525 100644 --- a/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/ui/SharedImage.kt +++ b/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt @@ -1,4 +1,4 @@ -package com.kevinschildhorn.fotopresenter.ui +package com.kevinschildhorn.fotopresenter.ui.shared import androidx.compose.ui.graphics.ImageBitmap import com.hierynomus.smbj.share.File