Skip to content

Commit

Permalink
UI load only file names.
Browse files Browse the repository at this point in the history
- Added individual call for loading each file.
  • Loading branch information
jsixface committed Jan 20, 2025
1 parent 9338200 commit aaedb7d
Show file tree
Hide file tree
Showing 11 changed files with 246 additions and 118 deletions.
11 changes: 7 additions & 4 deletions composeApp/src/commonMain/kotlin/services/Koin.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ import io.ktor.client.plugins.resources.Resources
import io.ktor.serialization.kotlinx.cbor.cbor
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.cbor.Cbor
import org.koin.core.module.dsl.factoryOf
import org.koin.dsl.module
import viewmodels.AppViewModel
import viewmodels.BackupScreenViewModel
import viewmodels.JobsScreenModel
import viewmodels.SettingsScreenModel
Expand All @@ -22,10 +24,11 @@ object Koin {
val services = module {
single { createHttpClient(enableNetworkLogs = true) }

factory { SettingsScreenModel(client = get()) }
factory { JobsScreenModel(client = get()) }
factory { BackupScreenViewModel(client = get()) }
factory { VideoListViewModel(client = get()) }
factoryOf(::AppViewModel)
factoryOf(::BackupScreenViewModel)
factoryOf(::JobsScreenModel)
factoryOf(::SettingsScreenModel)
factoryOf(::VideoListViewModel)
}

@OptIn(ExperimentalSerializationApi::class)
Expand Down
61 changes: 46 additions & 15 deletions composeApp/src/commonMain/kotlin/ui/MainScreen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,42 +3,73 @@ package ui
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.adaptive.navigationsuite.NavigationSuiteScaffold
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import io.github.jsixface.common.CodecsCollection
import org.koin.compose.koinInject
import ui.home.HomeScreen
import ui.model.AppPages
import ui.model.ModelState
import viewmodels.AppViewModel


@Composable
fun MainScreen() {

Box(modifier = Modifier.fillMaxSize()) {
var currentPage by rememberSaveable { mutableStateOf(AppPages.HOME) }
var codecsCollection by remember { mutableStateOf<CodecsCollection?>(null) }
val viewModel = koinInject<AppViewModel>()
var errorLoading by remember { mutableStateOf(false) }

LaunchedEffect(Unit) {
viewModel.codecsCollection.collect {
when (it) {
is ModelState.Init -> {
errorLoading = false
}

NavigationSuiteScaffold(
navigationSuiteItems = {
AppPages.entries.forEach { page ->
item(
icon = { Icon(page.icon, contentDescription = page.title) },
onClick = { currentPage = page },
label = { Text(page.title) },
selected = currentPage == page
)
is ModelState.Error -> {
errorLoading = true
}

is ModelState.Success -> {
errorLoading = false
codecsCollection = it.result
}
}
}
) {
when (currentPage) {
AppPages.HOME -> HomeScreen()
AppPages.JOBS -> JobsScreen()
AppPages.BACKUPS -> BackupsScreen()
AppPages.SETTINGS -> SettingsScreen()
}
if (errorLoading) {
Text("Error Loading!!!", style = MaterialTheme.typography.headlineSmall)
} else {
NavigationSuiteScaffold(
navigationSuiteItems = {
AppPages.entries.forEach { page ->
item(
icon = { Icon(page.icon, contentDescription = page.title) },
onClick = { currentPage = page },
label = { Text(page.title) },
selected = currentPage == page
)
}
}
) {
when (currentPage) {
AppPages.HOME -> HomeScreen(codecsCollection)
AppPages.JOBS -> JobsScreen()
AppPages.BACKUPS -> BackupsScreen()
AppPages.SETTINGS -> SettingsScreen()
}
}
}
}
Expand Down
101 changes: 65 additions & 36 deletions composeApp/src/commonMain/kotlin/ui/home/FileDetails.kt
Original file line number Diff line number Diff line change
@@ -1,37 +1,62 @@
package ui.home

import androidx.compose.foundation.layout.*
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.*
import androidx.compose.material3.Button
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.FilterChip
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedCard
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateMapOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog
import androidx.compose.ui.window.DialogProperties
import io.github.jsixface.common.*
import io.github.jsixface.common.Codec
import io.github.jsixface.common.Conversion
import io.github.jsixface.common.Conversion.Convert
import io.github.jsixface.common.MediaTrack
import io.github.jsixface.common.VideoFile
import org.koin.compose.koinInject
import ui.model.ModelState
import viewmodels.VideoListViewModel

@Composable
fun FileDetailsDialog(file: VideoFile, onDismiss: (Map<MediaTrack, Conversion>?) -> Unit) {
Dialog(
onDismissRequest = { onDismiss(null) },
properties = DialogProperties(usePlatformDefaultWidth = false)
) {
FileDetails(file) { onDismiss(it) }
}
}
fun FileDetails(file: String, onDismiss: (Map<MediaTrack, Conversion>?) -> Unit) {
val viewModel = koinInject<VideoListViewModel>()
var videoFile by remember { mutableStateOf<VideoFile?>(null) }
var errorLoading by remember { mutableStateOf<String?>(null) }
val conversion = remember { mutableStateMapOf<MediaTrack, Conversion>() }
LaunchedEffect(file) {
viewModel.getVideoFile(file).collect {
when (it) {
is ModelState.Success -> {
videoFile = it.result
it.result.audios.forEach { a -> conversion[a] = Conversion.Copy }
it.result.videos.forEach { v -> conversion[v] = Conversion.Copy }
}

@Composable
fun FileDetails(file: VideoFile, onDismiss: (Map<MediaTrack, Conversion>?) -> Unit) {
val conversion = remember {
mutableStateMapOf<MediaTrack, Conversion>().apply {
file.audios.forEach { put(it, Conversion.Copy) }
file.videos.forEach { put(it, Conversion.Copy) }
is ModelState.Error<*> -> {
errorLoading = it.msg
}

is ModelState.Init<*> -> {
videoFile = null
}
}
}
}

Expand All @@ -45,33 +70,37 @@ fun FileDetails(file: VideoFile, onDismiss: (Map<MediaTrack, Conversion>?) -> Un
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally,
) {
Row {
Text(file.fileName, style = MaterialTheme.typography.displaySmall, modifier = padder)
}
videoFile?.let { file ->
Row {
Text(file.fileName, style = MaterialTheme.typography.displaySmall, modifier = padder)
}

if (file.audios.isNotEmpty()) Text("Audio Tracks", style = MaterialTheme.typography.bodyLarge)
LazyColumn {
itemsIndexed(file.audios) { i, track ->
CodecRow(i, track, conversion[track] ?: Conversion.Copy) { conversion[track] = it }
if (file.audios.isNotEmpty()) Text("Audio Tracks", style = MaterialTheme.typography.bodyLarge)
LazyColumn {
itemsIndexed(file.audios) { i, track ->
CodecRow(i, track, conversion[track] ?: Conversion.Copy) { conversion[track] = it }
}
}
}

if (file.videos.isNotEmpty()) Text("Video Tracks", style = MaterialTheme.typography.bodyLarge)
LazyColumn {
itemsIndexed(file.videos) { i, track ->
CodecRow(i, track, conversion[track] ?: Conversion.Copy) { conversion[track] = it }
if (file.videos.isNotEmpty()) Text("Video Tracks", style = MaterialTheme.typography.bodyLarge)
LazyColumn {
itemsIndexed(file.videos) { i, track ->
CodecRow(i, track, conversion[track] ?: Conversion.Copy) { conversion[track] = it }
}
}
}

Row {
Button(onClick = { onDismiss(conversion.toMap()) }, modifier = padder) { Text("Convert") }
Button(onClick = { onDismiss(null) }, modifier = padder) { Text("Cancel") }
Row {
Button(onClick = { onDismiss(conversion.toMap()) }, modifier = padder) { Text("Convert") }
Button(onClick = { onDismiss(null) }, modifier = padder) { Text("Cancel") }
}
} ?: Column(horizontalAlignment = Alignment.CenterHorizontally) {
Text("Loading...", style = MaterialTheme.typography.displayLarge, modifier = padder)
CircularProgressIndicator(modifier = padder)
}
}
}
}

@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun CodecRow(ai: Int, track: MediaTrack, selected: Conversion, onSelect: (Conversion) -> Unit) {
val codecsAvailable = Codec.entries.filter { it.type == track.type }
Expand Down
Loading

0 comments on commit aaedb7d

Please sign in to comment.