diff --git a/.github/workflows/build-project.yml b/.github/workflows/build-project.yml new file mode 100644 index 00000000..6984225d --- /dev/null +++ b/.github/workflows/build-project.yml @@ -0,0 +1,71 @@ +name: Build Variant artifacts + +on: + workflow_dispatch: + push: + branches: [main] + pull_request: + branches: [main] + +concurrency: + group: build-${{ github.ref }} + cancel-in-progress: true + +jobs: + code-formatting: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + + - name: Setup Java + uses: actions/setup-java@v5 + with: + java-version: 17 + distribution: zulu + cache: 'gradle' + + - name: Check Spotless + run: ./gradlew spotlessCheck + + build_android: + name: Build Android app + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v5 + + - name: Set up Java + uses: actions/setup-java@v5 + with: + distribution: zulu + java-version: 17 + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v5 + with: + cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }} + + - name: Build app + run: ./gradlew assembleDebug lintDebug + + build_ios: + name: Build iOS app + runs-on: macos-latest + + steps: + - uses: maxim-lobanov/setup-xcode@v1 + with: + xcode-version: latest-stable + + - name: Checkout + uses: actions/checkout@v5 + + - name: Build iOS app + uses: mxcl/xcodebuild@v3 + with: + xcode: ^16 + scheme: Variant + platform: iOS + action: build + working-directory: iosVariant \ No newline at end of file diff --git a/.spotless/copyright.txt b/.spotless/copyright.txt new file mode 100644 index 00000000..bd40a287 --- /dev/null +++ b/.spotless/copyright.txt @@ -0,0 +1,17 @@ +/* + * Variant - A digital comic book reading application for the iPad and Android tablets. + * Copyright (C) $YEAR, The ComiXed Project + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ \ No newline at end of file diff --git a/androidVariant/build.gradle.kts b/androidVariant/build.gradle.kts index 8c7f041d..796b8085 100644 --- a/androidVariant/build.gradle.kts +++ b/androidVariant/build.gradle.kts @@ -1,51 +1,44 @@ plugins { - alias(libs.plugins.android.application) - alias(libs.plugins.kotlin.android) - alias(libs.plugins.compose.compiler) + alias(libs.plugins.android.application) + alias(libs.plugins.kotlin.android) + alias(libs.plugins.compose.compiler) } android { - namespace = "org.comixedproject.variant.android" - compileSdk = 34 - defaultConfig { - applicationId = "org.comixedproject.variant.android" - minSdk = 26 - targetSdk = 34 - versionCode = 1 - versionName = "0.2.dev" - multiDexEnabled = true - } - buildFeatures { - compose = true - } - packaging { - resources { - excludes += "/META-INF/{AL2.0,LGPL2.1}" - } - } - buildTypes { - getByName("release") { - isMinifyEnabled = false - } - } - compileOptions { - isCoreLibraryDesugaringEnabled = true - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 - } - kotlinOptions { - jvmTarget = JavaVersion.VERSION_17.toString() + namespace = "org.comixedproject.variant.android" + compileSdk = 36 + defaultConfig { + applicationId = "org.comixedproject.variant.android" + minSdk = 26 + targetSdk = 36 + versionCode = 1 + versionName = "0.2.dev" + multiDexEnabled = true + } + buildFeatures { compose = true } + packaging { resources { excludes += "/META-INF/{AL2.0,LGPL2.1}" } } + buildTypes { + getByName("release") { + isMinifyEnabled = true + isShrinkResources = true } + } + compileOptions { + isCoreLibraryDesugaringEnabled = true + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + } + kotlin { jvmToolchain(17) } } dependencies { - implementation(projects.shared) - implementation(libs.koin.android) - implementation(libs.bundles.android.compose) - implementation(libs.compose.ui) - implementation(libs.compose.ui.tooling.preview) - implementation(libs.androidx.activity.compose) - debugImplementation(libs.compose.ui.tooling) + implementation(projects.shared) + implementation(libs.koin.android) + implementation(libs.bundles.android.compose) + implementation(libs.compose.ui) + implementation(libs.compose.ui.tooling.preview) + implementation(libs.androidx.activity.compose) + debugImplementation(libs.compose.ui.tooling) - coreLibraryDesugaring(libs.desugar.jdk.libs) -} \ No newline at end of file + coreLibraryDesugaring(libs.desugar.jdk.libs) +} diff --git a/androidVariant/src/main/AndroidManifest.xml b/androidVariant/src/main/AndroidManifest.xml index a9b05e5d..469923a9 100644 --- a/androidVariant/src/main/AndroidManifest.xml +++ b/androidVariant/src/main/AndroidManifest.xml @@ -20,4 +20,4 @@ - \ No newline at end of file + diff --git a/androidVariant/src/main/java/org/comixedproject/variant/android/Fixtures.kt b/androidVariant/src/main/java/org/comixedproject/variant/android/Fixtures.kt index a94b96ed..5578f0c3 100644 --- a/androidVariant/src/main/java/org/comixedproject/variant/android/Fixtures.kt +++ b/androidVariant/src/main/java/org/comixedproject/variant/android/Fixtures.kt @@ -24,104 +24,78 @@ import org.comixedproject.variant.model.library.ComicBookMetadata import org.comixedproject.variant.model.library.ComicPage import org.comixedproject.variant.model.library.DirectoryEntry -val DIRECTORY_LIST = listOf( +val DIRECTORY_LIST = + listOf( + DirectoryEntry(1, "1", "All Comics", "/api/v1/all", 0, "/api/v1/root", "", true, null), DirectoryEntry( - 1, - "1", - "All Comics", - "/api/v1/all", - 0, - "/api/v1/root", - "", - true, - null + 2, + "2", + "Unread Comics", + "/api/v1/all?unread=true", + 0, + "/api/v1/root", + "", + true, + null, ), + DirectoryEntry(3, "3", "Collections", "/api/v1/collections", 0, "/api/v1/root", "", true, null), DirectoryEntry( - 2, - "2", - "Unread Comics", - "/api/v1/all?unread=true", - 0, - "/api/v1/root", - "", - true, - null + 4, + "4", + "Reading Lists", + "/api/v1/lists/reading", + 0, + "/api/v1/root", + "", + true, + null, ), + DirectoryEntry(5, "5", "Smart Lists", "/api/v1/lists/smart", 0, "/api/v1/root", "", true, null), DirectoryEntry( - 3, - "3", - "Collections", - "/api/v1/collections", - 0, - "/api/v1/root", - "", - true, - null + 11, + "11", + "The Amazing Spider-Man V2018 #75 (unknown)", + "Amazing Spider-Man #75 (v2018) (No Cover Date).cbz", + (32 * BYTES_PER_MB).toLong(), + "/api/v1/lists/reading", + "/api/v1/root", + false, + "", ), DirectoryEntry( - 4, - "4", - "Reading Lists", - "/api/v1/lists/reading", - 0, - "/api/v1/root", - "", - true, - null + 12, + "12", + "The Amazing Spider-Man V2022 #75 (unknown)", + "Amazing Spider-Man #6 (v2022) (Sep 2022).cbz", + (32 * BYTES_PER_MB).toLong(), + "/api/v1/lists/smart", + "/api/v1/root", + false, + "", ), DirectoryEntry( - 5, - "5", - "Smart Lists", - "/api/v1/lists/smart", - 0, - "/api/v1/root", - "", - true, - null + 13, + "13", + "[unknown] V???? #? (unknown)", + "Unknown VUnknown #Unknown (Unknown).cbz", + (32 * BYTES_PER_MB).toLong(), + "/api/v1/lists/smart", + "/api/v1/root", + false, + "", ), - DirectoryEntry( - 11, - "11", - "The Amazing Spider-Man V2018 #75 (unknown)", - "Amazing Spider-Man #75 (v2018) (No Cover Date).cbz", - (32 * BYTES_PER_MB).toLong(), - "/api/v1/lists/reading", - "/api/v1/root", - false, - "" - ), - DirectoryEntry( - 12, - "12", - "The Amazing Spider-Man V2022 #75 (unknown)", - "Amazing Spider-Man #6 (v2022) (Sep 2022).cbz", - (32 * BYTES_PER_MB).toLong(), - "/api/v1/lists/smart", - "/api/v1/root", - false, - "" - ), - DirectoryEntry( - 13, - "13", - "[unknown] V???? #? (unknown)", - "Unknown VUnknown #Unknown (Unknown).cbz", - (32 * BYTES_PER_MB).toLong(), - "/api/v1/lists/smart", - "/api/v1/root", - false, - "" - ) -) + ) -val COMIC_BOOK_LIST = DIRECTORY_LIST.filter { !it.isDirectory }.map { - ComicBook( +val COMIC_BOOK_LIST = + DIRECTORY_LIST.filter { !it.isDirectory } + .map { + ComicBook( it.path, it.filename, (it.filename.length * 1024).toLong(), System.currentTimeMillis(), ComicBookMetadata("Marvel", "The Amazing Spider-Man", "1963", "181"), - mutableListOf(ComicPage("page-0.jpg")) - ) -}.toList() + mutableListOf(ComicPage("page-0.jpg")), + ) + } + .toList() diff --git a/androidVariant/src/main/java/org/comixedproject/variant/android/MainActivity.kt b/androidVariant/src/main/java/org/comixedproject/variant/android/MainActivity.kt index c05afedf..a3b3a668 100644 --- a/androidVariant/src/main/java/org/comixedproject/variant/android/MainActivity.kt +++ b/androidVariant/src/main/java/org/comixedproject/variant/android/MainActivity.kt @@ -38,73 +38,64 @@ import org.koin.androidx.compose.koinViewModel private const val TAG = "MainActivity" class MainActivity : ComponentActivity() { - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) - setContent { - val variantViewModel: VariantViewModel = koinViewModel() - val directory = applicationContext.filesDir.path + setContent { + val variantViewModel: VariantViewModel = koinViewModel() + val directory = applicationContext.filesDir.path - variantViewModel.setLibraryDirectory(directory) + variantViewModel.setLibraryDirectory(directory) - VariantTheme { - val comicBook by variantViewModel.comicBook.collectAsState() - val comicBookList by variantViewModel.comicBookList.collectAsState() - val loading by variantViewModel.loading.collectAsState() - val browsingState by variantViewModel.browsingState.collectAsState() - val selectionMode by variantViewModel.selectionMode.collectAsState() - val selectionList by variantViewModel.selectionList.collectAsState() + VariantTheme { + val comicBook by variantViewModel.comicBook.collectAsState() + val comicBookList by variantViewModel.comicBookList.collectAsState() + val loading by variantViewModel.loading.collectAsState() + val browsingState by variantViewModel.browsingState.collectAsState() + val selectionMode by variantViewModel.selectionMode.collectAsState() + val selectionList by variantViewModel.selectionList.collectAsState() - val coroutineScope = rememberCoroutineScope() + val coroutineScope = rememberCoroutineScope() - Surface( - modifier = Modifier.fillMaxSize(), - color = MaterialTheme.colorScheme.background - ) { - HomeView( - comicBook, - comicBookList, - browsingState, - loading, - selectionMode, - selectionList, - variantViewModel.address, - variantViewModel.username, - variantViewModel.password, - onLoadDirectory = { path, reload -> - coroutineScope.launch(Dispatchers.IO) { - Log.debug(TAG, "Loading directory: ${path} reload=${reload}") - variantViewModel.loadDirectory(path, reload) - } - }, - onDownloadFile = { path, filename -> - coroutineScope.launch(Dispatchers.IO) { - Log.debug(TAG, "Downloading file: ${path} filename=${filename}") - variantViewModel.downloadFile(path, filename) - } - }, - onReadComicBook = { comicBook -> - variantViewModel.readComicBook(comicBook) - }, - onSetSelectionMode = { enabled -> - variantViewModel.setSelectMode(enabled) - }, - onUpdateSelection = { comicBook -> - variantViewModel.updateSelectionList(comicBook.path) - }, - onDeleteSelections = { - coroutineScope.launch(Dispatchers.Unconfined) { - variantViewModel.deleteSelections() - } - }, - onSaveSettings = { address, username, password -> - variantViewModel.address = address - variantViewModel.username = username - variantViewModel.password = password - } - ) - } - } + Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background) { + HomeView( + comicBook, + comicBookList, + browsingState, + loading, + selectionMode, + selectionList, + variantViewModel.address, + variantViewModel.username, + variantViewModel.password, + onLoadDirectory = { path, reload -> + coroutineScope.launch(Dispatchers.IO) { + Log.debug(TAG, "Loading directory: ${path} reload=${reload}") + variantViewModel.loadDirectory(path, reload) + } + }, + onDownloadFile = { path, filename -> + coroutineScope.launch(Dispatchers.IO) { + Log.debug(TAG, "Downloading file: ${path} filename=${filename}") + variantViewModel.downloadFile(path, filename) + } + }, + onReadComicBook = { comicBook -> variantViewModel.readComicBook(comicBook) }, + onSetSelectionMode = { enabled -> variantViewModel.setSelectMode(enabled) }, + onUpdateSelection = { comicBook -> + variantViewModel.updateSelectionList(comicBook.path) + }, + onDeleteSelections = { + coroutineScope.launch(Dispatchers.Unconfined) { variantViewModel.deleteSelections() } + }, + onSaveSettings = { address, username, password -> + variantViewModel.address = address + variantViewModel.username = username + variantViewModel.password = password + }, + ) } + } } + } } diff --git a/androidVariant/src/main/java/org/comixedproject/variant/android/VariantApp.kt b/androidVariant/src/main/java/org/comixedproject/variant/android/VariantApp.kt index f8b9926f..8bd7d109 100644 --- a/androidVariant/src/main/java/org/comixedproject/variant/android/VariantApp.kt +++ b/androidVariant/src/main/java/org/comixedproject/variant/android/VariantApp.kt @@ -29,19 +29,21 @@ import org.koin.dsl.module lateinit var koin: Koin class VariantApp : Application() { - override fun onCreate() { - super.onCreate() - VariantAppContext.setUp(applicationContext) + override fun onCreate() { + super.onCreate() + VariantAppContext.setUp(applicationContext) - koin = - initKoin( - appModule = module { - single { this@VariantApp } + koin = + initKoin( + appModule = + module { + single { this@VariantApp } - single { - get().getSharedPreferences("VariantApp", Context.MODE_PRIVATE) - } - } - ).koin - } -} \ No newline at end of file + single { + get().getSharedPreferences("VariantApp", Context.MODE_PRIVATE) + } + } + ) + .koin + } +} diff --git a/androidVariant/src/main/java/org/comixedproject/variant/android/VariantTheme.kt b/androidVariant/src/main/java/org/comixedproject/variant/android/VariantTheme.kt index 91b26ffd..09aeefe8 100644 --- a/androidVariant/src/main/java/org/comixedproject/variant/android/VariantTheme.kt +++ b/androidVariant/src/main/java/org/comixedproject/variant/android/VariantTheme.kt @@ -34,40 +34,32 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp @Composable -fun VariantTheme( - darkTheme: Boolean = isSystemInDarkTheme(), - content: @Composable () -> Unit -) { - val colors = if (darkTheme) { - darkColorScheme( - primary = Color(0xFFBB86FC), - secondary = Color(0xFF03DAC5), - tertiary = Color(0xFF3700B3) - ) +fun VariantTheme(darkTheme: Boolean = isSystemInDarkTheme(), content: @Composable () -> Unit) { + val colors = + if (darkTheme) { + darkColorScheme( + primary = Color(0xFFBB86FC), + secondary = Color(0xFF03DAC5), + tertiary = Color(0xFF3700B3), + ) } else { - lightColorScheme( - primary = Color(0xFF6200EE), - secondary = Color(0xFF03DAC5), - tertiary = Color(0xFF3700B3) - ) + lightColorScheme( + primary = Color(0xFF6200EE), + secondary = Color(0xFF03DAC5), + tertiary = Color(0xFF3700B3), + ) } - val typography = Typography( - bodyMedium = TextStyle( - fontFamily = FontFamily.Default, - fontWeight = FontWeight.Normal, - fontSize = 16.sp - ) + val typography = + Typography( + bodyMedium = + TextStyle(fontFamily = FontFamily.Default, fontWeight = FontWeight.Normal, fontSize = 16.sp) ) - val shapes = Shapes( - small = RoundedCornerShape(4.dp), - medium = RoundedCornerShape(4.dp), - large = RoundedCornerShape(0.dp) + val shapes = + Shapes( + small = RoundedCornerShape(4.dp), + medium = RoundedCornerShape(4.dp), + large = RoundedCornerShape(0.dp), ) - MaterialTheme( - colorScheme = colors, - typography = typography, - shapes = shapes, - content = content - ) + MaterialTheme(colorScheme = colors, typography = typography, shapes = shapes, content = content) } diff --git a/androidVariant/src/main/java/org/comixedproject/variant/android/ui/DismissBackground.kt b/androidVariant/src/main/java/org/comixedproject/variant/android/ui/DismissBackground.kt index 64c7c46a..cd758df8 100644 --- a/androidVariant/src/main/java/org/comixedproject/variant/android/ui/DismissBackground.kt +++ b/androidVariant/src/main/java/org/comixedproject/variant/android/ui/DismissBackground.kt @@ -38,28 +38,20 @@ import androidx.compose.ui.unit.dp @Composable fun DismissBackground(dismissState: SwipeToDismissBoxState) { - val color = when (dismissState.dismissDirection) { - SwipeToDismissBoxValue.StartToEnd -> Color(0xFFFF1744) - SwipeToDismissBoxValue.EndToStart -> Color(0xFF1DE9B6) - SwipeToDismissBoxValue.Settled -> Color.Transparent + val color = + when (dismissState.dismissDirection) { + SwipeToDismissBoxValue.StartToEnd -> Color(0xFFFF1744) + SwipeToDismissBoxValue.EndToStart -> Color(0xFF1DE9B6) + SwipeToDismissBoxValue.Settled -> Color.Transparent } - Row( - modifier = Modifier - .fillMaxSize() - .background(color) - .padding(12.dp, 8.dp), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.SpaceBetween - ) { - Icon( - Icons.Default.Delete, - contentDescription = "delete" - ) - Spacer(modifier = Modifier) - Icon( - imageVector = Icons.Default.Edit, - contentDescription = "Archive" - ) - } -} \ No newline at end of file + Row( + modifier = Modifier.fillMaxSize().background(color).padding(12.dp, 8.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween, + ) { + Icon(Icons.Default.Delete, contentDescription = "delete") + Spacer(modifier = Modifier) + Icon(imageVector = Icons.Default.Edit, contentDescription = "Archive") + } +} diff --git a/androidVariant/src/main/java/org/comixedproject/variant/android/view/AppDestination.kt b/androidVariant/src/main/java/org/comixedproject/variant/android/view/AppDestination.kt index 6fdf3800..52128c2d 100644 --- a/androidVariant/src/main/java/org/comixedproject/variant/android/view/AppDestination.kt +++ b/androidVariant/src/main/java/org/comixedproject/variant/android/view/AppDestination.kt @@ -21,7 +21,7 @@ package org.comixedproject.variant.android.view import org.comixedproject.variant.android.R enum class AppDestination(val icon: Int, val label: Int) { - COMICS(R.drawable.ic_comic_library, R.string.comicsDestinationLabel), - BROWSE(R.drawable.ic_browse_library, R.string.browseServerDestinationLabel), - SETTINGS(R.drawable.ic_settings, R.string.settingsDestinationLabel) -} \ No newline at end of file + COMICS(R.drawable.ic_comic_library, R.string.comicsDestinationLabel), + BROWSE(R.drawable.ic_browse_library, R.string.browseServerDestinationLabel), + SETTINGS(R.drawable.ic_settings, R.string.settingsDestinationLabel), +} diff --git a/androidVariant/src/main/java/org/comixedproject/variant/android/view/Constants.kt b/androidVariant/src/main/java/org/comixedproject/variant/android/view/Constants.kt index b3b3010f..aa72b300 100644 --- a/androidVariant/src/main/java/org/comixedproject/variant/android/view/Constants.kt +++ b/androidVariant/src/main/java/org/comixedproject/variant/android/view/Constants.kt @@ -18,4 +18,4 @@ package org.comixedproject.variant.android.view -val BYTES_PER_MB = 1024.0 * 1024.0 \ No newline at end of file +val BYTES_PER_MB = 1024.0 * 1024.0 diff --git a/androidVariant/src/main/java/org/comixedproject/variant/android/view/HomeView.kt b/androidVariant/src/main/java/org/comixedproject/variant/android/view/HomeView.kt index 3137216c..adeaeaab 100644 --- a/androidVariant/src/main/java/org/comixedproject/variant/android/view/HomeView.kt +++ b/androidVariant/src/main/java/org/comixedproject/variant/android/view/HomeView.kt @@ -47,132 +47,133 @@ private const val TAG = "HomeView" @Composable fun HomeView( - comicBook: ComicBook?, - comicBookList: List, - browsingState: BrowsingState, - loading: Boolean, - selectionMode: Boolean, - selectionList: List, - address: String, username: String, password: String, - onLoadDirectory: (String, Boolean) -> Unit, - onDownloadFile: (String, String) -> Unit, - onReadComicBook: (ComicBook?) -> Unit, - onSetSelectionMode: (Boolean) -> Unit, - onUpdateSelection: (ComicBook) -> Unit, - onDeleteSelections: () -> Unit, - onSaveSettings: (String, String, String) -> Unit + comicBook: ComicBook?, + comicBookList: List, + browsingState: BrowsingState, + loading: Boolean, + selectionMode: Boolean, + selectionList: List, + address: String, + username: String, + password: String, + onLoadDirectory: (String, Boolean) -> Unit, + onDownloadFile: (String, String) -> Unit, + onReadComicBook: (ComicBook?) -> Unit, + onSetSelectionMode: (Boolean) -> Unit, + onUpdateSelection: (ComicBook) -> Unit, + onDeleteSelections: () -> Unit, + onSaveSettings: (String, String, String) -> Unit, ) { - var currentDestination by remember { mutableStateOf(AppDestination.COMICS) } + var currentDestination by remember { mutableStateOf(AppDestination.COMICS) } - Scaffold( - topBar = { VariantTopAppBar() }, - content = { padding -> - NavigationSuiteScaffold( - navigationSuiteItems = { - AppDestination.entries.forEach { - item( - icon = { - Icon( - painterResource(it.icon), - contentDescription = stringResource(it.label) - ) - }, - label = { Text(stringResource(it.label)) }, - selected = it == currentDestination, - onClick = { - if (it == AppDestination.BROWSE - ) { - onLoadDirectory(browsingState.currentPath, false) - } - currentDestination = it - } - ) - } + Scaffold( + topBar = { VariantTopAppBar() }, + content = { padding -> + NavigationSuiteScaffold( + navigationSuiteItems = { + AppDestination.entries.forEach { + item( + icon = { + Icon(painterResource(it.icon), contentDescription = stringResource(it.label)) + }, + label = { Text(stringResource(it.label)) }, + selected = it == currentDestination, + onClick = { + if (it == AppDestination.BROWSE) { + onLoadDirectory(browsingState.currentPath, false) + } + currentDestination = it + }, + ) + } + }, + modifier = Modifier.padding(padding), + ) { + when (currentDestination) { + AppDestination.COMICS -> + if (comicBook != null) { + ReadingView( + comicBook, + onStopReading = { onReadComicBook(null) }, + modifier = Modifier.fillMaxSize(), + ) + } else { + ComicBookView( + comicBookList, + selectionMode, + selectionList, + onSetSelectionMode = { + Log.info(TAG, "Setting selection mode: ${it}") + onSetSelectionMode(it) + }, + onComicBookClicked = { comicBook -> + if (selectionMode) { + Log.info(TAG, "Toggling comic book selection: ${comicBook.path}") + onUpdateSelection(comicBook) + } else { + Log.info(TAG, "Reading comic book: ${comicBook.filename}") + onReadComicBook(comicBook) + } }, - modifier = Modifier.padding(padding) - ) { - when (currentDestination) { - AppDestination.COMICS -> - if (comicBook != null) { - ReadingView( - comicBook, - onStopReading = { onReadComicBook(null) }, - modifier = Modifier - .fillMaxSize() - ) - } else { - ComicBookView( - comicBookList, - selectionMode, - selectionList, - onSetSelectionMode = { - Log.info(TAG, "Setting selection mode: ${it}") - onSetSelectionMode(it) - }, - onComicBookClicked = { comicBook -> - if (selectionMode) { - Log.info( - TAG, - "Toggling comic book selection: ${comicBook.path}" - ) - onUpdateSelection(comicBook) - } else { - Log.info(TAG, "Reading comic book: ${comicBook.filename}") - onReadComicBook(comicBook) - } - }, - onDeleteComics = { onDeleteSelections() }, - modifier = Modifier - .fillMaxSize() - ) - } + onDeleteComics = { onDeleteSelections() }, + modifier = Modifier.fillMaxSize(), + ) + } - AppDestination.BROWSE -> ServerView( - browsingState, comicBookList, loading, - onLoadDirectory = { path, reload -> onLoadDirectory(path, reload) }, - onDownloadFile = { path, filename -> onDownloadFile(path, filename) }, - modifier = Modifier - .fillMaxSize() - ) + AppDestination.BROWSE -> + ServerView( + browsingState, + comicBookList, + loading, + onLoadDirectory = { path, reload -> onLoadDirectory(path, reload) }, + onDownloadFile = { path, filename -> onDownloadFile(path, filename) }, + modifier = Modifier.fillMaxSize(), + ) - AppDestination.SETTINGS -> SettingsView( - address, username, password, - onSaveSettings = { address, username, password -> - Log.info( - TAG, - "Updating server settings: address=${address} username=${username} password=${ + AppDestination.SETTINGS -> + SettingsView( + address, + username, + password, + onSaveSettings = { address, username, password -> + Log.info( + TAG, + "Updating server settings: address=${address} username=${username} password=${ password.first() - }*****" - ) - onSaveSettings(address, username, password) - currentDestination = AppDestination.COMICS - }, - modifier = Modifier - .fillMaxSize() - ) - } - } - }) + }*****", + ) + onSaveSettings(address, username, password) + currentDestination = AppDestination.COMICS + }, + modifier = Modifier.fillMaxSize(), + ) + } + } + }, + ) } @Composable @Preview fun HomeViewPreview() { - VariantTheme { - HomeView( - COMIC_BOOK_LIST.get(0), - COMIC_BOOK_LIST, - BrowsingState("", "", "", listOf(), listOf()), - false, - false, - listOf(), - "http://www.comixedproject.org:7171", "reader@comixedproject.org", "my!password", - onLoadDirectory = { _, _ -> }, - onDownloadFile = { _, _ -> }, - onReadComicBook = { _ -> }, - onSetSelectionMode = { _ -> }, - onUpdateSelection = { _ -> }, - onDeleteSelections = { }, onSaveSettings = { _, _, _ -> } - ) - } -} \ No newline at end of file + VariantTheme { + HomeView( + COMIC_BOOK_LIST.get(0), + COMIC_BOOK_LIST, + BrowsingState("", "", "", listOf(), listOf()), + false, + false, + listOf(), + "http://www.comixedproject.org:7171", + "reader@comixedproject.org", + "my!password", + onLoadDirectory = { _, _ -> }, + onDownloadFile = { _, _ -> }, + onReadComicBook = { _ -> }, + onSetSelectionMode = { _ -> }, + onUpdateSelection = { _ -> }, + onDeleteSelections = {}, + onSaveSettings = { _, _, _ -> }, + ) + } +} diff --git a/androidVariant/src/main/java/org/comixedproject/variant/android/view/VariantAppTopBar.kt b/androidVariant/src/main/java/org/comixedproject/variant/android/view/VariantAppTopBar.kt index 2e3a8231..234f1c7b 100644 --- a/androidVariant/src/main/java/org/comixedproject/variant/android/view/VariantAppTopBar.kt +++ b/androidVariant/src/main/java/org/comixedproject/variant/android/view/VariantAppTopBar.kt @@ -28,21 +28,12 @@ import org.comixedproject.variant.android.VariantTheme @OptIn(ExperimentalMaterial3Api::class) @Composable -fun VariantTopAppBar( - modifier: Modifier = Modifier -) { - TopAppBar( - title = { - Text("Variant") - }, - modifier = modifier - ) +fun VariantTopAppBar(modifier: Modifier = Modifier) { + TopAppBar(title = { Text("Variant") }, modifier = modifier) } @Composable @Preview fun VariantTopAppBarPreview() { - VariantTheme { - VariantTopAppBar() - } -} \ No newline at end of file + VariantTheme { VariantTopAppBar() } +} diff --git a/androidVariant/src/main/java/org/comixedproject/variant/android/view/comics/ComicBookListItemView.kt b/androidVariant/src/main/java/org/comixedproject/variant/android/view/comics/ComicBookListItemView.kt index d04e57fa..99bcb00d 100644 --- a/androidVariant/src/main/java/org/comixedproject/variant/android/view/comics/ComicBookListItemView.kt +++ b/androidVariant/src/main/java/org/comixedproject/variant/android/view/comics/ComicBookListItemView.kt @@ -58,87 +58,65 @@ private val TAG = "ComicBookListItemView" @OptIn(ExperimentalFoundationApi::class) @Composable fun ComicBookListItemView( - comicBook: ComicBook, - selected: Boolean, - onClick: (ComicBook) -> Unit, - modifier: Modifier = Modifier + comicBook: ComicBook, + selected: Boolean, + onClick: (ComicBook) -> Unit, + modifier: Modifier = Modifier, ) { - var coverContent by remember { mutableStateOf(null) } - val coroutineScope = rememberCoroutineScope() - val borderWidth = when (selected) { - true -> 5.dp - false -> 0.dp + var coverContent by remember { mutableStateOf(null) } + val coroutineScope = rememberCoroutineScope() + val borderWidth = + when (selected) { + true -> 5.dp + false -> 0.dp } - ElevatedCard( - colors = CardDefaults.cardColors(containerColor = colorScheme.surface), - modifier = modifier - .fillMaxWidth() - .border(borderWidth, Color.Red) - ) { - val title = MetadataAPI.displayableTitle(comicBook) + ElevatedCard( + colors = CardDefaults.cardColors(containerColor = colorScheme.surface), + modifier = modifier.fillMaxWidth().border(borderWidth, Color.Red), + ) { + val title = MetadataAPI.displayableTitle(comicBook) - Column( - modifier = Modifier.combinedClickable( - onClick = { onClick(comicBook) } - ) - ) { - comicBook.pages.firstOrNull()?.let { cover -> - if (coverContent == null) { - Image( - painter = painterResource(id = R.drawable.ic_cover_image_placeholder), - contentDescription = title - ) - - coroutineScope.launch(Dispatchers.Main) { - Log.debug( - TAG, - "Loading content for ${comicBook.filename}:${cover.filename}" - ) - coverContent = ArchiveAPI.loadCover( - comicBook.path, - cover.filename - ) - } - } else { - coverContent?.let { content -> - Image( - bitmap = BitmapFactory.decodeByteArray(content, 0, content.size) - .asImageBitmap(), - contentDescription = title - ) - } - } - } + Column(modifier = Modifier.combinedClickable(onClick = { onClick(comicBook) })) { + comicBook.pages.firstOrNull()?.let { cover -> + if (coverContent == null) { + Image( + painter = painterResource(id = R.drawable.ic_cover_image_placeholder), + contentDescription = title, + ) - Text( - title, - style = MaterialTheme.typography.titleMedium, - maxLines = 1, - overflow = TextOverflow.Ellipsis + coroutineScope.launch(Dispatchers.Main) { + Log.debug(TAG, "Loading content for ${comicBook.filename}:${cover.filename}") + coverContent = ArchiveAPI.loadCover(comicBook.path, cover.filename) + } + } else { + coverContent?.let { content -> + Image( + bitmap = BitmapFactory.decodeByteArray(content, 0, content.size).asImageBitmap(), + contentDescription = title, ) + } } + } + + Text( + title, + style = MaterialTheme.typography.titleMedium, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + ) } + } } @Composable @Preview fun ComicBookListItemViewPreview() { - VariantTheme { - ComicBookListItemView( - comicBook = COMIC_BOOK_LIST.get(0), - false, - onClick = {}) - } + VariantTheme { ComicBookListItemView(comicBook = COMIC_BOOK_LIST.get(0), false, onClick = {}) } } @Composable @Preview fun ComicBookListItemViewSelectedPreview() { - VariantTheme { - ComicBookListItemView( - comicBook = COMIC_BOOK_LIST.get(0), - true, - onClick = {}) - } -} \ No newline at end of file + VariantTheme { ComicBookListItemView(comicBook = COMIC_BOOK_LIST.get(0), true, onClick = {}) } +} diff --git a/androidVariant/src/main/java/org/comixedproject/variant/android/view/comics/ComicBookListView.kt b/androidVariant/src/main/java/org/comixedproject/variant/android/view/comics/ComicBookListView.kt index d8299615..c4d581d0 100644 --- a/androidVariant/src/main/java/org/comixedproject/variant/android/view/comics/ComicBookListView.kt +++ b/androidVariant/src/main/java/org/comixedproject/variant/android/view/comics/ComicBookListView.kt @@ -42,53 +42,46 @@ private val TAG = "ComicBookListView" @Composable fun ComicBookListView( - comicBookList: List, - selectionList: List, - onClick: (ComicBook) -> Unit, - modifier: Modifier = Modifier + comicBookList: List, + selectionList: List, + onClick: (ComicBook) -> Unit, + modifier: Modifier = Modifier, ) { - Scaffold( - topBar = { - Text( - pluralStringResource( - R.plurals.comicBookListTitle, comicBookList.size, - comicBookList.size - ), - style = MaterialTheme.typography.headlineMedium - ) - }, - content = { padding -> - if (comicBookList.isEmpty()) { - Log.debug( - TAG, - "No comics to display" - ) - Text(stringResource(R.string.emptyComicListText)) - } else { - LazyVerticalStaggeredGrid( - columns = StaggeredGridCells.Adaptive(minSize = 128.dp), - verticalItemSpacing = 4.dp, - horizontalArrangement = Arrangement.spacedBy(4.dp), - content = { - items(comicBookList) { comicBook -> - ComicBookListItemView( - comicBook, - selectionList.contains(comicBook.path), - onClick = { onClick(it) } - ) - } - }, - modifier = modifier.padding(padding) - ) + Scaffold( + topBar = { + Text( + pluralStringResource(R.plurals.comicBookListTitle, comicBookList.size, comicBookList.size), + style = MaterialTheme.typography.headlineMedium, + ) + }, + content = { padding -> + if (comicBookList.isEmpty()) { + Log.debug(TAG, "No comics to display") + Text(stringResource(R.string.emptyComicListText)) + } else { + LazyVerticalStaggeredGrid( + columns = StaggeredGridCells.Adaptive(minSize = 128.dp), + verticalItemSpacing = 4.dp, + horizontalArrangement = Arrangement.spacedBy(4.dp), + content = { + items(comicBookList) { comicBook -> + ComicBookListItemView( + comicBook, + selectionList.contains(comicBook.path), + onClick = { onClick(it) }, + ) } - }, modifier = modifier.padding(8.dp) - ) + }, + modifier = modifier.padding(padding), + ) + } + }, + modifier = modifier.padding(8.dp), + ) } @Composable @Preview fun ComicBookListViewPreview() { - VariantTheme { - ComicBookListView(COMIC_BOOK_LIST, emptyList(), onClick = {}) - } -} \ No newline at end of file + VariantTheme { ComicBookListView(COMIC_BOOK_LIST, emptyList(), onClick = {}) } +} diff --git a/androidVariant/src/main/java/org/comixedproject/variant/android/view/comics/ComicBookView.kt b/androidVariant/src/main/java/org/comixedproject/variant/android/view/comics/ComicBookView.kt index a0222987..91e0a0cf 100644 --- a/androidVariant/src/main/java/org/comixedproject/variant/android/view/comics/ComicBookView.kt +++ b/androidVariant/src/main/java/org/comixedproject/variant/android/view/comics/ComicBookView.kt @@ -38,83 +38,87 @@ private val TAG = "ComicBookView" @Composable fun ComicBookView( - comicBookList: List, - selectionMode: Boolean, - selectionList: List, - onSetSelectionMode: (Boolean) -> Unit, - onComicBookClicked: (ComicBook) -> Unit, - onDeleteComics: () -> Unit, - modifier: Modifier = Modifier + comicBookList: List, + selectionMode: Boolean, + selectionList: List, + onSetSelectionMode: (Boolean) -> Unit, + onComicBookClicked: (ComicBook) -> Unit, + onDeleteComics: () -> Unit, + modifier: Modifier = Modifier, ) { - Scaffold( - content = { padding -> - ComicBookListView( - comicBookList, - selectionList, - onClick = { onComicBookClicked(it) }, - modifier = modifier.padding(padding) - ) - }, - bottomBar = { - BottomAppBar( - actions = { - if (selectionMode) { - IconButton(onClick = { onSetSelectionMode(false) }) { - Icon( - painterResource(id = R.drawable.ic_selection_mode_on), - contentDescription = stringResource(R.string.markReadLabel) - ) - } - } else { - IconButton(onClick = { onSetSelectionMode(true) }) { - Icon( - painterResource(id = R.drawable.ic_selection_mode_off), - contentDescription = stringResource(R.string.markReadLabel) - ) - } - } - if (!selectionList.isEmpty()) { - IconButton(enabled = !selectionList.isEmpty(), onClick = { - Log.info(TAG, "Deleting ${selectionList.size} comic book(s)") - onDeleteComics() - }) { - Icon( - painterResource(R.drawable.ic_delete_comics), - contentDescription = stringResource(R.string.deleteSelectionsLabel) - ) - } - } - - } - ) + Scaffold( + content = { padding -> + ComicBookListView( + comicBookList, + selectionList, + onClick = { onComicBookClicked(it) }, + modifier = modifier.padding(padding), + ) + }, + bottomBar = { + BottomAppBar( + actions = { + if (selectionMode) { + IconButton(onClick = { onSetSelectionMode(false) }) { + Icon( + painterResource(id = R.drawable.ic_selection_mode_on), + contentDescription = stringResource(R.string.markReadLabel), + ) + } + } else { + IconButton(onClick = { onSetSelectionMode(true) }) { + Icon( + painterResource(id = R.drawable.ic_selection_mode_off), + contentDescription = stringResource(R.string.markReadLabel), + ) + } + } + if (!selectionList.isEmpty()) { + IconButton( + enabled = !selectionList.isEmpty(), + onClick = { + Log.info(TAG, "Deleting ${selectionList.size} comic book(s)") + onDeleteComics() + }, + ) { + Icon( + painterResource(R.drawable.ic_delete_comics), + contentDescription = stringResource(R.string.deleteSelectionsLabel), + ) + } + } } - ) + ) + }, + ) } @Composable @Preview fun ComicBookViewPreview() { - VariantTheme { - ComicBookView( - COMIC_BOOK_LIST, - false, - emptyList(), - onSetSelectionMode = { _ -> }, - onComicBookClicked = { _ -> }, - onDeleteComics = { }) - } + VariantTheme { + ComicBookView( + COMIC_BOOK_LIST, + false, + emptyList(), + onSetSelectionMode = { _ -> }, + onComicBookClicked = { _ -> }, + onDeleteComics = {}, + ) + } } @Composable @Preview fun ComicBookViewWithSelectionsPreview() { - VariantTheme { - ComicBookView( - COMIC_BOOK_LIST, - true, - listOf(COMIC_BOOK_LIST.get(0).path), - onSetSelectionMode = { _ -> }, - onComicBookClicked = { _ -> }, - onDeleteComics = { }) - } -} \ No newline at end of file + VariantTheme { + ComicBookView( + COMIC_BOOK_LIST, + true, + listOf(COMIC_BOOK_LIST.get(0).path), + onSetSelectionMode = { _ -> }, + onComicBookClicked = { _ -> }, + onDeleteComics = {}, + ) + } +} diff --git a/androidVariant/src/main/java/org/comixedproject/variant/android/view/reading/PageNavigationView.kt b/androidVariant/src/main/java/org/comixedproject/variant/android/view/reading/PageNavigationView.kt index b69498f2..9ea1573e 100644 --- a/androidVariant/src/main/java/org/comixedproject/variant/android/view/reading/PageNavigationView.kt +++ b/androidVariant/src/main/java/org/comixedproject/variant/android/view/reading/PageNavigationView.kt @@ -61,167 +61,153 @@ private const val TAG = "PageNavigationView" @Composable fun PageNavigationView( - comicBook: ComicBook, - onStopReading: () -> Unit, - modifier: Modifier = Modifier + comicBook: ComicBook, + onStopReading: () -> Unit, + modifier: Modifier = Modifier, ) { - var pageFilename by remember { mutableStateOf("") } - var currentPage by remember { mutableIntStateOf(0) } - var currentPageContent by remember { mutableStateOf(null) } - var showPageOverlay by remember { mutableStateOf(false) } - val context = LocalContext.current - - Column( - modifier = modifier - .verticalScroll(rememberScrollState()) - .pointerInput(Unit) { - detectTapGestures( - onPress = { location -> - var handled = false - val screenHeightMiddle = context.resources.displayMetrics.heightPixels / 2 - if (location.y > (screenHeightMiddle * 1.5)) { - val screenWidthMiddle = context.resources.displayMetrics.widthPixels / 2 - if (location.x <= (screenWidthMiddle / 2)) { - if (currentPage > 0) { - Log.info(TAG, "Navigating back to page ${currentPage - 1}") - currentPageContent = null - currentPage = currentPage - 1 - } - handled = true - } else if (location.x >= (screenWidthMiddle * 3) / 2) { - if (currentPage < comicBook.pages.size - 1) { - Log.info( - TAG, - "Navigating forward to page ${currentPage + 1}" - ) - currentPageContent = null - currentPage = currentPage + 1 - } - handled = true - } - } - if (!handled) { - showPageOverlay = (showPageOverlay == false) - Log.info(TAG, "Setting show overlay: ${showPageOverlay}") - } - } - ) - } - .fillMaxSize()) { - if (showPageOverlay) { - Row( - verticalAlignment = Alignment.CenterVertically, - modifier = Modifier.fillMaxWidth() - ) { - IconButton( - onClick = { - Log.debug( - TAG, - "Closing comic book" - ) - onStopReading() - } - ) { - Icon( - painterResource(R.drawable.ic_close), - contentDescription = stringResource(R.string.stopReadingLabel) - ) - } - - Text( - text = comicBook.filename, - style = MaterialTheme.typography.titleMedium, - textAlign = TextAlign.Center, - maxLines = 1, - overflow = TextOverflow.Ellipsis, - modifier = Modifier.fillMaxWidth() - ) - } - - Text( - text = pageFilename, - style = MaterialTheme.typography.titleSmall, - textAlign = TextAlign.Center, - maxLines = 1, overflow = TextOverflow.Ellipsis, - modifier = Modifier.fillMaxWidth() - ) - Row(modifier = Modifier.fillMaxWidth()) { - IconButton(onClick = { + var pageFilename by remember { mutableStateOf("") } + var currentPage by remember { mutableIntStateOf(0) } + var currentPageContent by remember { mutableStateOf(null) } + var showPageOverlay by remember { mutableStateOf(false) } + val context = LocalContext.current + + Column( + modifier = + modifier + .verticalScroll(rememberScrollState()) + .pointerInput(Unit) { + detectTapGestures( + onPress = { location -> + var handled = false + val screenHeightMiddle = context.resources.displayMetrics.heightPixels / 2 + if (location.y > (screenHeightMiddle * 1.5)) { + val screenWidthMiddle = context.resources.displayMetrics.widthPixels / 2 + if (location.x <= (screenWidthMiddle / 2)) { + if (currentPage > 0) { + Log.info(TAG, "Navigating back to page ${currentPage - 1}") currentPageContent = null currentPage = currentPage - 1 - }, enabled = (currentPage > 0)) { - Icon( - painterResource(R.drawable.ic_previous_page), - contentDescription = stringResource(R.string.previousPageLabel) - ) - } - - Slider( - value = currentPage.toFloat(), - valueRange = 0f..(comicBook.pages.size - 1).toFloat(), - steps = comicBook.pages.size, - onValueChange = { - currentPageContent = null - currentPage = it.toInt() - }, - modifier = Modifier.weight(0.9f) - ) - - IconButton(onClick = { + } + handled = true + } else if (location.x >= (screenWidthMiddle * 3) / 2) { + if (currentPage < comicBook.pages.size - 1) { + Log.info(TAG, "Navigating forward to page ${currentPage + 1}") currentPageContent = null currentPage = currentPage + 1 - }, enabled = (currentPage < (comicBook.pages.size - 1))) { - Icon( - painterResource(R.drawable.ic_next_page), - contentDescription = stringResource(R.string.nextPageLabel) - ) + } + handled = true } + } + if (!handled) { + showPageOverlay = (showPageOverlay == false) + Log.info(TAG, "Setting show overlay: ${showPageOverlay}") + } } + ) + } + .fillMaxSize() + ) { + if (showPageOverlay) { + Row(verticalAlignment = Alignment.CenterVertically, modifier = Modifier.fillMaxWidth()) { + IconButton( + onClick = { + Log.debug(TAG, "Closing comic book") + onStopReading() + } + ) { + Icon( + painterResource(R.drawable.ic_close), + contentDescription = stringResource(R.string.stopReadingLabel), + ) } + Text( + text = comicBook.filename, + style = MaterialTheme.typography.titleMedium, + textAlign = TextAlign.Center, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + modifier = Modifier.fillMaxWidth(), + ) + } + + Text( + text = pageFilename, + style = MaterialTheme.typography.titleSmall, + textAlign = TextAlign.Center, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + modifier = Modifier.fillMaxWidth(), + ) + Row(modifier = Modifier.fillMaxWidth()) { + IconButton( + onClick = { + currentPageContent = null + currentPage = currentPage - 1 + }, + enabled = (currentPage > 0), + ) { + Icon( + painterResource(R.drawable.ic_previous_page), + contentDescription = stringResource(R.string.previousPageLabel), + ) + } - if (currentPageContent == null) { - LaunchedEffect(currentPageContent) { - pageFilename = comicBook.pages.get(currentPage).filename - currentPageContent = - ArchiveAPI.loadPage(comicBook.path, pageFilename) - - } - } else { - currentPageContent?.let { content -> - Image( - bitmap = BitmapFactory.decodeByteArray(content, 0, content.size) - .asImageBitmap(), - contentDescription = comicBook.pages.get(currentPage).filename, - modifier = modifier - .fillMaxHeight() - ) - } + Slider( + value = currentPage.toFloat(), + valueRange = 0f..(comicBook.pages.size - 1).toFloat(), + steps = comicBook.pages.size, + onValueChange = { + currentPageContent = null + currentPage = it.toInt() + }, + modifier = Modifier.weight(0.9f), + ) + + IconButton( + onClick = { + currentPageContent = null + currentPage = currentPage + 1 + }, + enabled = (currentPage < (comicBook.pages.size - 1)), + ) { + Icon( + painterResource(R.drawable.ic_next_page), + contentDescription = stringResource(R.string.nextPageLabel), + ) } + } } -} + if (currentPageContent == null) { + LaunchedEffect(currentPageContent) { + pageFilename = comicBook.pages.get(currentPage).filename + currentPageContent = ArchiveAPI.loadPage(comicBook.path, pageFilename) + } + } else { + currentPageContent?.let { content -> + Image( + bitmap = BitmapFactory.decodeByteArray(content, 0, content.size).asImageBitmap(), + contentDescription = comicBook.pages.get(currentPage).filename, + modifier = modifier.fillMaxHeight(), + ) + } + } + } +} @Composable @Preview fun PageNavigationPreview() { - val comic = COMIC_BOOK_LIST.get(0) + val comic = COMIC_BOOK_LIST.get(0) - VariantTheme { - PageNavigationView( - comic, - onStopReading = {}) - } + VariantTheme { PageNavigationView(comic, onStopReading = {}) } } @Composable @Preview fun PageNavigationPreviewWithOverlay() { - val comic = COMIC_BOOK_LIST.get(0) + val comic = COMIC_BOOK_LIST.get(0) - VariantTheme { - PageNavigationView( - comic, - onStopReading = {}) - } + VariantTheme { PageNavigationView(comic, onStopReading = {}) } } diff --git a/androidVariant/src/main/java/org/comixedproject/variant/android/view/reading/ReadingView.kt b/androidVariant/src/main/java/org/comixedproject/variant/android/view/reading/ReadingView.kt index e2412616..af477205 100644 --- a/androidVariant/src/main/java/org/comixedproject/variant/android/view/reading/ReadingView.kt +++ b/androidVariant/src/main/java/org/comixedproject/variant/android/view/reading/ReadingView.kt @@ -28,20 +28,12 @@ import org.comixedproject.variant.model.library.ComicBook private const val TAG = "ReadingView" @Composable -fun ReadingView( - comicBook: ComicBook, - onStopReading: () -> Unit, - modifier: Modifier = Modifier -) { - PageNavigationView( - comicBook, - onStopReading = onStopReading, - modifier = modifier - ) +fun ReadingView(comicBook: ComicBook, onStopReading: () -> Unit, modifier: Modifier = Modifier) { + PageNavigationView(comicBook, onStopReading = onStopReading, modifier = modifier) } @Composable @Preview fun ReadingViewPreview() { - VariantTheme { ReadingView(COMIC_BOOK_LIST.get(0), onStopReading = {}) } + VariantTheme { ReadingView(COMIC_BOOK_LIST.get(0), onStopReading = {}) } } diff --git a/androidVariant/src/main/java/org/comixedproject/variant/android/view/server/BrowseServerView.kt b/androidVariant/src/main/java/org/comixedproject/variant/android/view/server/BrowseServerView.kt index 8cc9aa46..4bfde37c 100644 --- a/androidVariant/src/main/java/org/comixedproject/variant/android/view/server/BrowseServerView.kt +++ b/androidVariant/src/main/java/org/comixedproject/variant/android/view/server/BrowseServerView.kt @@ -52,122 +52,132 @@ private const val TAG = "BrowseServerView" @OptIn(ExperimentalMaterial3Api::class) @Composable fun BrowseServerView( - path: String, - title: String, - parentPath: String, - contents: List, - comicBookList: List, - downloadingState: List, - loading: Boolean, - onLoadDirectory: (String, Boolean) -> Unit, - onDownloadFile: (String, String) -> Unit, - modifier: Modifier = Modifier + path: String, + title: String, + parentPath: String, + contents: List, + comicBookList: List, + downloadingState: List, + loading: Boolean, + onLoadDirectory: (String, Boolean) -> Unit, + onDownloadFile: (String, String) -> Unit, + modifier: Modifier = Modifier, ) { - val pullToRefreshState = rememberPullToRefreshState() + val pullToRefreshState = rememberPullToRefreshState() - Scaffold( - topBar = { - Row(verticalAlignment = Alignment.CenterVertically) { - IconButton( - onClick = { - Log.debug(TAG, "Going back to parent: ${parentPath}") - onLoadDirectory(parentPath, false) - }, - enabled = !parentPath.isEmpty() - ) { - Icon(painterResource(R.drawable.ic_back), contentDescription = parentPath) - } + Scaffold( + topBar = { + Row(verticalAlignment = Alignment.CenterVertically) { + IconButton( + onClick = { + Log.debug(TAG, "Going back to parent: ${parentPath}") + onLoadDirectory(parentPath, false) + }, + enabled = !parentPath.isEmpty(), + ) { + Icon(painterResource(R.drawable.ic_back), contentDescription = parentPath) + } - val displayedTitle = when (title.isEmpty()) { - false -> title - true -> stringResource(R.string.rootDirectoryTitle) - } + val displayedTitle = + when (title.isEmpty()) { + false -> title + true -> stringResource(R.string.rootDirectoryTitle) + } - Text( - "${displayedTitle} [${downloadingState.size}]", - maxLines = 1, - overflow = TextOverflow.Ellipsis, - style = MaterialTheme.typography.headlineMedium, modifier = Modifier.weight(1f) - ) - } - }, - content = { padding -> - PullToRefreshBox( - isRefreshing = loading, - state = pullToRefreshState, - onRefresh = { onLoadDirectory(path, true) }, - content = { - LazyColumn( - modifier = Modifier - .padding(padding) - .fillMaxWidth() - ) { - items(contents) { entry -> - when (entry.isDirectory) { + Text( + "${displayedTitle} [${downloadingState.size}]", + maxLines = 1, + overflow = TextOverflow.Ellipsis, + style = MaterialTheme.typography.headlineMedium, + modifier = Modifier.weight(1f), + ) + } + }, + content = { padding -> + PullToRefreshBox( + isRefreshing = loading, + state = pullToRefreshState, + onRefresh = { onLoadDirectory(path, true) }, + content = { + LazyColumn(modifier = Modifier.padding(padding).fillMaxWidth()) { + items(contents) { entry -> + when (entry.isDirectory) { + true -> + DirectoryItemView( + entry, + onLoadDirectory = { path -> onLoadDirectory(path, false) }, + ) - true -> DirectoryItemView( - entry, - onLoadDirectory = { path -> - onLoadDirectory( - path, - false - ) - }) - - else -> FileItemView( - entry, - comicBookList.map { it.filename }.toList(), - downloadingState, - onDownloadFile = onDownloadFile - ) - } - } - } - }, - modifier = Modifier - .padding(padding) - .fillMaxSize() - ) + else -> + FileItemView( + entry, + comicBookList.map { it.filename }.toList(), + downloadingState, + onDownloadFile = onDownloadFile, + ) + } + } + } }, - modifier = modifier.fillMaxSize() - ) + modifier = Modifier.padding(padding).fillMaxSize(), + ) + }, + modifier = modifier.fillMaxSize(), + ) } @Composable @Preview fun BrowseServerViewPreviewDirectories() { - VariantTheme { - BrowseServerView( - "http://www.comixedproject.org:7171", - "", - "", - DIRECTORY_LIST.filter { it.isDirectory }, emptyList(), emptyList(), false, - onLoadDirectory = { _, _ -> }, onDownloadFile = { _, _ -> }) - } + VariantTheme { + BrowseServerView( + "http://www.comixedproject.org:7171", + "", + "", + DIRECTORY_LIST.filter { it.isDirectory }, + emptyList(), + emptyList(), + false, + onLoadDirectory = { _, _ -> }, + onDownloadFile = { _, _ -> }, + ) + } } @Composable @Preview fun BrowseServerViewPreviewFiles() { - val directory = DIRECTORY_LIST.get(0) - VariantTheme { - BrowseServerView( - "http://www.comixedproject.org:7171", - directory.title, directory.parent, - DIRECTORY_LIST.filter { !it.isDirectory }, emptyList(), emptyList(), false, - onLoadDirectory = { _, _ -> }, onDownloadFile = { _, _ -> }) - } + val directory = DIRECTORY_LIST.get(0) + VariantTheme { + BrowseServerView( + "http://www.comixedproject.org:7171", + directory.title, + directory.parent, + DIRECTORY_LIST.filter { !it.isDirectory }, + emptyList(), + emptyList(), + false, + onLoadDirectory = { _, _ -> }, + onDownloadFile = { _, _ -> }, + ) + } } @Composable @Preview fun BrowseServerViewPreviewRefreshing() { - val directory = DIRECTORY_LIST.get(0) - VariantTheme { - BrowseServerView( - "http://www.comixedproject.org:7171", - directory.title, directory.parent, - DIRECTORY_LIST.filter { !it.isDirectory }, emptyList(), emptyList(), true, - onLoadDirectory = { _, _ -> }, onDownloadFile = { _, _ -> }) - } + val directory = DIRECTORY_LIST.get(0) + VariantTheme { + BrowseServerView( + "http://www.comixedproject.org:7171", + directory.title, + directory.parent, + DIRECTORY_LIST.filter { !it.isDirectory }, + emptyList(), + emptyList(), + true, + onLoadDirectory = { _, _ -> }, + onDownloadFile = { _, _ -> }, + ) + } } diff --git a/androidVariant/src/main/java/org/comixedproject/variant/android/view/server/DirectoryItemView.kt b/androidVariant/src/main/java/org/comixedproject/variant/android/view/server/DirectoryItemView.kt index 063372c1..616f1334 100644 --- a/androidVariant/src/main/java/org/comixedproject/variant/android/view/server/DirectoryItemView.kt +++ b/androidVariant/src/main/java/org/comixedproject/variant/android/view/server/DirectoryItemView.kt @@ -49,51 +49,46 @@ private const val TAG = "DirectoryDetailView" @Composable fun DirectoryItemView( - directoryEntry: DirectoryEntry, - onLoadDirectory: (String) -> Unit, - modifier: Modifier = Modifier + directoryEntry: DirectoryEntry, + onLoadDirectory: (String) -> Unit, + modifier: Modifier = Modifier, ) { - ElevatedCard( - colors = CardDefaults.cardColors(containerColor = colorScheme.surface), - modifier = modifier - .fillMaxWidth() + ElevatedCard( + colors = CardDefaults.cardColors(containerColor = colorScheme.surface), + modifier = modifier.fillMaxWidth(), + ) { + Column( + modifier = + modifier.padding(16.dp).fillMaxWidth().clickable { + Log.info(TAG, "Loading path: ${directoryEntry.path}") + onLoadDirectory(directoryEntry.path) + } ) { - Column( - modifier = modifier - .padding(16.dp) - .fillMaxWidth() - .clickable { - Log.info(TAG, "Loading path: ${directoryEntry.path}") - onLoadDirectory(directoryEntry.path) - } - ) { - Row( - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.SpaceBetween, - modifier = Modifier.fillMaxWidth() - ) { - Text( - text = "${directoryEntry.title}", - style = MaterialTheme.typography.bodyLarge, - fontWeight = FontWeight.Bold, - textAlign = TextAlign.Left, - maxLines = 1, - overflow = TextOverflow.Ellipsis, - modifier = Modifier.weight(1f) - ) + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween, + modifier = Modifier.fillMaxWidth(), + ) { + Text( + text = "${directoryEntry.title}", + style = MaterialTheme.typography.bodyLarge, + fontWeight = FontWeight.Bold, + textAlign = TextAlign.Left, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + modifier = Modifier.weight(1f), + ) - Icon(Icons.Default.MoreVert, contentDescription = directoryEntry.title) - } - } + Icon(Icons.Default.MoreVert, contentDescription = directoryEntry.title) + } } + } } @Composable @Preview fun DirectoryItemViewPreview() { - VariantTheme { - DirectoryItemView( - DIRECTORY_LIST.filter { it.isDirectory }.first(), - onLoadDirectory = { _ -> }) - } -} \ No newline at end of file + VariantTheme { + DirectoryItemView(DIRECTORY_LIST.filter { it.isDirectory }.first(), onLoadDirectory = { _ -> }) + } +} diff --git a/androidVariant/src/main/java/org/comixedproject/variant/android/view/server/FileItemView.kt b/androidVariant/src/main/java/org/comixedproject/variant/android/view/server/FileItemView.kt index 7100e519..15751aaf 100644 --- a/androidVariant/src/main/java/org/comixedproject/variant/android/view/server/FileItemView.kt +++ b/androidVariant/src/main/java/org/comixedproject/variant/android/view/server/FileItemView.kt @@ -51,154 +51,123 @@ private const val TAG = "DirectoryDetailView" @Composable fun FileItemView( - fileEntry: DirectoryEntry, - comicBookFilenameList: List, - downloadingState: List, - onDownloadFile: (String, String) -> Unit, - modifier: Modifier = Modifier + fileEntry: DirectoryEntry, + comicBookFilenameList: List, + downloadingState: List, + onDownloadFile: (String, String) -> Unit, + modifier: Modifier = Modifier, ) { - val downloading = downloadingState - .filter { it.path == fileEntry.path } - .firstOrNull() + val downloading = downloadingState.filter { it.path == fileEntry.path }.firstOrNull() - - ElevatedCard( - colors = CardDefaults.cardColors(containerColor = colorScheme.surface), - modifier = modifier - .fillMaxWidth() - ) { - Column( - modifier = modifier - .padding(8.dp) - .fillMaxWidth() - ) { - Row( - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.SpaceBetween, - modifier = Modifier.fillMaxWidth() + ElevatedCard( + colors = CardDefaults.cardColors(containerColor = colorScheme.surface), + modifier = modifier.fillMaxWidth(), + ) { + Column(modifier = modifier.padding(8.dp).fillMaxWidth()) { + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween, + modifier = Modifier.fillMaxWidth(), + ) { + if (downloading == null) { + if (comicBookFilenameList.contains(fileEntry.filename)) { + IconButton(onClick = {}, enabled = downloadingState.size < 5) { + Icon( + painterResource(id = R.drawable.ic_downloaded_file), + contentDescription = fileEntry.title, + ) + } + } else { + IconButton( + onClick = { onDownloadFile(fileEntry.path, fileEntry.filename) }, + enabled = downloadingState.size < 5, ) { - if (downloading == null) { - if (comicBookFilenameList.contains(fileEntry.filename)) { - IconButton( - onClick = { }, - enabled = downloadingState.size < 5 - ) { - Icon( - painterResource(id = R.drawable.ic_downloaded_file), - contentDescription = fileEntry.title - ) - } - } else { - IconButton( - onClick = { - onDownloadFile(fileEntry.path, fileEntry.filename) - }, - enabled = downloadingState.size < 5 - ) { - Icon( - painterResource(R.drawable.ic_download_file), - contentDescription = fileEntry.title - ) - } - } - } else { - IconButton( - onClick = { }, - enabled = downloadingState.size < 5 - ) { - Icon( - painterResource(R.drawable.ic_downloading_file), - contentDescription = fileEntry.title - ) - } - } + Icon( + painterResource(R.drawable.ic_download_file), + contentDescription = fileEntry.title, + ) + } + } + } else { + IconButton(onClick = {}, enabled = downloadingState.size < 5) { + Icon( + painterResource(R.drawable.ic_downloading_file), + contentDescription = fileEntry.title, + ) + } + } - Column(modifier = Modifier.weight(1f)) { - Text( - text = "${fileEntry.title}", - style = MaterialTheme.typography.bodyLarge, - fontWeight = FontWeight.Bold, - textAlign = TextAlign.Left, - maxLines = 1, - overflow = TextOverflow.Ellipsis - ) + Column(modifier = Modifier.weight(1f)) { + Text( + text = "${fileEntry.title}", + style = MaterialTheme.typography.bodyLarge, + fontWeight = FontWeight.Bold, + textAlign = TextAlign.Left, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + ) - if (downloading == null) { - Text( - text = "${fileEntry.filename}", - style = MaterialTheme.typography.bodySmall, - fontWeight = FontWeight.Bold, - textAlign = TextAlign.Left, - maxLines = 1, - overflow = TextOverflow.Ellipsis - ) - } else { - val received = downloading.received - val total = downloading.total - val progress = when (received > 0) { - true -> (received.toFloat() / total.toFloat()) - false -> 0.0 - } - val fileSize = String.format("%.1f", fileEntry.fileSize / BYTES_PER_MB) - Row( - modifier = Modifier.fillMaxWidth(), - verticalAlignment = Alignment.CenterVertically - ) { - Text("${fileSize} MB", style = MaterialTheme.typography.bodySmall) - LinearProgressIndicator( - progress = { progress.toFloat() }, - modifier = Modifier - .fillMaxWidth() - .padding(4.dp) - ) - } - } - } + if (downloading == null) { + Text( + text = "${fileEntry.filename}", + style = MaterialTheme.typography.bodySmall, + fontWeight = FontWeight.Bold, + textAlign = TextAlign.Left, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + ) + } else { + val received = downloading.received + val total = downloading.total + val progress = + when (received > 0) { + true -> (received.toFloat() / total.toFloat()) + false -> 0.0 + } + val fileSize = String.format("%.1f", fileEntry.fileSize / BYTES_PER_MB) + Row( + modifier = Modifier.fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically, + ) { + Text("${fileSize} MB", style = MaterialTheme.typography.bodySmall) + LinearProgressIndicator( + progress = { progress.toFloat() }, + modifier = Modifier.fillMaxWidth().padding(4.dp), + ) } + } } + } } + } } @Composable @Preview fun FileItemViewPreview() { - val fileEntry = DIRECTORY_LIST.filter { !it.isDirectory }.first() - VariantTheme { - FileItemView( - fileEntry, - listOf(), - listOf(), - onDownloadFile = { _, _ -> }) - } + val fileEntry = DIRECTORY_LIST.filter { !it.isDirectory }.first() + VariantTheme { FileItemView(fileEntry, listOf(), listOf(), onDownloadFile = { _, _ -> }) } } @Composable @Preview fun FileItemViewPreviewDownloaded() { - val fileEntry = DIRECTORY_LIST.filter { !it.isDirectory }.first() - VariantTheme { - FileItemView( - fileEntry, - listOf(fileEntry.filename), - listOf(), - onDownloadFile = { _, _ -> }) - } + val fileEntry = DIRECTORY_LIST.filter { !it.isDirectory }.first() + VariantTheme { + FileItemView(fileEntry, listOf(fileEntry.filename), listOf(), onDownloadFile = { _, _ -> }) + } } @Composable @Preview fun FileItemViewPreviewDownloading() { - val fileEntry = DIRECTORY_LIST.filter { !it.isDirectory }.first() - VariantTheme { - FileItemView( - fileEntry, - listOf(), - listOf( - DownloadingState( - fileEntry.path, fileEntry.filename, - 50, 100 - ) - ), - onDownloadFile = { _, _ -> }) - } -} \ No newline at end of file + val fileEntry = DIRECTORY_LIST.filter { !it.isDirectory }.first() + VariantTheme { + FileItemView( + fileEntry, + listOf(), + listOf(DownloadingState(fileEntry.path, fileEntry.filename, 50, 100)), + onDownloadFile = { _, _ -> }, + ) + } +} diff --git a/androidVariant/src/main/java/org/comixedproject/variant/android/view/server/ServerView.kt b/androidVariant/src/main/java/org/comixedproject/variant/android/view/server/ServerView.kt index d1d4d436..052b2de3 100644 --- a/androidVariant/src/main/java/org/comixedproject/variant/android/view/server/ServerView.kt +++ b/androidVariant/src/main/java/org/comixedproject/variant/android/view/server/ServerView.kt @@ -30,37 +30,37 @@ private const val TAG = "ServerView" @Composable fun ServerView( - browsingState: BrowsingState, - comicBookList: List, - loading: Boolean, - onLoadDirectory: (String, Boolean) -> Unit, - onDownloadFile: (String, String) -> Unit, - modifier: Modifier = Modifier + browsingState: BrowsingState, + comicBookList: List, + loading: Boolean, + onLoadDirectory: (String, Boolean) -> Unit, + onDownloadFile: (String, String) -> Unit, + modifier: Modifier = Modifier, ) { - BrowseServerView( - browsingState.currentPath, - browsingState.title, - browsingState.parentPath, - browsingState.contents, - comicBookList, - browsingState.downloadingState, - loading, - modifier = modifier, - onLoadDirectory = { path, reload -> onLoadDirectory(path, reload) }, - onDownloadFile = { path, filename -> onDownloadFile(path, filename) }, - ) + BrowseServerView( + browsingState.currentPath, + browsingState.title, + browsingState.parentPath, + browsingState.contents, + comicBookList, + browsingState.downloadingState, + loading, + modifier = modifier, + onLoadDirectory = { path, reload -> onLoadDirectory(path, reload) }, + onDownloadFile = { path, filename -> onDownloadFile(path, filename) }, + ) } @Composable @Preview fun ServerViewPreview() { - VariantTheme { - ServerView( - BrowsingState("", "", "", listOf(), listOf()), - COMIC_BOOK_LIST, - false, - onLoadDirectory = { _, _ -> }, - onDownloadFile = { _, _ -> } - ) - } -} \ No newline at end of file + VariantTheme { + ServerView( + BrowsingState("", "", "", listOf(), listOf()), + COMIC_BOOK_LIST, + false, + onLoadDirectory = { _, _ -> }, + onDownloadFile = { _, _ -> }, + ) + } +} diff --git a/androidVariant/src/main/java/org/comixedproject/variant/android/view/settings/EditServerView.kt b/androidVariant/src/main/java/org/comixedproject/variant/android/view/settings/EditServerView.kt index 2dc71f07..13dfbb4b 100644 --- a/androidVariant/src/main/java/org/comixedproject/variant/android/view/settings/EditServerView.kt +++ b/androidVariant/src/main/java/org/comixedproject/variant/android/view/settings/EditServerView.kt @@ -41,90 +41,98 @@ import org.comixedproject.variant.android.VariantTheme private const val TAG = "EditServerView" private fun validateForm(url: String): Boolean { - return !(url.isBlank()) + return !(url.isBlank()) } @Composable fun EditServerView( - address: String, - username: String, - password: String, - onSave: (String, String, String) -> Unit, - modifier: Modifier = Modifier + address: String, + username: String, + password: String, + onSave: (String, String, String) -> Unit, + modifier: Modifier = Modifier, ) { - var addressValue by rememberSaveable { mutableStateOf(address) } - var usernameValue by rememberSaveable { mutableStateOf(username) } - var passwordValue by rememberSaveable { mutableStateOf(password) } - var validForm by rememberSaveable { mutableStateOf(validateForm(addressValue)) } + var addressValue by rememberSaveable { mutableStateOf(address) } + var usernameValue by rememberSaveable { mutableStateOf(username) } + var passwordValue by rememberSaveable { mutableStateOf(password) } + var validForm by rememberSaveable { mutableStateOf(validateForm(addressValue)) } - Column(modifier = modifier.fillMaxWidth()) { - TextField(value = addressValue, onValueChange = { - addressValue = it - validForm = validateForm(addressValue) - }, label = { - Text( - stringResource(R.string.serverUrlLabel) - ) - }, modifier = Modifier.fillMaxWidth()) + Column(modifier = modifier.fillMaxWidth()) { + TextField( + value = addressValue, + onValueChange = { + addressValue = it + validForm = validateForm(addressValue) + }, + label = { Text(stringResource(R.string.serverUrlLabel)) }, + modifier = Modifier.fillMaxWidth(), + ) - TextField(value = usernameValue, onValueChange = { - usernameValue = it - validForm = validateForm(addressValue) - }, label = { - Text( - stringResource(R.string.serverUsernameLabel) - ) - }, modifier = Modifier.fillMaxWidth()) + TextField( + value = usernameValue, + onValueChange = { + usernameValue = it + validForm = validateForm(addressValue) + }, + label = { Text(stringResource(R.string.serverUsernameLabel)) }, + modifier = Modifier.fillMaxWidth(), + ) - TextField(value = passwordValue, onValueChange = { - passwordValue = it - validForm = validateForm(addressValue) - }, label = { - Text( - stringResource(R.string.serverPasswordLabel) - ) - }, modifier = Modifier.fillMaxWidth()) + TextField( + value = passwordValue, + onValueChange = { + passwordValue = it + validForm = validateForm(addressValue) + }, + label = { Text(stringResource(R.string.serverPasswordLabel)) }, + modifier = Modifier.fillMaxWidth(), + ) - Row(modifier = Modifier.fillMaxWidth()) { - Spacer(modifier = Modifier.weight(1f)) + Row(modifier = Modifier.fillMaxWidth()) { + Spacer(modifier = Modifier.weight(1f)) - Button(onClick = { - onSave(addressValue, usernameValue, passwordValue) - }, enabled = validForm) { - Icon( - painterResource(R.drawable.ic_save), - contentDescription = stringResource(R.string.saveButton) - ) - } + Button( + onClick = { onSave(addressValue, usernameValue, passwordValue) }, + enabled = validForm, + ) { + Icon( + painterResource(R.drawable.ic_save), + contentDescription = stringResource(R.string.saveButton), + ) + } - Button(onClick = { - addressValue = address - usernameValue = username - passwordValue = password - }, enabled = validForm) { - Icon( - painterResource(R.drawable.ic_cancel), - contentDescription = stringResource(R.string.cancelButton) - ) - } - } + Button( + onClick = { + addressValue = address + usernameValue = username + passwordValue = password + }, + enabled = validForm, + ) { + Icon( + painterResource(R.drawable.ic_cancel), + contentDescription = stringResource(R.string.cancelButton), + ) + } } + } } @Composable @Preview fun EditServerViewPreviewNew() { - VariantTheme { EditServerView("", "", "", onSave = { _, _, _ -> }) } + VariantTheme { EditServerView("", "", "", onSave = { _, _, _ -> }) } } @Composable @Preview fun EditServerViewPreviewExisting() { - VariantTheme { - EditServerView( - "hostname:7171", - "reader@comixproject.org", - "my!password", - onSave = { _, _, _ -> }) - } -} \ No newline at end of file + VariantTheme { + EditServerView( + "hostname:7171", + "reader@comixproject.org", + "my!password", + onSave = { _, _, _ -> }, + ) + } +} diff --git a/androidVariant/src/main/java/org/comixedproject/variant/android/view/settings/SettingsView.kt b/androidVariant/src/main/java/org/comixedproject/variant/android/view/settings/SettingsView.kt index 6a53b678..a358a538 100644 --- a/androidVariant/src/main/java/org/comixedproject/variant/android/view/settings/SettingsView.kt +++ b/androidVariant/src/main/java/org/comixedproject/variant/android/view/settings/SettingsView.kt @@ -28,32 +28,31 @@ private val TAG = "SettingsView" @Composable fun SettingsView( - address: String, - username: String, - password: String, - onSaveSettings: (String, String, String) -> Unit, - modifier: Modifier = Modifier + address: String, + username: String, + password: String, + onSaveSettings: (String, String, String) -> Unit, + modifier: Modifier = Modifier, ) { - Column(modifier = modifier) { - EditServerView( - address, - username, - password, - onSave = { address, username, password -> - onSaveSettings(address, username, password) - } - ) - } + Column(modifier = modifier) { + EditServerView( + address, + username, + password, + onSave = { address, username, password -> onSaveSettings(address, username, password) }, + ) + } } @Composable @Preview fun SettingsViewPreview() { - VariantTheme { - SettingsView( - "http://www.comixedproject.org:7171", - "reader@comixedproject.org", - "my!password", - onSaveSettings = { _, _, _ -> }) - } -} \ No newline at end of file + VariantTheme { + SettingsView( + "http://www.comixedproject.org:7171", + "reader@comixedproject.org", + "my!password", + onSaveSettings = { _, _, _ -> }, + ) + } +} diff --git a/androidVariant/src/main/res/drawable/ic_cover_image_placeholder.xml b/androidVariant/src/main/res/drawable/ic_cover_image_placeholder.xml index e7f653fc..538beac6 100644 --- a/androidVariant/src/main/res/drawable/ic_cover_image_placeholder.xml +++ b/androidVariant/src/main/res/drawable/ic_cover_image_placeholder.xml @@ -16,4 +16,4 @@ android:pathData="M1300.061 348.398l-0.37 -9.633c-1.111 -18.896 5.188 -38.162 21.858 -58.169c11.856 -14.078 21.49 -25.934 21.49 -38.532c0 -12.967 -8.522 -21.488 -27.046 -22.229c-12.228 0 -27.048 4.446 -36.681 11.115l-12.597 -40.385c13.339 -7.78 35.568 -15.19 61.873 -15.19c48.906 0 71.136 27.046 71.136 57.798c0 28.158 -17.412 46.683 -31.493 62.244c-13.707 15.19 -19.265 29.64 -18.895 46.313v6.669H1300.061zM1290.428 404.112c0 -19.636 13.709 -33.714 32.975 -33.714c20.007 0 32.974 14.078 33.345 33.714c0 19.268 -13.338 33.717 -33.345 33.717C1303.766 437.829 1290.428 423.379 1290.428 404.112z" android:fillColor="#FFFFFF" /> - \ No newline at end of file + diff --git a/androidVariant/src/main/res/values/styles.xml b/androidVariant/src/main/res/values/styles.xml index 6b4fa3d0..676b4dda 100644 --- a/androidVariant/src/main/res/values/styles.xml +++ b/androidVariant/src/main/res/values/styles.xml @@ -1,3 +1,3 @@