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

Adding database #36

Merged
merged 2 commits into from
Dec 14, 2023
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
6 changes: 4 additions & 2 deletions atomik/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ kotlin {
publishLibraryVariants("debug", "release")
}
jvm("desktop")
/*
listOf(
iosX64(),
iosArm64(),
Expand All @@ -44,7 +45,7 @@ kotlin {
iosTarget.binaries.framework {
baseName = "atomik"
}
}
}*/
jvm("desktop")

jvmToolchain(15)
Expand Down Expand Up @@ -77,6 +78,7 @@ kotlin {
api("androidx.core:core-ktx:1.12.0")
}
}
/*
val iosX64Main by getting
val iosArm64Main by getting
val iosSimulatorArm64Main by getting
Expand All @@ -85,7 +87,7 @@ kotlin {
iosX64Main.dependsOn(this)
iosArm64Main.dependsOn(this)
iosSimulatorArm64Main.dependsOn(this)
}
}*/

val desktopMain by getting {
dependsOn(jvmMain)
Expand Down
1 change: 1 addition & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ plugins {
id("org.jetbrains.compose").apply(false)
id("org.jlleitschuh.gradle.ktlint").version("12.0.2").apply(false)
id("dev.icerock.mobile.multiplatform-resources").version("0.23.0").apply(false)
id("app.cash.sqldelight").version("2.0.1").apply(false)
}
12 changes: 12 additions & 0 deletions shared/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ plugins {
id("org.jetbrains.compose")
id("org.jlleitschuh.gradle.ktlint")
id("dev.icerock.mobile.multiplatform-resources")
id("app.cash.sqldelight")
}

kotlin {
Expand Down Expand Up @@ -61,6 +62,7 @@ kotlin {
dependencies {
implementation("com.hierynomus:smbj:0.13.0")
implementation(compose.uiTooling)
implementation("app.cash.sqldelight:sqlite-driver:2.0.1")
}
}

Expand All @@ -72,6 +74,7 @@ kotlin {
api("androidx.appcompat:appcompat:1.6.1")
api("androidx.core:core-ktx:1.12.0")
implementation("io.github.kevinschildhorn:atomik:0.0.6")
implementation("app.cash.sqldelight:android-driver:2.0.1")
}
}
/*
Expand All @@ -84,6 +87,7 @@ kotlin {
iosArm64Main.dependsOn(this)
iosSimulatorArm64Main.dependsOn(this)
resources.srcDirs("src/commonMain/resources")
implementation("app.cash.sqldelight:native-driver:2.0.1")
}*/
val desktopMain by getting {
dependsOn(jvmMain)
Expand Down Expand Up @@ -123,3 +127,11 @@ multiplatformResources {
dependencies {
ktlintRuleset("com.twitter.compose.rules:ktlint:0.0.26")
}

sqldelight {
databases {
create("PlaylistDatabase") {
packageName.set("com.kevinschildhorn.fotopresenter")
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ import android.app.Application
import android.content.Context
import androidx.security.crypto.EncryptedSharedPreferences
import androidx.security.crypto.MasterKey
import app.cash.sqldelight.db.SqlDriver
import com.kevinschildhorn.fotopresenter.data.datasources.CredentialsDataSource
import com.kevinschildhorn.fotopresenter.data.network.NetworkHandler
import com.kevinschildhorn.fotopresenter.data.network.SMBJHandler
import com.kevinschildhorn.fotopresenter.ui.shared.DriverFactory
import com.russhwolf.settings.Settings
import com.russhwolf.settings.SharedPreferencesSettings
import org.koin.core.KoinApplication
Expand Down Expand Up @@ -41,6 +43,7 @@ internal actual val platformModule: Module = module {
single<NetworkHandler> {
SMBJHandler
}
single<SqlDriver> { DriverFactory(context = get()).createDriver() }
}

fun KoinApplication.androidContext(androidContext: Context): KoinApplication {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.kevinschildhorn.fotopresenter.ui.shared

import android.content.Context
import app.cash.sqldelight.db.SqlDriver
import app.cash.sqldelight.driver.android.AndroidSqliteDriver
import com.kevinschildhorn.fotopresenter.PlaylistDatabase

actual class DriverFactory(private val context: Context) {
actual fun createDriver(): SqlDriver {
return AndroidSqliteDriver(PlaylistDatabase.Schema, context, "playlist.db")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ import com.kevinschildhorn.fotopresenter.data.datasources.CredentialsDataSource
import com.kevinschildhorn.fotopresenter.data.datasources.DirectoryDataSource
import com.kevinschildhorn.fotopresenter.data.datasources.ImageCacheDataSource
import com.kevinschildhorn.fotopresenter.data.datasources.ImageRemoteDataSource
import com.kevinschildhorn.fotopresenter.data.datasources.PlaylistDataSource
import com.kevinschildhorn.fotopresenter.data.repositories.CredentialsRepository
import com.kevinschildhorn.fotopresenter.data.repositories.DirectoryRepository
import com.kevinschildhorn.fotopresenter.data.repositories.ImageRepository
import com.kevinschildhorn.fotopresenter.data.repositories.PlaylistRepository
import com.kevinschildhorn.fotopresenter.domain.RetrieveDirectoryContentsUseCase
import com.kevinschildhorn.fotopresenter.domain.connection.AutoConnectUseCase
import com.kevinschildhorn.fotopresenter.domain.connection.ConnectToServerUseCase
Expand All @@ -19,6 +21,7 @@ import com.kevinschildhorn.fotopresenter.domain.image.RetrieveImageDirectoriesUs
import com.kevinschildhorn.fotopresenter.domain.image.RetrieveImageUseCase
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 com.kevinschildhorn.fotopresenter.ui.shared.CacheInterface
import com.kevinschildhorn.fotopresenter.ui.shared.SharedCache
Expand All @@ -38,6 +41,8 @@ val commonModule =
single { ImageRemoteDataSource(get()) }
single { ImageRepository(get()) }
single { ImageCacheDataSource(get()) }
single { PlaylistDataSource(get()) }
single { PlaylistRepository(get()) }

// Domain
factory { ConnectToServerUseCase(get(), baseLogger.withTag("ConnectToServerUseCase")) }
Expand All @@ -59,6 +64,7 @@ val commonModule =
single { LoginViewModel(baseLogger.withTag("LoginViewModel"), get()) }
single { DirectoryViewModel(baseLogger.withTag("DirectoryViewModel")) }
single { SlideshowViewModel(baseLogger.withTag("SlideshowViewModel")) }
single { PlaylistViewModel(get(),baseLogger.withTag("PlaylistViewModel")) }
}

internal expect val platformModule: Module
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package com.kevinschildhorn.fotopresenter.data.datasources

import app.cash.sqldelight.db.SqlDriver
import com.kevinschildhorn.fotopresenter.Playlist
import com.kevinschildhorn.fotopresenter.PlaylistDatabase
import com.kevinschildhorn.fotopresenter.PlaylistImage
import com.kevinschildhorn.fotopresenter.data.ImageDirectory
import org.koin.core.component.KoinComponent

class PlaylistDataSource(
driver: SqlDriver,
) : KoinComponent {

private val database = PlaylistDatabase(driver)

fun createPlaylist(name: String, directories: List<ImageDirectory> = emptyList()): Playlist? {
return try {
//logger?.i { "Creating Playlist $name with images: ${directories.count()}" }
database.playlistQueries.insertPlaylist(name)
val playlist = database.playlistQueries.selectPlaylistByName(name).executeAsOne()
//logger?.i { "Playlist Created, now adding images" }

directories.forEach {
insertPlaylistImage(playlistId = playlist.id, directory = it)
}
playlist
} catch (e: Exception) {
null
}
}

fun getAllPlaylists(): List<Playlist> {
return try {
database.playlistQueries.selectAllPlaylists().executeAsList()
} catch (e: Exception) {
emptyList()
}

}

fun getPlaylistByName(name: String): Playlist? {
return try {
//logger?.i { "Selecting playlist by name $name" }
val playList: Playlist =
database.playlistQueries.selectPlaylistByName(name).executeAsOne()
//logger?.i { "Retrieved Playlist!" }
playList
} catch (e: Exception) {
null
}
}

fun insertPlaylistImage(playlistId: Long, directory: ImageDirectory): PlaylistImage? {
//logger?.i { "Inserting Playlist Image ${directory.name}" }

database.imageDirectoryQueries.insertPlaylistImage(
playlist_id = playlistId,
directory_path = directory.details.fullPath,
directory_id = directory.id.toLong(),
)
return getPlaylistImage(playlistId, directory.details.fullPath)
}

fun getPlaylistImage(playlistId: Long, directoryPath: String): PlaylistImage? {
return try {
//logger?.i { "Selecting Playlist Image $playlistId" }
val image: PlaylistImage =
database.imageDirectoryQueries.selectPlaylistImage(playlistId, directoryPath)
.executeAsOne()
//logger?.i { "Selecting Playlist Image" }
image
} catch (e: Exception) {
null
}
}

fun deletePlaylistByName(name: String): Boolean {
return try {
val playlist = database.playlistQueries.selectPlaylistByName(name).executeAsOne()
database.playlistQueries.deletePlaylist(playlist.name)
database.imageDirectoryQueries.deletePlaylist(playlist.id)
true
} catch (e: Exception) {
false
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.kevinschildhorn.fotopresenter.data.repositories

import com.kevinschildhorn.fotopresenter.Playlist
import com.kevinschildhorn.fotopresenter.PlaylistImage
import com.kevinschildhorn.fotopresenter.data.ImageDirectory
import com.kevinschildhorn.fotopresenter.data.datasources.PlaylistDataSource

class PlaylistRepository(
private val playlistDataSource: PlaylistDataSource,
) {

fun createPlaylist(name: String, directories: List<ImageDirectory> = emptyList()): Playlist? =
playlistDataSource.createPlaylist(name, directories)

fun getAllPlaylists(): List<Playlist> =
playlistDataSource.getAllPlaylists()

fun getPlaylistByName(name: String): Playlist? =
playlistDataSource.getPlaylistByName(name)

fun insertPlaylistImage(playlistId: Long, directory: ImageDirectory): PlaylistImage? =
playlistDataSource.insertPlaylistImage(playlistId, directory)

fun getPlaylistImage(playlistId: Long, directoryPath: String): PlaylistImage? =
playlistDataSource.getPlaylistImage(playlistId, directoryPath)

fun deletePlaylistByName(name: String): Boolean =
playlistDataSource.deletePlaylistByName(name)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.kevinschildhorn.fotopresenter.ui.screens.playlist


import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue

@Composable
fun PlaylistScreen(
viewModel: PlaylistViewModel,
onLoginSuccess: () -> Unit,
) {
val uiState by viewModel.uiState.collectAsState()
LazyColumn {
items(uiState.playlists) {
Text(it.name)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.kevinschildhorn.fotopresenter.ui.screens.playlist

import com.kevinschildhorn.fotopresenter.Playlist
import com.kevinschildhorn.fotopresenter.ui.UiState
import com.kevinschildhorn.fotopresenter.ui.screens.common.ScreenState

data class PlaylistScreenState(
val playlists: List<Playlist> = emptyList(),
val selectedId: Long = 0L,
override val state: UiState = UiState.IDLE,
) : ScreenState
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.kevinschildhorn.fotopresenter.ui.screens.playlist

import co.touchlab.kermit.Logger
import com.kevinschildhorn.fotopresenter.data.repositories.PlaylistRepository
import com.kevinschildhorn.fotopresenter.ui.shared.ViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
import org.koin.core.component.KoinComponent

class PlaylistViewModel(
private val playlistRepository: PlaylistRepository,
private val logger: Logger,
) : ViewModel(), KoinComponent {

private val _uiState = MutableStateFlow(PlaylistScreenState())
val uiState: StateFlow<PlaylistScreenState> = _uiState.asStateFlow()

init {
refreshPlaylists()
}

fun refreshPlaylists(){
val allPlaylists = playlistRepository.getAllPlaylists()
_uiState.update { it.copy(playlists = allPlaylists) }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.kevinschildhorn.fotopresenter.ui.shared

import app.cash.sqldelight.db.SqlDriver

expect class DriverFactory {
fun createDriver(): SqlDriver
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
CREATE TABLE PlaylistImage (
id INTEGER PRIMARY KEY NOT NULL,
playlist_id INTEGER NOT NULL,
directory_path TEXT NOT NULL,
directory_id INTEGER NOT NULL
);

insertPlaylistImage:
INSERT INTO PlaylistImage(playlist_id, directory_path, directory_id)
VALUES (?, ?, ?);

selectPlaylistImage:
SELECT *
FROM PlaylistImage
WHERE playlist_id = ? AND directory_path = ?;

deletePlaylistImage:
DELETE
FROM PlaylistImage
WHERE directory_path = ?;

deletePlaylist:
DELETE
FROM PlaylistImage
WHERE playlist_id = ?;
Loading