Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ks/adding coil #56

Merged
merged 6 commits into from
Oct 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions androidApp/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import org.gradle.kotlin.dsl.get
import org.gradle.kotlin.dsl.implementation
import org.gradle.kotlin.dsl.java

plugins {
Expand All @@ -18,6 +19,7 @@ kotlin {
implementation(project(":shared"))
implementation(libs.koin.android)
implementation(libs.firebase.crashlytics)
implementation(libs.coil)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,40 @@ import MainView
import android.os.Bundle
import androidx.activity.compose.setContent
import androidx.appcompat.app.AppCompatActivity
import coil3.ImageLoader
import coil3.compose.setSingletonImageLoaderFactory
import com.kevinschildhorn.fotopresenter.SMBJFetcher
import com.kevinschildhorn.fotopresenter.data.network.NetworkHandler
import com.kevinschildhorn.fotopresenter.startKoin
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
import org.koin.androidx.viewmodel.ext.android.viewModel
import org.koin.core.component.KoinComponent
import org.koin.core.component.inject

class MainActivity : AppCompatActivity(), KoinComponent {

private val loginViewModel by viewModel<LoginViewModel>()
private val directoryViewModel by viewModel<DirectoryViewModel>()
private val slideshowViewModel by viewModel<SlideshowViewModel>()
private val playlistViewModel by viewModel<PlaylistViewModel>()
private val networkHandler: NetworkHandler by inject()

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
startKoin(this)

setContent {
setSingletonImageLoaderFactory { context ->
ImageLoader.Builder(context)
.components {
add(SMBJFetcher.Factory(networkHandler))
}
.build()
}

MainView(loginViewModel, directoryViewModel, slideshowViewModel, playlistViewModel)
}
}
Expand Down
2 changes: 2 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ agp = "8.5.2"
appcompat = "1.7.0"
atomik = "0.0.6"
cache4k = "0.12.0"
coil = "3.0.0-rc01"
core-ktx = "1.13.1"
eva-icons = "1.1.0"
firebase-crashlytics = "19.2.0"
Expand Down Expand Up @@ -49,6 +50,7 @@ firebase-crashlytics = { module = "com.google.firebase:firebase-crashlytics", ve
kermit = { module = "co.touchlab:kermit", version.ref = "kermit" }
kermit-koin = { module = "co.touchlab:kermit-koin", version.ref = "kermit-koin" }
kim = { module = "com.ashampoo:kim", version.ref = "kim" }
coil = { module = "io.coil-kt.coil3:coil-compose", version.ref = "coil" }
koin-android = { module = "io.insert-koin:koin-android", version.ref = "koin-core" }
koin-core = { module = "io.insert-koin:koin-core", version.ref = "koin-core" }
koin-test = { module = "io.insert-koin:koin-test", version.ref = "koin-test" }
Expand Down
2 changes: 2 additions & 0 deletions shared/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ kotlin {
implementation(libs.multiplatform.settings)
implementation(libs.kotlinx.datetime)
implementation(libs.kim)
implementation(libs.coil)

}
}
val commonTest by getting {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package com.kevinschildhorn.fotopresenter

import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import coil3.ImageLoader
import coil3.asImage
import coil3.decode.DataSource
import coil3.fetch.FetchResult
import coil3.fetch.Fetcher
import coil3.fetch.ImageFetchResult
import coil3.request.Options
import com.hierynomus.smbj.share.File
import com.kevinschildhorn.fotopresenter.data.datasources.ImageCacheDataSource
import com.kevinschildhorn.fotopresenter.data.network.NetworkDirectoryDetails
import com.kevinschildhorn.fotopresenter.data.network.NetworkHandler
import com.kevinschildhorn.fotopresenter.ui.shared.DriverFactory
import com.kevinschildhorn.fotopresenter.ui.shared.SharedCache
import com.kevinschildhorn.fotopresenter.ui.shared.getScaledDimensions
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import kotlin.math.roundToInt

class SMBJFetcher(
private val directoryDetails: NetworkDirectoryDetails,
private val networkHandler: NetworkHandler,
context: Context,
) : Fetcher {

val imageCacheDataSource = ImageCacheDataSource(
cache = SharedCache,
driver = DriverFactory(context).createDriver(),
logger = baseLogger.withTag("ImageCacheDataSource")
)

override suspend fun fetch(): FetchResult? {
return withContext(Dispatchers.IO) {
imageCacheDataSource.getImage(directoryDetails)
if (networkHandler.isConnected) {
val image = networkHandler.openImage(path = directoryDetails.fullPath)
val file = image?.file
if (file != null) {
val bitmap = getBitmapFromFile(file, 64)
if (bitmap != null) {
file.close()
ImageFetchResult(
image = bitmap.asImage(),
isSampled = true,
dataSource = DataSource.NETWORK,
)
} else {
throw Exception("Failed to fetch image from FTP")
}
} else {
throw Exception("Failed to fetch image from FTP")
}
} else {
throw Exception("Failed to fetch image from FTP")
}
}
}

private fun getBitmapFromFile(file: File, size: Int): Bitmap? {

val options = BitmapFactory.Options()
options.inJustDecodeBounds = true
BitmapFactory.decodeStream(file.inputStream, null, options)

val height: Int = options.outHeight
val width: Int = options.outWidth
val dimensions = getScaledDimensions(width, height, size)
val heightRatio: Int = (height.toFloat() / dimensions.second.toFloat()).roundToInt()
val widthRatio: Int = (width.toFloat() / dimensions.first.toFloat()).roundToInt()
options.inSampleSize = if (heightRatio < widthRatio) heightRatio else widthRatio

options.inJustDecodeBounds = false
return BitmapFactory.decodeStream(file.inputStream, null, options)
}

class Factory(private val networkHandler: NetworkHandler) : Fetcher.Factory<NetworkDirectoryDetails> {
override fun create(
data: NetworkDirectoryDetails,
options: Options,
imageLoader: ImageLoader
): Fetcher? = SMBJFetcher(data, networkHandler, options.context)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@ package com.kevinschildhorn.fotopresenter.ui.compose
import androidx.compose.foundation.layout.Column
import androidx.compose.runtime.Composable
import androidx.compose.ui.tooling.preview.Preview
import com.kevinschildhorn.fotopresenter.data.State
import com.kevinschildhorn.fotopresenter.data.network.DefaultNetworkDirectoryDetails
import com.kevinschildhorn.fotopresenter.data.network.MockNetworkDirectoryDetails
import com.kevinschildhorn.fotopresenter.data.network.NetworkDirectoryDetails
import com.kevinschildhorn.fotopresenter.ui.screens.directory.DirectoryGridCellState
import com.kevinschildhorn.fotopresenter.ui.screens.directory.composables.grid.DirectoryGridCell
import com.kevinschildhorn.fotopresenter.ui.screens.directory.composables.grid.DirectoryGrid
import com.kevinschildhorn.fotopresenter.ui.screens.directory.composables.grid.FolderDirectoryGridCell
import com.kevinschildhorn.fotopresenter.ui.screens.directory.DirectoryGridState
import com.kevinschildhorn.fotopresenter.ui.screens.directory.FolderDirectoryGridCellState
import com.kevinschildhorn.fotopresenter.ui.screens.directory.ImageDirectoryGridCellState
import com.kevinschildhorn.fotopresenter.ui.screens.directory.composables.navbar.DirectoryNavigationBar
import com.kevinschildhorn.fotopresenter.ui.screens.directory.composables.navbar.DirectoryNavigationItem

Expand All @@ -25,7 +26,7 @@ fun BaseDirectoryPreview() {
@Composable
fun FolderDirectoryEmptyPreview() {
Column {
FolderDirectoryGridCell(FolderDirectoryGridCellState("Hello",0))
FolderDirectoryGridCell(DirectoryGridCellState.Folder("Hello",0))
}
}

Expand All @@ -35,10 +36,10 @@ fun DirectoryGridPreview() {
DirectoryGrid(
directoryContent = DirectoryGridState(
folderStates = listOf(
FolderDirectoryGridCellState("Hello",0),
DirectoryGridCellState.Folder("Hello",0),
),
imageStates = mutableListOf(
ImageDirectoryGridCellState(State.IDLE,"Hello", 1)
DirectoryGridCellState.Image(MockNetworkDirectoryDetails(),"Hello", 1)
)
),
onFolderPressed = {},
Expand Down
1 change: 0 additions & 1 deletion shared/src/commonMain/kotlin/App.kt
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ fun App(
typography = FotoTypography(),
shapes = fotoShapes,
) {

Scaffold { innerPadding ->
NavHost(
navController = navController,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,9 @@ class DefaultNetworkDirectoryDetails(
override val id: Int,
override val dateMillis: Long = Clock.System.now().toEpochMilliseconds()
) : NetworkDirectoryDetails

class MockNetworkDirectoryDetails(
override val fullPath: String = "",
override val id: Int = 0,
override val dateMillis: Long = Clock.System.now().toEpochMilliseconds()
) : NetworkDirectoryDetails
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,15 @@ class DirectoryRepository(
val imageDirectories: List<NetworkDirectoryDetails> =
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 }
)
},
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,6 @@ class RetrieveDirectoryContentsUseCase(
) {
suspend operator fun invoke(path: String): DirectoryContents {
logger.i { "Getting directory Contents at path $path" }
val directoryContents = directoryRepository.getDirectoryContents(path)
return directoryContents.updateImages {
logger.i { "Updating Image File ${it.name}" }
imageRepository.getImage(it)
}
return directoryRepository.getDirectoryContents(path)
}
}

private suspend fun DirectoryContents.updateImages(block: suspend (NetworkDirectoryDetails) -> SharedImage?): DirectoryContents =
this.copy(
images =
images.map {
ImageDirectory(
it.details,
it.metaData,
image = block(it.details)
)
},
)
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,6 @@ fun DirectoryScreen(
val imageUiState by viewModel.imageUiState.collectAsState()
var overlayVisible by remember { mutableStateOf(DirectoryOverlay.NONE) }

// Navigation
uiState.slideshowDetails?.let {
onStartSlideshow(it)
}

//region UI
Column {
Row(horizontalArrangement = Arrangement.SpaceBetween) {
Expand Down Expand Up @@ -103,24 +98,6 @@ fun DirectoryScreen(
},
modifier = Modifier.padding(Padding.SMALL.dp)
)
if (uiState.imageCountString.isNotEmpty()) {
Text(
uiState.imageCountString,
modifier = Modifier.fillMaxWidth(),
textAlign = TextAlign.Center,
style = FotoTypography().caption,
color = fotoColors.onBackground,
)
LinearProgressIndicator(
progress = uiState.currentImageCount.toFloat() / uiState.totalImageCount.toFloat(),
modifier = Modifier.fillMaxWidth()
.height(25.dp)
.padding(horizontal = Padding.EXTRA_LARGE.dp, vertical = Padding.SMALL.dp)
.clip(RoundedCornerShape(5.dp)),
color = fotoColors.primary,
)

}
DirectoryGrid(
uiState.directoryGridState,
onFolderPressed = {
Expand Down Expand Up @@ -149,6 +126,7 @@ fun DirectoryScreen(
when (it.action) {
ActionSheetAction.START_SLIDESHOW -> {
viewModel.startSlideshow()
onStartSlideshow(uiState.slideshowDetails!!)
overlayVisible = DirectoryOverlay.NONE
viewModel.setSelectedDirectory(null)
}
Expand Down Expand Up @@ -223,6 +201,7 @@ fun DirectoryScreen(
},
onConfirmation = {
viewModel.logout()
onLogout()
overlayVisible = DirectoryOverlay.NONE
},
)
Expand Down
Loading
Loading