From 933fe8c590da7ef05b46bf7005faa95720c0a2a8 Mon Sep 17 00:00:00 2001 From: Kevin Schildhorn Date: Fri, 11 Oct 2024 11:07:18 -0400 Subject: [PATCH] adding temp code --- .../com/kevinschildhorn/MainActivity.kt | 3 +- desktopApp/src/jvmMain/kotlin/Main.kt | 17 +++- shared/src/androidMain/kotlin/Main.android.kt | 3 +- shared/src/commonMain/kotlin/App.kt | 5 +- .../com/kevinschildhorn/fotopresenter/Koin.kt | 7 +- .../fotopresenter/data/Directory.kt | 2 + .../fotopresenter/data/DirectoryEtc.kt | 82 ++++++++++++++++ .../data/repositories/DirectoryRepository.kt | 7 +- .../data/repositories/ImageRepository.kt | 1 + .../domain/image/RetrieveImageUseCase.kt | 2 +- .../ui/screens/directory/DirectoryScreen.kt | 43 ++++---- .../screens/directory/DirectoryViewModel.kt | 72 ++++++++------ .../directory/DirectoryViewModelTwo.kt | 97 +++++++++++++++++++ .../fotopresenter/ui/shared/SharedImage.kt | 3 +- shared/src/desktopMain/kotlin/Main.desktop.kt | 3 +- .../fotopresenter/UseCaseFactoryDesktop.kt | 6 +- .../fotopresenter/ui/shared/SharedImage.kt | 5 +- .../fotopresenter/ui/shared/SharedImage.kt | 3 +- .../fotopresenter/data/network/SMBJHandler.kt | 3 +- .../fotopresenter/ui/shared/SharedImage.kt | 5 +- 20 files changed, 304 insertions(+), 65 deletions(-) create mode 100644 shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/DirectoryEtc.kt create mode 100644 shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryViewModelTwo.kt diff --git a/androidApp/src/androidMain/kotlin/com/kevinschildhorn/MainActivity.kt b/androidApp/src/androidMain/kotlin/com/kevinschildhorn/MainActivity.kt index b9d912e0..35c02d18 100644 --- a/androidApp/src/androidMain/kotlin/com/kevinschildhorn/MainActivity.kt +++ b/androidApp/src/androidMain/kotlin/com/kevinschildhorn/MainActivity.kt @@ -6,6 +6,7 @@ import androidx.activity.compose.setContent import androidx.appcompat.app.AppCompatActivity import com.kevinschildhorn.fotopresenter.startKoin import com.kevinschildhorn.fotopresenter.ui.screens.directory.DirectoryViewModel +import com.kevinschildhorn.fotopresenter.ui.screens.directory.DirectoryViewModelTwo import com.kevinschildhorn.fotopresenter.ui.screens.login.LoginViewModel import com.kevinschildhorn.fotopresenter.ui.screens.playlist.PlaylistViewModel import com.kevinschildhorn.fotopresenter.ui.screens.slideshow.SlideshowViewModel @@ -15,7 +16,7 @@ import org.koin.core.component.KoinComponent class MainActivity : AppCompatActivity(), KoinComponent { private val loginViewModel by viewModel() - private val directoryViewModel by viewModel() + private val directoryViewModel by viewModel() private val slideshowViewModel by viewModel() private val playlistViewModel by viewModel() diff --git a/desktopApp/src/jvmMain/kotlin/Main.kt b/desktopApp/src/jvmMain/kotlin/Main.kt index 44a8bfbf..7c563025 100644 --- a/desktopApp/src/jvmMain/kotlin/Main.kt +++ b/desktopApp/src/jvmMain/kotlin/Main.kt @@ -3,6 +3,7 @@ import androidx.compose.ui.window.application import co.touchlab.kermit.Logger import com.kevinschildhorn.fotopresenter.UseCaseFactory import com.kevinschildhorn.fotopresenter.ui.screens.directory.DirectoryViewModel +import com.kevinschildhorn.fotopresenter.ui.screens.directory.DirectoryViewModelTwo import com.kevinschildhorn.fotopresenter.ui.screens.login.LoginViewModel import com.kevinschildhorn.fotopresenter.ui.screens.playlist.PlaylistViewModel import com.kevinschildhorn.fotopresenter.ui.screens.slideshow.SlideshowViewModel @@ -12,7 +13,19 @@ object KoinPurse { val loginViewModel = LoginViewModel(Logger.withTag("LoginViewModel"), UseCaseFactory.credentialsRepository) val directoryViewModel = - DirectoryViewModel(UseCaseFactory.playlistRepository, Logger.withTag("DirectoryViewModel")) + DirectoryViewModel( + UseCaseFactory.playlistRepository, + Logger.withTag("DirectoryViewModel"), + UseCaseFactory.directoryRepository, + UseCaseFactory.directoryEtc, + ) + val directoryViewModelTwo = + DirectoryViewModelTwo( + UseCaseFactory.playlistRepository, + Logger.withTag("DirectoryViewModel"), + UseCaseFactory.directoryRepository, + UseCaseFactory.directoryEtc, + ) val slideshowViewModel = SlideshowViewModel(Logger.withTag("SlideshowViewModel")) val playlistViewModel = PlaylistViewModel(UseCaseFactory.playlistRepository, Logger.withTag("PlaylistViewModel")) @@ -25,7 +38,7 @@ fun main() = application { ) { MainView( KoinPurse.loginViewModel, - KoinPurse.directoryViewModel, + KoinPurse.directoryViewModelTwo, KoinPurse.slideshowViewModel, KoinPurse.playlistViewModel, ) diff --git a/shared/src/androidMain/kotlin/Main.android.kt b/shared/src/androidMain/kotlin/Main.android.kt index fd25cda6..758a5f37 100644 --- a/shared/src/androidMain/kotlin/Main.android.kt +++ b/shared/src/androidMain/kotlin/Main.android.kt @@ -1,5 +1,6 @@ import androidx.compose.runtime.Composable import com.kevinschildhorn.fotopresenter.ui.screens.directory.DirectoryViewModel +import com.kevinschildhorn.fotopresenter.ui.screens.directory.DirectoryViewModelTwo import com.kevinschildhorn.fotopresenter.ui.screens.login.LoginViewModel import com.kevinschildhorn.fotopresenter.ui.screens.playlist.PlaylistViewModel import com.kevinschildhorn.fotopresenter.ui.screens.slideshow.SlideshowViewModel @@ -9,7 +10,7 @@ actual fun getPlatformName(): String = "Android" @Composable fun MainView( loginViewModel: LoginViewModel, - directoryViewModel: DirectoryViewModel, + directoryViewModel: DirectoryViewModelTwo, slideshowViewModel: SlideshowViewModel, playlistViewModel: PlaylistViewModel, ) = App(loginViewModel, directoryViewModel, slideshowViewModel, playlistViewModel) diff --git a/shared/src/commonMain/kotlin/App.kt b/shared/src/commonMain/kotlin/App.kt index e0d2632c..a38533f0 100644 --- a/shared/src/commonMain/kotlin/App.kt +++ b/shared/src/commonMain/kotlin/App.kt @@ -14,6 +14,7 @@ import com.kevinschildhorn.fotopresenter.ui.atoms.fotoShapes import com.kevinschildhorn.fotopresenter.ui.screens.common.Screen import com.kevinschildhorn.fotopresenter.ui.screens.directory.DirectoryScreen import com.kevinschildhorn.fotopresenter.ui.screens.directory.DirectoryViewModel +import com.kevinschildhorn.fotopresenter.ui.screens.directory.DirectoryViewModelTwo import com.kevinschildhorn.fotopresenter.ui.screens.login.LoginScreen import com.kevinschildhorn.fotopresenter.ui.screens.login.LoginViewModel import com.kevinschildhorn.fotopresenter.ui.screens.playlist.PlaylistScreen @@ -25,7 +26,7 @@ import com.kevinschildhorn.fotopresenter.ui.screens.slideshow.SlideshowViewModel @Composable fun App( loginViewModel: LoginViewModel, - directoryViewModel: DirectoryViewModel, + directoryViewModel: DirectoryViewModelTwo, slideshowViewModel: SlideshowViewModel, playlistViewModel: PlaylistViewModel, navController: NavHostController = rememberNavController() @@ -56,7 +57,7 @@ fun App( }, onStartSlideshow = { slideshowViewModel.setSlideshow(it) - directoryViewModel.clearSlideshow() + //directoryViewModel.clearSlideshow() navController.navigate(Screen.SLIDESHOW.name) }, onShowPlaylists = { diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/Koin.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/Koin.kt index 27543619..f1a6ab74 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/Koin.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/Koin.kt @@ -2,6 +2,7 @@ package com.kevinschildhorn.fotopresenter import co.touchlab.kermit.Logger import co.touchlab.kermit.LoggerConfig +import com.kevinschildhorn.fotopresenter.data.DirectoryEtc import com.kevinschildhorn.fotopresenter.data.datasources.CredentialsDataSource import com.kevinschildhorn.fotopresenter.data.datasources.DirectoryDataSource import com.kevinschildhorn.fotopresenter.data.datasources.ImageCacheDataSource @@ -24,6 +25,7 @@ import com.kevinschildhorn.fotopresenter.domain.image.RetrieveImageUseCase import com.kevinschildhorn.fotopresenter.domain.image.RetrieveSlideshowFromPlaylistUseCase import com.kevinschildhorn.fotopresenter.domain.image.SaveMetadataForPathUseCase import com.kevinschildhorn.fotopresenter.ui.screens.directory.DirectoryViewModel +import com.kevinschildhorn.fotopresenter.ui.screens.directory.DirectoryViewModelTwo import com.kevinschildhorn.fotopresenter.ui.screens.login.LoginViewModel import com.kevinschildhorn.fotopresenter.ui.screens.playlist.PlaylistViewModel import com.kevinschildhorn.fotopresenter.ui.screens.slideshow.SlideshowViewModel @@ -45,6 +47,8 @@ val commonModule = single { CredentialsRepository(get()) } single { DirectoryDataSource(get(), baseLogger.withTag("DirectoryDataSource")) } single { DirectoryRepository(get(), get()) } + single { DirectoryEtc(get(), get(), baseLogger.withTag("DirectoryEtc")) } + single { ImageRemoteDataSource(get()) } single { ImageRepository(get()) } single { ImageCacheDataSource(get(), get(), baseLogger.withTag("ImageCacheDataSource")) } @@ -83,7 +87,8 @@ val commonModule = factory { SaveMetadataForPathUseCase(get()) } // UI single { LoginViewModel(baseLogger.withTag("LoginViewModel"), get()) } - single { DirectoryViewModel(get(), baseLogger.withTag("DirectoryViewModel")) } + single { DirectoryViewModel(get(), baseLogger.withTag("DirectoryViewModel"), get(), get()) } + single { DirectoryViewModelTwo(get(), baseLogger.withTag("DirectoryViewModel"), get(), get())} single { SlideshowViewModel(baseLogger.withTag("SlideshowViewModel")) } single { PlaylistViewModel(get(), baseLogger.withTag("PlaylistViewModel")) } } 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 f663b314..94a1a95d 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/Directory.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/Directory.kt @@ -1,5 +1,6 @@ package com.kevinschildhorn.fotopresenter.data +import androidx.compose.ui.graphics.ImageBitmap import com.kevinschildhorn.fotopresenter.data.network.NetworkDirectoryDetails import com.kevinschildhorn.fotopresenter.ui.SortingType import com.kevinschildhorn.fotopresenter.ui.shared.SharedImage @@ -29,6 +30,7 @@ data class ImageDirectory( override val details: NetworkDirectoryDetails, val metaData: MetadataFileDetails?, val image: SharedImage? = null, + val imageBitmap: ImageBitmap? = null, ) : Directory { override fun toString(): String = "(I:${details.fullPath}:${details.id})" } diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/DirectoryEtc.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/DirectoryEtc.kt new file mode 100644 index 00000000..22806af3 --- /dev/null +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/data/DirectoryEtc.kt @@ -0,0 +1,82 @@ +package com.kevinschildhorn.fotopresenter.data + +import co.touchlab.kermit.Logger +import com.kevinschildhorn.fotopresenter.data.repositories.DirectoryRepository +import com.kevinschildhorn.fotopresenter.data.repositories.ImageRepository +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.update +import kotlinx.coroutines.launch +import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.withContext + +class DirectoryEtc( + private val imageRepository: ImageRepository, + private val directoryRepository: DirectoryRepository, + private val logger: Logger, +) { + + private val _directoryContentsFlow = MutableStateFlow(DirectoryContents()) + private val _imageDirectoryList = MutableStateFlow>(emptyList()) + + val directoryFlow: Flow = + combine(_directoryContentsFlow, _imageDirectoryList) { directory, images -> + directory.copy(images = images) + } + + fun refreshDirectories(path: String, coroutineScope: CoroutineScope) { + coroutineScope.launch(Dispatchers.Default) { + // Retrieve File Data + var directoryContents = directoryRepository.getDirectoryContents(path) + _directoryContentsFlow.emit(directoryContents) + _imageDirectoryList.emit(directoryContents.images) + + // For each image, get the Byte Array + val images = directoryContents + .images + //.take(10) + .toMutableList() + + images.chunked(10).forEach { imageChunk -> + logger.i("Starting Jobs!") + runBlocking { + imageChunk.forEachIndexed { index, image -> + coroutineScope.launch { + processItemAsync(index, image) + } + } + } + logger.i("Joined!") + } + + logger.i { "Finished!" } + } + } + + suspend fun processItemAsync( + index: Int, + item: ImageDirectory, + ) { + var mutableItemDirectory = item + val itemWithBytes = withContext(Dispatchers.IO) { + val sharedImage = imageRepository.getImage(item.details) + mutableItemDirectory.copy(image = sharedImage) + } + updateImageList(index, itemWithBytes) + val itemWithBitmap = withContext(Dispatchers.IO) { + val bitmap = itemWithBytes.image?.getImageBitmap(256) + itemWithBytes.copy(imageBitmap = bitmap) + } + updateImageList(index, itemWithBitmap) + item.image?.close() + } + + private fun updateImageList(index: Int, item: ImageDirectory) { + val items = _imageDirectoryList.value.toMutableList() + items[index] = item + _imageDirectoryList.update { items } + } +} \ No newline at end of file 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 7bf66afa..52265801 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 @@ -12,21 +12,22 @@ class DirectoryRepository( private val directoryDataSource: DirectoryDataSource, private val metadataDataSource: ImageMetadataDataSource, ) { + // Retrieves [NetworkDirectoryDetails] for folders and directories. Contains no bitmap data suspend fun getDirectoryContents(path: String): DirectoryContents { val folderDirectories: List = directoryDataSource.getFolderDirectories(path) val imageDirectories: List = directoryDataSource.getImageDirectories(path) - val metaData = metadataDataSource.importMetaData() - + //val metaData = metadataDataSource.importMetaData() return DirectoryContents( folders = folderDirectories.map { FolderDirectory(it) }, images = imageDirectories.map { networkDetails -> ImageDirectory( networkDetails, - metaData = metaData.files.find { networkDetails.fullPath == it.filePath } + metaData = null, //metaData.files.find { networkDetails.fullPath == it.filePath } + image = null, ) }, ) 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 ddbc81b9..df91ac04 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 @@ -7,5 +7,6 @@ import com.kevinschildhorn.fotopresenter.ui.shared.SharedImage class ImageRepository( private val remoteDataSource: ImageRemoteDataSource, ) { + // Gets Image ByteArray from a Remote Data Source suspend fun getImage(directory: NetworkDirectoryDetails): SharedImage? = remoteDataSource.getImage(directory) } diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/domain/image/RetrieveImageUseCase.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/domain/image/RetrieveImageUseCase.kt index cc2efaa8..dc9bd540 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/domain/image/RetrieveImageUseCase.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/domain/image/RetrieveImageUseCase.kt @@ -14,7 +14,7 @@ class RetrieveImageUseCase( private val logger: Logger, ) { - suspend operator fun invoke( + operator fun invoke( directory: ImageDirectory, imageSize: Int, ): ImageBitmap? { diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryScreen.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryScreen.kt index ab3ee5a1..a173e716 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryScreen.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryScreen.kt @@ -20,6 +20,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp +import com.kevinschildhorn.fotopresenter.baseLogger import com.kevinschildhorn.fotopresenter.data.ImageSlideshowDetails import com.kevinschildhorn.fotopresenter.ui.UiState import com.kevinschildhorn.fotopresenter.ui.atoms.FotoTypography @@ -56,23 +57,24 @@ enum class DirectoryOverlay { @Composable fun DirectoryScreen( - viewModel: DirectoryViewModel, + viewModel: DirectoryViewModelTwo, onLogout: () -> Unit, onStartSlideshow: (ImageSlideshowDetails) -> Unit, onShowPlaylists: () -> Unit, ) { LaunchedEffect(Unit) { + baseLogger.i { "Launched Effect" } viewModel.refreshScreen() } - val uiState by viewModel.uiState.collectAsState() - val imageUiState by viewModel.imageUiState.collectAsState() + val uiState by viewModel.uiState.collectAsState(DirectoryScreenStateTwo()) + //val imageUiState by viewModel.imageUiState.collectAsState() var overlayVisible by remember { mutableStateOf(DirectoryOverlay.NONE) } // Navigation - if (!uiState.loggedIn) onLogout() - uiState.slideshowDetails?.let { - onStartSlideshow(it) - } + //if (!uiState.loggedIn) onLogout() + //uiState.slideshowDetails?.let { + // onStartSlideshow(it) + //} //region UI Column { @@ -97,13 +99,14 @@ fun DirectoryScreen( DirectoryNavigationBar( directories = uiState.currentPathList, onHome = { - viewModel.navigateToFolder(-1) + //viewModel.navigateToFolder(-1) }, onItem = { - viewModel.navigateToFolder(it) + //viewModel.navigateToFolder(it) }, modifier = Modifier.padding(Padding.SMALL.dp) ) + /* if (uiState.imageCountString.isNotEmpty()) { Text( uiState.imageCountString, @@ -121,18 +124,18 @@ fun DirectoryScreen( color = fotoColors.primary, ) - } + }*/ DirectoryGrid( uiState.directoryGridState, onFolderPressed = { - viewModel.changeDirectory(it) + //viewModel.changeDirectory(it) }, onImageDirectoryPressed = { - viewModel.setSelectedImageById(it) + //viewModel.setSelectedImageById(it) overlayVisible = DirectoryOverlay.IMAGE }, onActionSheet = { - viewModel.setSelectedDirectory(it) + //viewModel.setSelectedDirectory(it) overlayVisible = DirectoryOverlay.ACTION_SHEET }, ) @@ -142,6 +145,7 @@ fun DirectoryScreen( // Overlays //region ActionSheet + /* ActionSheet( visible = overlayVisible == DirectoryOverlay.ACTION_SHEET, offset = 200, @@ -173,9 +177,9 @@ fun DirectoryScreen( overlayVisible = DirectoryOverlay.NONE viewModel.setSelectedDirectory(null) }, - ) + )*/ //endregion - +/* //region Selected Image imageUiState.selectedImage?.let { ImagePreviewOverlay( @@ -192,7 +196,7 @@ fun DirectoryScreen( viewModel.showNextImage() }, ) - } + }*/ //endregion //region Loading @@ -223,7 +227,7 @@ fun DirectoryScreen( overlayVisible = DirectoryOverlay.NONE }, onConfirmation = { - viewModel.logout() + //viewModel.logout() overlayVisible = DirectoryOverlay.NONE }, ) @@ -237,12 +241,13 @@ fun DirectoryScreen( overlayVisible = DirectoryOverlay.NONE }, onConfirmation = { - viewModel.setFilterType(it) + //viewModel.setFilterType(it) } ) } //region Playlist + /* if (overlayVisible == DirectoryOverlay.PLAYLIST) { PlaylistScreen( viewModel, @@ -269,5 +274,5 @@ fun DirectoryScreen( viewModel.setSelectedDirectory(null) overlayVisible = DirectoryOverlay.NONE }) - } + }*/ } diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryViewModel.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryViewModel.kt index 4be35edf..828d31b8 100644 --- a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryViewModel.kt +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryViewModel.kt @@ -4,13 +4,14 @@ import co.touchlab.kermit.Logger import com.kevinschildhorn.fotopresenter.UseCaseFactory import com.kevinschildhorn.fotopresenter.data.Directory import com.kevinschildhorn.fotopresenter.data.DirectoryContents +import com.kevinschildhorn.fotopresenter.data.DirectoryEtc import com.kevinschildhorn.fotopresenter.data.FolderDirectory import com.kevinschildhorn.fotopresenter.data.ImageDirectory -import com.kevinschildhorn.fotopresenter.data.ImageSlideshowDetails import com.kevinschildhorn.fotopresenter.data.MetadataFileDetails import com.kevinschildhorn.fotopresenter.data.PlaylistDetails import com.kevinschildhorn.fotopresenter.data.State import com.kevinschildhorn.fotopresenter.data.network.NetworkHandlerException +import com.kevinschildhorn.fotopresenter.data.repositories.DirectoryRepository import com.kevinschildhorn.fotopresenter.data.repositories.PlaylistRepository import com.kevinschildhorn.fotopresenter.domain.image.RetrieveImageUseCase import com.kevinschildhorn.fotopresenter.extension.addPath @@ -26,10 +27,10 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.async import kotlinx.coroutines.awaitAll import kotlinx.coroutines.cancelChildren -import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.last import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import kotlinx.coroutines.plus @@ -39,6 +40,8 @@ import org.koin.core.component.KoinComponent class DirectoryViewModel( private val playlistRepository: PlaylistRepository, private val logger: Logger, + private val directoryRepository: DirectoryRepository, + private val directoryEtc:DirectoryEtc, ) : PlaylistViewModel(playlistRepository, logger), ImageViewModel by DefaultImageViewModel(logger), KoinComponent { @@ -49,7 +52,7 @@ class DirectoryViewModel( private val _uiState = MutableStateFlow(DirectoryScreenState()) val uiState: StateFlow = _uiState.asStateFlow() - private val _directoryContentsState = MutableStateFlow(DirectoryContents()) + private val _directoryContentsState = directoryEtc.directoryFlow // Indexes of all Downloaded images private val downloadedImageSet: MutableSet = mutableSetOf() @@ -75,7 +78,7 @@ class DirectoryViewModel( //region Connection fun setLoggedIn() { - _uiState.update { it.copy(loggedIn = true) } + //_uiState.update { it.copy(loggedIn = true) } } fun logout() { @@ -85,7 +88,7 @@ class DirectoryViewModel( val logoutUseCase = UseCaseFactory.disconnectFromServerUseCase logoutUseCase() logger.d { "Setting loggedIn state to false" } - _uiState.update { it.copy(loggedIn = false) } + //_uiState.update { it.copy(loggedIn = false) } } } @@ -99,13 +102,15 @@ class DirectoryViewModel( logger.d { "Checking for Selected Directory" } uiState.value.selectedDirectory?.id?.let { id -> logger.d { "Finding Folder" } - _directoryContentsState.value.folders.find { it.id == id }?.let { - logger.d { "Folder found, starting to retrieve images" } - slideshowScope.launch { - val retrieveImagesUseCase = UseCaseFactory.retrieveImageDirectoriesUseCase - val images = retrieveImagesUseCase(it.details) - logger.v { "Retrieved images, copying them to state" } - _uiState.update { it.copy(slideshowDetails = ImageSlideshowDetails(images)) } + viewModelScope.launch { + _directoryContentsState.last().folders.find { it.id == id }?.let { + logger.d { "Folder found, starting to retrieve images" } + slideshowScope.launch { + val retrieveImagesUseCase = UseCaseFactory.retrieveImageDirectoriesUseCase + val images = retrieveImagesUseCase(it.details) + logger.v { "Retrieved images, copying them to state" } + //_uiState.update { it.copy(slideshowDetails = ImageSlideshowDetails(images)) } + } } } } ?: run { @@ -114,7 +119,7 @@ class DirectoryViewModel( } fun clearSlideshow() { - _uiState.update { it.copy(slideshowDetails = null) } + //_uiState.update { it.copy(slideshowDetails = null) } } fun setSelectedImageById(imageId: Int?) { @@ -143,8 +148,10 @@ class DirectoryViewModel( } fun changeDirectory(id: Int) { - _directoryContentsState.value.allDirectories.find { it.id == id }?.let { - changeDirectoryToPath(currentPath.addPath(it.details.name)) + viewModelScope.launch { + _directoryContentsState.last().allDirectories.find { it.id == id }?.let { + changeDirectoryToPath(currentPath.addPath(it.details.name)) + } } } @@ -188,14 +195,23 @@ class DirectoryViewModel( logger.i { "Updating Directories" } _uiState.update { it.copy(state = UiState.LOADING) } viewModelScope.launch(Dispatchers.Default) { - val retrieveDirectoryUseCase = UseCaseFactory.retrieveDirectoryContentsUseCase + + // Use Pagination + // Get first ten images + //val retrieveDirectoryUseCase = UseCaseFactory.retrieveDirectoryContentsUseCase + viewModelScope.launch(Dispatchers.IO) { + + val directoryContents = directoryRepository.getDirectoryContents(currentPath) + //directoryEtc.todo(currentPath) + } + logger.i { "Getting Directory Contents" } - val directoryContents = retrieveDirectoryUseCase(currentPath) - logger.i { "Got Directory Contents: ${directoryContents.allDirectories.count()}" } - _directoryContentsState.update { directoryContents } + //val directoryContents = retrieveDirectoryUseCase(currentPath) + //logger.i { "Got Directory Contents: ${directoryContents.allDirectories.count()}" } + //_directoryContentsState.update { directoryContents } - updateGrid() + //updateGrid() logger.i { "Current State ${uiState.value.state}" } updatePhotos() } @@ -240,7 +256,7 @@ class DirectoryViewModel( // TODO: STORE LARGEST IMAGES IN CHUNKS } } - +/* private fun updateGrid() = with(_directoryContentsState.value) { logger.i { "Updating State to Success" } logger.i { "Setting Directories: $this" } @@ -253,7 +269,7 @@ class DirectoryViewModel( state = UiState.SUCCESS, ) } - } + }*/ private val DirectoryContents.asDirectoryGridState: DirectoryGridState get() = @@ -274,6 +290,7 @@ class DirectoryViewModel( //region Playlist fun addSelectedDirectoryToPlaylist(playlist: PlaylistDetails) { + /* uiState.value.selectedDirectory?.let { selectedDirectory -> with(_directoryContentsState.value) { logger.i { "Inserting Playlist Image ${playlist.id} as ${uiState.value.selectedDirectory}" } @@ -291,7 +308,7 @@ class DirectoryViewModel( } } ?: run { logger.w { "Selected Directory Not found" } - } + }*/ } //endregion @@ -306,10 +323,11 @@ class DirectoryViewModel( fun setFilterType(sortingType: SortingType) { logger.i { "Setting Filter Type" } + /* _directoryContentsState.update { it.sorted(sortingType) - } - updateGrid() + }*/ + //updateGrid() } private fun cancelJobs() { @@ -324,12 +342,12 @@ class DirectoryViewModel( private fun findSelectedFolderDirectory(): FolderDirectory? = uiState.value.selectedDirectory?.id?.let { id -> logger.d { "Finding Selected Directory" } - return _directoryContentsState.value.folders.find { it.id == id } + return null// _directoryContentsState.value.folders.find { it.id == id } } private fun findSelectedImageDirectory(): ImageDirectory? = uiState.value.selectedDirectory?.id?.let { id -> logger.d { "Finding Selected Directory" } - return _directoryContentsState.value.images.find { it.id == id } + return null//_directoryContentsState.value.images.find { it.id == id } } } diff --git a/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryViewModelTwo.kt b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryViewModelTwo.kt new file mode 100644 index 00000000..2206ff00 --- /dev/null +++ b/shared/src/commonMain/kotlin/com/kevinschildhorn/fotopresenter/ui/screens/directory/DirectoryViewModelTwo.kt @@ -0,0 +1,97 @@ +package com.kevinschildhorn.fotopresenter.ui.screens.directory + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import co.touchlab.kermit.Logger +import com.kevinschildhorn.fotopresenter.data.DirectoryEtc +import com.kevinschildhorn.fotopresenter.data.FolderDirectory +import com.kevinschildhorn.fotopresenter.data.ImageDirectory +import com.kevinschildhorn.fotopresenter.data.State +import com.kevinschildhorn.fotopresenter.data.repositories.DirectoryRepository +import com.kevinschildhorn.fotopresenter.data.repositories.PlaylistRepository +import com.kevinschildhorn.fotopresenter.ui.SortingType +import com.kevinschildhorn.fotopresenter.ui.UiState +import com.kevinschildhorn.fotopresenter.ui.screens.common.ScreenState +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.launch +import org.koin.core.component.KoinComponent +import kotlin.String + +data class DirectoryScreenStateTwo( + val currentPath: String = "", + val directoryGridState: DirectoryGridState = DirectoryGridState(emptyList(), mutableListOf()), + val selectedDirectory: DirectoryGridCellState? = null, + val currentImageCount: Int = 0, + val totalImageCount: Int = 0, + val sortingType: SortingType = SortingType.NAME_ASC, + override val state: UiState = UiState.IDLE, +) : ScreenState { + + val currentPathList: List + get() = currentPath.split("\\").filter { it.isNotEmpty() } +} + +class DirectoryViewModelTwo( + private val playlistRepository: PlaylistRepository, + private val logger: Logger, + private val directoryRepository: DirectoryRepository, + private val directoryEtc: DirectoryEtc, +) : ViewModel(), KoinComponent { + + private var currentPath: String = "" + + private val _directoryContentsState = directoryEtc.directoryFlow + val directoryGridStateFlow: Flow = + _directoryContentsState.map { directory -> + DirectoryGridState( + folderStates = directory.folders.map { it.asCellState }, + imageStates = directory.images.map { it.asCellState }, + ) + } + + private var selectedDirectory: DirectoryGridCellState? = null + private var sortingType: SortingType = SortingType.NAME_ASC + private var state: UiState = UiState.IDLE + + + val uiState: Flow = directoryGridStateFlow.map { + logger.v{ it.toString() } + DirectoryScreenStateTwo( + currentPath = currentPath, + directoryGridState = it, + selectedDirectory = selectedDirectory, + currentImageCount = 0, + totalImageCount = 0, + sortingType = sortingType, + state = UiState.SUCCESS, + ) + } + + fun refreshScreen(){ + if(state != UiState.LOADING) { + currentPath = "Camera Uploads/Camera" + updateDirectories() + } + } + + private fun updateDirectories() { + logger.i { "Updating Directories" } + state = UiState.LOADING + directoryEtc.refreshDirectories(currentPath, viewModelScope) + } + + private val FolderDirectory.asCellState: FolderDirectoryGridCellState + get() = FolderDirectoryGridCellState(name = name, id = id) + + private val ImageDirectory.asCellState: ImageDirectoryGridCellState + get() { + val imageState = when{ + (imageBitmap != null) -> State.SUCCESS(imageBitmap) + image != null -> State.ERROR("") + else -> State.IDLE + } + return ImageDirectoryGridCellState(imageState = imageState, name = name, id = id) + } +} \ 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 14dd76ef..e645707a 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,6 +3,7 @@ package com.kevinschildhorn.fotopresenter.ui.shared import androidx.compose.ui.graphics.ImageBitmap expect class SharedImage { - fun getImageBitmap(size: Int): ImageBitmap? val byteArray: ByteArray + fun getImageBitmap(size: Int): ImageBitmap? + fun close() } diff --git a/shared/src/desktopMain/kotlin/Main.desktop.kt b/shared/src/desktopMain/kotlin/Main.desktop.kt index 868146ed..8d84ac39 100644 --- a/shared/src/desktopMain/kotlin/Main.desktop.kt +++ b/shared/src/desktopMain/kotlin/Main.desktop.kt @@ -1,5 +1,6 @@ import androidx.compose.runtime.Composable import com.kevinschildhorn.fotopresenter.ui.screens.directory.DirectoryViewModel +import com.kevinschildhorn.fotopresenter.ui.screens.directory.DirectoryViewModelTwo import com.kevinschildhorn.fotopresenter.ui.screens.login.LoginViewModel import com.kevinschildhorn.fotopresenter.ui.screens.playlist.PlaylistViewModel import com.kevinschildhorn.fotopresenter.ui.screens.slideshow.SlideshowViewModel @@ -9,7 +10,7 @@ actual fun getPlatformName(): String = "Desktop" @Composable fun MainView( loginViewModel: LoginViewModel, - directoryViewModel: DirectoryViewModel, + directoryViewModel: DirectoryViewModelTwo, slideshowViewModel: SlideshowViewModel, playlistViewModel: PlaylistViewModel, ) = App(loginViewModel, directoryViewModel, slideshowViewModel, playlistViewModel) diff --git a/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/UseCaseFactoryDesktop.kt b/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/UseCaseFactoryDesktop.kt index 460b0abf..dff24c4a 100644 --- a/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/UseCaseFactoryDesktop.kt +++ b/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/UseCaseFactoryDesktop.kt @@ -2,6 +2,7 @@ package com.kevinschildhorn.fotopresenter import co.touchlab.kermit.Logger import co.touchlab.kermit.LoggerConfig +import com.kevinschildhorn.fotopresenter.data.DirectoryEtc import com.kevinschildhorn.fotopresenter.data.datasources.CredentialsDataSource import com.kevinschildhorn.fotopresenter.data.datasources.DirectoryDataSource import com.kevinschildhorn.fotopresenter.data.datasources.ImageCacheDataSource @@ -46,12 +47,15 @@ actual object UseCaseFactory { networkHandler = networkHandler, logger = baseLogger.withTag("imageMetadataDataSource") ) - private val directoryRepository = DirectoryRepository(directoryDataSource, imageMetadataDataSource) + val directoryRepository = DirectoryRepository(directoryDataSource, imageMetadataDataSource) + private val imageRepository = ImageRepository(ImageRemoteDataSource(networkHandler)) private val playlistSQLDataSource = PlaylistSQLDataSource( sqlDriver, com.kevinschildhorn.fotopresenter.baseLogger ) + val directoryEtc = DirectoryEtc(imageRepository, directoryRepository, baseLogger) + private val playlistFileDataSource = PlaylistFileDataSource( baseLogger.withTag("playlistFileDataSource"), diff --git a/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt b/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt index feda2259..022ad298 100644 --- a/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt +++ b/shared/src/desktopMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt @@ -3,7 +3,8 @@ package com.kevinschildhorn.fotopresenter.ui.shared import androidx.compose.ui.graphics.ImageBitmap import androidx.compose.ui.res.loadImageBitmap import com.hierynomus.smbj.share.File +import java.io.InputStream -actual fun getBitmapFromFile(file: File, size:Int): ImageBitmap? = - file.inputStream.buffered().use(::loadImageBitmap) +actual fun getBitmapFromFile(inputStream: InputStream, size:Int): ImageBitmap? = + inputStream.buffered().use(::loadImageBitmap) diff --git a/shared/src/iosMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt b/shared/src/iosMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt index 744138ab..16f0f21a 100644 --- a/shared/src/iosMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt +++ b/shared/src/iosMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt @@ -3,6 +3,7 @@ package com.kevinschildhorn.fotopresenter.ui import androidx.compose.ui.graphics.ImageBitmap actual class SharedImage { - actual fun getImageBitmap(size:Int): ImageBitmap? = null actual val byteArray: ByteArray = ByteArray() + actual fun getImageBitmap(size:Int): ImageBitmap? = null + actual fun close() {} } 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 63033d22..8aad463e 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 @@ -63,6 +63,7 @@ object SMBJHandler : NetworkHandler { } } catch (e: Exception) { logger.e(e) { "Failed To Connect" } + logger.e(e.localizedMessage) disconnect() return false } @@ -107,7 +108,7 @@ object SMBJHandler : NetworkHandler { override suspend fun openImage(path: String): SharedImage? = getFile(path)?.let { val sharedImage = SharedImage(it) - it.close() + //it.close() TODO sharedImage } ?: run { null } diff --git a/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt b/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt index 2a95e3f1..5a7c7d03 100644 --- a/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt +++ b/shared/src/jvmMain/kotlin/com/kevinschildhorn/fotopresenter/ui/shared/SharedImage.kt @@ -4,8 +4,11 @@ import androidx.compose.ui.graphics.ImageBitmap import com.hierynomus.smbj.share.File actual open class SharedImage(val file: File) { - actual fun getImageBitmap(size: Int): ImageBitmap? = getBitmapFromFile(file, size) actual val byteArray: ByteArray = file.inputStream.readAllBytes() + actual fun getImageBitmap(size: Int): ImageBitmap? = getBitmapFromFile(file, size) + actual fun close(){ + file.close() + } } expect fun getBitmapFromFile(file: File, size: Int): ImageBitmap?