Skip to content

Commit

Permalink
Merge pull request #47 from KevinSchildhorn/FixingDesktopVersion
Browse files Browse the repository at this point in the history
Fixing desktop version
  • Loading branch information
KevinSchildhorn authored Feb 8, 2024
2 parents c48e2b4 + 972eea2 commit 0dcf6b0
Show file tree
Hide file tree
Showing 36 changed files with 777 additions and 180 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,5 @@ ios/FotoPresenter.xcworkspace/xcuserdata/kevinschildhorn.xcuserdatad/UserInterfa
ios/FotoPresenter.xcworkspace/xcuserdata/kevinschildhorn.xcuserdatad/UserInterfaceState.xcuserstate
common/src/commonMain/kotlin/me/kevinschildhorn/common/network/ftps/TestingLoginInfo.kt
androidApp/build/kotlin/compileDebugKotlinAndroid/cacheable/caches-jvm/lookups/lookups.tab_i.len

desktopApp/build
4 changes: 4 additions & 0 deletions desktopApp/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ kotlin {
val jvmMain by getting {
dependencies {
implementation(compose.desktop.currentOs)
implementation("io.insert-koin:koin-core:3.4.0")
implementation("co.touchlab:kermit:1.2.2")
implementation("com.russhwolf:multiplatform-settings:1.0.0")

implementation(project(":shared"))
}
}
Expand Down
29 changes: 26 additions & 3 deletions desktopApp/src/jvmMain/kotlin/Main.kt
Original file line number Diff line number Diff line change
@@ -1,9 +1,32 @@
import androidx.compose.material.Text
import androidx.compose.ui.window.Window
import androidx.compose.ui.window.application
import com.kevinschildhorn.fotopresenter.UseCaseFactory
import com.kevinschildhorn.fotopresenter.ui.screens.directory.DirectoryViewModel
import com.kevinschildhorn.fotopresenter.ui.screens.login.LoginViewModel
import com.kevinschildhorn.fotopresenter.ui.screens.playlist.PlaylistViewModel
import com.kevinschildhorn.fotopresenter.ui.screens.slideshow.SlideshowViewModel


object KoinPurse {
val loginViewModel =
LoginViewModel(UseCaseFactory.baseLogger, UseCaseFactory.credentialsRepository)
val directoryViewModel =
DirectoryViewModel(UseCaseFactory.playlistRepository, UseCaseFactory.baseLogger)
val slideshowViewModel = SlideshowViewModel(UseCaseFactory.baseLogger)
val playlistViewModel =
PlaylistViewModel(UseCaseFactory.playlistRepository, UseCaseFactory.baseLogger)
}

fun main() = application {
Window(onCloseRequest = ::exitApplication) {
Text("")
Window(
title = "FotoPresenter",
onCloseRequest = ::exitApplication
) {
MainView(
KoinPurse.loginViewModel,
KoinPurse.directoryViewModel,
KoinPurse.slideshowViewModel,
KoinPurse.playlistViewModel,
)
}
}
4 changes: 2 additions & 2 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ kotlin.mpp.androidSourceSetLayoutVersion=2
android.useAndroidX=true
android.compileSdk=34
android.targetSdk=34
android.minSdk=24
android.minSdk=22

#Versions
kotlin.version=1.9.21
agp.version=8.1.4
compose.version=1.5.11
compose.version=1.5.11
4 changes: 2 additions & 2 deletions shared/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ kotlin {
implementation("co.touchlab:kermit:1.2.2")
implementation("co.touchlab:kermit-koin:1.2.2")
implementation("com.russhwolf:multiplatform-settings:1.0.0")

implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.5.0")
api("dev.icerock.moko:resources:0.23.0")
api("dev.icerock.moko:resources-compose:0.23.0") // for compose multiplatform
}
Expand All @@ -60,7 +60,7 @@ kotlin {
dependsOn(commonMain)
resources.srcDir("src/commonMain/resources")
dependencies {
implementation("com.hierynomus:smbj:0.13.0")
implementation("com.hierynomus:smbj:0.11.5")
implementation(compose.uiTooling)
implementation("app.cash.sqldelight:sqlite-driver:2.0.1")
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package com.kevinschildhorn.fotopresenter

import com.kevinschildhorn.fotopresenter.domain.RetrieveDirectoryContentsUseCase
import com.kevinschildhorn.fotopresenter.domain.connection.AutoConnectUseCase
import com.kevinschildhorn.fotopresenter.domain.connection.ConnectToServerUseCase
import com.kevinschildhorn.fotopresenter.domain.connection.DisconnectFromServerUseCase
import com.kevinschildhorn.fotopresenter.domain.connection.SaveCredentialsUseCase
import com.kevinschildhorn.fotopresenter.domain.directory.ChangeDirectoryUseCase
import com.kevinschildhorn.fotopresenter.domain.image.RetrieveImageDirectoriesUseCase
import com.kevinschildhorn.fotopresenter.domain.image.RetrieveImageUseCase
import com.kevinschildhorn.fotopresenter.domain.image.RetrieveSlideshowFromPlaylistUseCase
import org.koin.core.component.KoinComponent
import org.koin.core.component.inject

actual object UseCaseFactory : KoinComponent {

actual val connectToServerUseCase: ConnectToServerUseCase
get() {
val useCase: ConnectToServerUseCase by inject()
return useCase
}
actual val changeDirectoryUseCase: ChangeDirectoryUseCase
get() {
val useCase: ChangeDirectoryUseCase by inject()
return useCase
}
actual val autoConnectUseCase: AutoConnectUseCase
get() {
val useCase: AutoConnectUseCase by inject()
return useCase
}
actual val saveCredentialsUseCase: SaveCredentialsUseCase
get() {
val useCase: SaveCredentialsUseCase by inject()
return useCase
}
actual val disconnectFromServerUseCase: DisconnectFromServerUseCase
get() {
val useCase: DisconnectFromServerUseCase by inject()
return useCase
}
actual val retrieveImageDirectoriesUseCase: RetrieveImageDirectoriesUseCase
get() {
val useCase: RetrieveImageDirectoriesUseCase by inject()
return useCase
}
actual val retrieveSlideshowFromPlaylistUseCase: RetrieveSlideshowFromPlaylistUseCase
get() {
val useCase: RetrieveSlideshowFromPlaylistUseCase by inject()
return useCase
}
actual val retrieveDirectoryContentsUseCase: RetrieveDirectoryContentsUseCase
get() {
val useCase: RetrieveDirectoryContentsUseCase by inject()
return useCase
}
actual val retrieveImageUseCase: RetrieveImageUseCase
get() {
val useCase: RetrieveImageUseCase by inject()
return useCase
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import com.kevinschildhorn.fotopresenter.ui.screens.common.ActionSheetContext
import com.kevinschildhorn.fotopresenter.ui.screens.common.composables.ActionSheet
import com.kevinschildhorn.fotopresenter.ui.screens.common.composables.ButtonState
import com.kevinschildhorn.fotopresenter.ui.screens.common.composables.ConfirmationDialog
import com.kevinschildhorn.fotopresenter.ui.screens.common.composables.FilterDialog
import com.kevinschildhorn.fotopresenter.ui.screens.common.composables.PrimaryTextButton
import com.kevinschildhorn.fotopresenter.ui.screens.playlist.composables.TextEntryDialog

Expand Down Expand Up @@ -64,3 +65,17 @@ fun TextConfirmationDialogPreview() {
)
}

@Preview
@Composable
fun FilterDialogPreview() {
FilterDialog(
"Hello",
{

},
{

},
)
}

Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import android.graphics.BitmapFactory
import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.asAndroidBitmap
import androidx.compose.ui.graphics.asImageBitmap
import java.nio.ByteBuffer
import java.io.ByteArrayOutputStream


actual object SharedImageConverter {
actual fun convertBytes(byteArray: ByteArray): ImageBitmap {
Expand All @@ -14,16 +15,20 @@ actual object SharedImageConverter {
}

actual fun convertImage(imageBitmap: ImageBitmap): ByteArray {
return imageBitmap.asAndroidBitmap().convertToByteArray()
val bitmap = imageBitmap.asAndroidBitmap()
val stream = ByteArrayOutputStream()
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream)
val byteArray = stream.toByteArray()
return byteArray
}

private fun Bitmap.convertToByteArray(): ByteArray {
val size = this.byteCount
val buffer = ByteBuffer.allocate(size)
val bytes = ByteArray(size)
this.copyPixelsToBuffer(buffer)
buffer.rewind()
buffer.get(bytes)
return bytes
val stream = ByteArrayOutputStream()
this.compress(Bitmap.CompressFormat.PNG, 100, stream)
val byteArray = stream.toByteArray()
if (this != null && !this.isRecycled()) {
this.recycle();
}
return byteArray
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,20 @@ import com.kevinschildhorn.fotopresenter.ui.shared.SharedCache
import org.koin.core.module.Module
import org.koin.dsl.module

val baseLogger = Logger(LoggerConfig.default)

val commonModule =
module {
val baseLogger = Logger(LoggerConfig.default)

// Data
single<CacheInterface> { SharedCache }
single { CredentialsDataSource(get()) }
single { CredentialsRepository(get()) }
single { DirectoryDataSource(get()) }
single { DirectoryDataSource(get(), baseLogger.withTag("DirectoryDataSource")) }
single { DirectoryRepository(get()) }
single { ImageRemoteDataSource(get()) }
single { ImageRepository(get()) }
single { ImageCacheDataSource(get()) }
single { ImageCacheDataSource(get(), get(), baseLogger.withTag("ImageCacheDataSource")) }
single { PlaylistDataSource(get(), baseLogger.withTag("PlaylistDataSource")) }
single { PlaylistRepository(get()) }

Expand All @@ -58,7 +59,12 @@ val commonModule =
)
}
factory { RetrieveImageDirectoriesUseCase(baseLogger.withTag("RetrieveImageDirectoriesUseCase")) }
factory { RetrieveSlideshowFromPlaylistUseCase(baseLogger.withTag("RetrieveSlideshowFromPlaylistUseCase")) }
factory {
RetrieveSlideshowFromPlaylistUseCase(
baseLogger.withTag("RetrieveSlideshowFromPlaylistUseCase"),
get()
)
}
factory {
RetrieveDirectoryContentsUseCase(
get(),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.kevinschildhorn.fotopresenter

import com.kevinschildhorn.fotopresenter.domain.RetrieveDirectoryContentsUseCase
import com.kevinschildhorn.fotopresenter.domain.connection.AutoConnectUseCase
import com.kevinschildhorn.fotopresenter.domain.connection.ConnectToServerUseCase
import com.kevinschildhorn.fotopresenter.domain.connection.DisconnectFromServerUseCase
import com.kevinschildhorn.fotopresenter.domain.connection.SaveCredentialsUseCase
import com.kevinschildhorn.fotopresenter.domain.directory.ChangeDirectoryUseCase
import com.kevinschildhorn.fotopresenter.domain.image.RetrieveImageDirectoriesUseCase
import com.kevinschildhorn.fotopresenter.domain.image.RetrieveImageUseCase
import com.kevinschildhorn.fotopresenter.domain.image.RetrieveSlideshowFromPlaylistUseCase

expect object UseCaseFactory {
val connectToServerUseCase: ConnectToServerUseCase
val changeDirectoryUseCase: ChangeDirectoryUseCase
val autoConnectUseCase: AutoConnectUseCase
val saveCredentialsUseCase: SaveCredentialsUseCase
val disconnectFromServerUseCase: DisconnectFromServerUseCase
val retrieveImageDirectoriesUseCase: RetrieveImageDirectoriesUseCase
val retrieveSlideshowFromPlaylistUseCase: RetrieveSlideshowFromPlaylistUseCase
val retrieveDirectoryContentsUseCase: RetrieveDirectoryContentsUseCase
val retrieveImageUseCase: RetrieveImageUseCase
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.kevinschildhorn.fotopresenter.data

import com.kevinschildhorn.fotopresenter.data.network.NetworkDirectoryDetails
import com.kevinschildhorn.fotopresenter.ui.SortingType
import com.kevinschildhorn.fotopresenter.ui.shared.SharedImage

interface Directory {
Expand Down Expand Up @@ -38,6 +39,13 @@ data class DirectoryContents(
val allDirectories: List<Directory>
get() = folders + images

fun sorted(sortingType: SortingType): DirectoryContents {
return DirectoryContents(
folders = folders.sorted(sortingType) as List<FolderDirectory>,
images = images.sorted(sortingType) as List<ImageDirectory>,
)
}

override fun toString(): String {
return """
DirectoryContents:
Expand All @@ -48,3 +56,11 @@ data class DirectoryContents(
"""
}
}

fun List<Directory>.sorted(sortingType: SortingType): List<Directory> =
when (sortingType) {
SortingType.NAME_ASC -> this.sortedBy { it.name }
SortingType.NAME_DESC -> this.sortedByDescending { it.name }
SortingType.TIME_ASC -> this.sortedBy { it.details.dateMillis }
SortingType.TIME_DESC -> this.sortedByDescending { it.details.dateMillis }
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.kevinschildhorn.fotopresenter.data.datasources

import co.touchlab.kermit.Logger
import com.kevinschildhorn.fotopresenter.data.network.NetworkDirectoryDetails
import com.kevinschildhorn.fotopresenter.data.network.NetworkHandler
import com.kevinschildhorn.fotopresenter.data.network.NetworkHandlerError
Expand All @@ -9,11 +10,21 @@ import kotlin.coroutines.cancellation.CancellationException
/**
Fetches Directory info from a NAS
**/
class DirectoryDataSource(private val networkHandler: NetworkHandler) {
class DirectoryDataSource(
private val networkHandler: NetworkHandler,
private val logger: Logger,
) {
@Throws(NetworkHandlerException::class, CancellationException::class)
suspend fun changeDirectory(directoryName: String): String {
logger.i { "Changing directory to $directoryName" }
logger.i { "Is network Connected? ${networkHandler.isConnected}" }
if (!networkHandler.isConnected) throw NetworkHandlerException(NetworkHandlerError.NOT_CONNECTED)

logger.i { "Does the directory exist?" }
//val exists = networkHandler.folderExists(directoryName)
//logger.i { "Does the directory exist? $exists" }

logger.i { "Opening the directory..." }
networkHandler.openDirectory(directoryName)?.let { return it }
throw NetworkHandlerException(NetworkHandlerError.DIRECTORY_NOT_FOUND)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,46 @@
package com.kevinschildhorn.fotopresenter.data.datasources

import androidx.compose.ui.graphics.ImageBitmap
import app.cash.sqldelight.db.SqlDriver
import co.touchlab.kermit.Logger
import com.kevinschildhorn.fotopresenter.PlaylistDatabase
import com.kevinschildhorn.fotopresenter.data.network.NetworkDirectoryDetails
import com.kevinschildhorn.fotopresenter.ui.shared.CacheInterface
import com.kevinschildhorn.fotopresenter.ui.shared.SharedImageConverter

class ImageCacheDataSource(private val cache: CacheInterface) {
fun getImage(directory: NetworkDirectoryDetails): ImageBitmap? = cache.getImage(directory.cacheId)
class ImageCacheDataSource(
private val cache: CacheInterface,
driver: SqlDriver,
private val logger: Logger
) {
private val database = PlaylistDatabase(driver)


fun getImage(directory: NetworkDirectoryDetails): ImageBitmap? {
logger.i { "Getting Image from Cache ${directory.cacheId}" }
return try {
val image = database.imageQueries.selectImageByName(directory.cacheId).executeAsOne()
SharedImageConverter.convertBytes(image.image)
} catch (e: Exception) {
logger.e(e) { "Image NOT found" }

null
}
//return cache.getImage(directory.cacheId)
}

fun saveImage(
directory: NetworkDirectoryDetails,
bitmap: ImageBitmap,
) {
cache.cacheImage(directory.cacheId, bitmap)
logger.i { "Saving Image To Cache ${directory.cacheId}" }
database.imageQueries.insertImage(
directory.cacheId,
SharedImageConverter.convertImage(bitmap)
)
logger.i { "Image Saved" }

//DiscCache.storeFile(directory.cacheId, bitmap)
}

private val NetworkDirectoryDetails.cacheId: String
Expand Down
Loading

0 comments on commit 0dcf6b0

Please sign in to comment.