diff --git a/.github/workflows/Preview.yml b/.github/workflows/Preview.yml index c23aa3e9..d39e27e3 100644 --- a/.github/workflows/Preview.yml +++ b/.github/workflows/Preview.yml @@ -30,7 +30,7 @@ jobs: arch: x64 os: macOS-latest shell: bash - build: packageUberJarForCurrentOS # packageDmg notarizeDmg + build: packageUberJarForCurrentOS packageDmg notarizeDmg setupCl: ./scripts/SetupClUnix.sh - runtime: win-x64 diff --git a/build.gradle.kts b/build.gradle.kts index dfa91dbb..b3fef253 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -8,10 +8,10 @@ import org.jmailen.gradle.kotlinter.tasks.FormatTask import org.jmailen.gradle.kotlinter.tasks.LintTask plugins { - kotlin("jvm") version "1.5.30" - kotlin("kapt") version "1.5.30" - kotlin("plugin.serialization") version "1.5.30" - id("org.jetbrains.compose") version "1.0.0-alpha4-build328" + kotlin("jvm") version "1.5.31" + kotlin("kapt") version "1.5.31" + kotlin("plugin.serialization") version "1.5.31" + id("org.jetbrains.compose") version "1.0.0-beta1" id("com.github.gmazzo.buildconfig") version "3.0.3" id("org.jmailen.kotlinter") version "3.6.0" id("com.github.ben-manes.versions") version "0.39.0" @@ -33,8 +33,8 @@ dependencies { implementation(compose.materialIconsExtended) implementation(compose("org.jetbrains.compose.ui:ui-util")) implementation("ca.gosyer:compose-router:0.24.2-jetbrains-2") - implementation("ca.gosyer:accompanist-pager:0.14.0") - implementation("ca.gosyer:accompanist-flowlayout:0.14.0") + implementation("ca.gosyer:accompanist-pager:0.18.1") + implementation("ca.gosyer:accompanist-flowlayout:0.18.1") // UI (Swing) implementation("com.github.weisj:darklaf-core:2.7.3") @@ -58,7 +58,7 @@ dependencies { kapt("com.github.stephanenicolas.toothpick:toothpick-compiler:$toothpickVersion") // Http client - val ktorVersion = "1.6.3" + val ktorVersion = "1.6.4" implementation("io.ktor:ktor-client-core:$ktorVersion") implementation("io.ktor:ktor-client-okhttp:$ktorVersion") implementation("io.ktor:ktor-client-serialization:$ktorVersion") diff --git a/src/main/kotlin/ca/gosyer/data/ui/model/WindowSettings.kt b/src/main/kotlin/ca/gosyer/data/ui/model/WindowSettings.kt index d8dd5510..1d824eeb 100644 --- a/src/main/kotlin/ca/gosyer/data/ui/model/WindowSettings.kt +++ b/src/main/kotlin/ca/gosyer/data/ui/model/WindowSettings.kt @@ -6,10 +6,10 @@ package ca.gosyer.data.ui.model +import androidx.compose.ui.unit.DpSize import androidx.compose.ui.unit.dp import androidx.compose.ui.window.WindowPlacement import androidx.compose.ui.window.WindowPosition -import androidx.compose.ui.window.WindowSize import kotlinx.serialization.Serializable @Serializable @@ -26,13 +26,13 @@ data class WindowSettings( if (maximized == true) { return WindowGet( WindowPosition.PlatformDefault, - WindowSize(800.dp, 600.dp), + DpSize(800.dp, 600.dp), WindowPlacement.Maximized ) } else if (fullscreen == true) { return WindowGet( WindowPosition.PlatformDefault, - WindowSize(800.dp, 600.dp), + DpSize(800.dp, 600.dp), WindowPlacement.Fullscreen ) } @@ -42,7 +42,7 @@ data class WindowSettings( } else { WindowPosition.PlatformDefault } - val size = WindowSize((width ?: 800).dp, (height ?: 600).dp) + val size = DpSize((width ?: 800).dp, (height ?: 600).dp) return WindowGet( offset, size, @@ -60,7 +60,7 @@ data class WindowSettings( data class WindowGet( val offset: WindowPosition, - val size: WindowSize, + val size: DpSize, val placement: WindowPlacement ) } diff --git a/src/main/kotlin/ca/gosyer/ui/base/WindowDialog.kt b/src/main/kotlin/ca/gosyer/ui/base/WindowDialog.kt index 20e3f340..8c37a8b0 100644 --- a/src/main/kotlin/ca/gosyer/ui/base/WindowDialog.kt +++ b/src/main/kotlin/ca/gosyer/ui/base/WindowDialog.kt @@ -29,10 +29,10 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.input.key.Key import androidx.compose.ui.input.key.KeyEvent import androidx.compose.ui.input.key.key +import androidx.compose.ui.unit.DpSize import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Window import androidx.compose.ui.window.WindowPosition -import androidx.compose.ui.window.WindowSize import androidx.compose.ui.window.rememberWindowState import ca.gosyer.common.di.AppScope import ca.gosyer.data.translation.XmlResourceBundle @@ -46,7 +46,7 @@ import kotlinx.coroutines.DelicateCoroutinesApi @Suppress("FunctionName") fun WindowDialog( title: String = "Dialog", - size: WindowSize = WindowSize(400.dp, 200.dp), + size: DpSize = DpSize(400.dp, 200.dp), onCloseRequest: (() -> Unit)? = null, forceFocus: Boolean = true, showNegativeButton: Boolean = true, @@ -130,7 +130,7 @@ fun WindowDialog( @OptIn(DelicateCoroutinesApi::class) fun WindowDialog( title: String = "Dialog", - size: WindowSize = WindowSize(400.dp, 200.dp), + size: DpSize = DpSize(400.dp, 200.dp), onCloseRequest: (() -> Unit)? = null, forceFocus: Boolean = true, keyboardShortcuts: Map Boolean> = emptyMap(), diff --git a/src/main/kotlin/ca/gosyer/ui/base/components/BoxWithTooltipSurface.kt b/src/main/kotlin/ca/gosyer/ui/base/components/BoxWithTooltipSurface.kt index 9c92ad1f..f5f31f65 100644 --- a/src/main/kotlin/ca/gosyer/ui/base/components/BoxWithTooltipSurface.kt +++ b/src/main/kotlin/ca/gosyer/ui/base/components/BoxWithTooltipSurface.kt @@ -6,12 +6,11 @@ package ca.gosyer.ui.base.components -import androidx.compose.foundation.BoxWithTooltip +import androidx.compose.foundation.TooltipArea import androidx.compose.foundation.TooltipPlacement import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.Surface import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.shadow import androidx.compose.ui.unit.DpOffset @@ -21,15 +20,13 @@ import androidx.compose.ui.unit.dp fun BoxWithTooltipSurface( tooltip: @Composable () -> Unit, modifier: Modifier = Modifier, - contentAlignment: Alignment = Alignment.TopStart, - propagateMinConstraints: Boolean = false, - delay: Int = 500, - offset: TooltipPlacement = TooltipPlacement.CursorPoint( + delayMillis: Int = 500, + tooltipPlacement: TooltipPlacement = TooltipPlacement.CursorPoint( offset = DpOffset(0.dp, 16.dp) ), content: @Composable () -> Unit ) { - BoxWithTooltip( + TooltipArea( { Surface( modifier = Modifier.shadow(4.dp), @@ -39,10 +36,8 @@ fun BoxWithTooltipSurface( ) }, modifier, - contentAlignment, - propagateMinConstraints, - delay, - offset, + delayMillis, + tooltipPlacement, content ) } diff --git a/src/main/kotlin/ca/gosyer/ui/base/components/ColorPickerDialog.kt b/src/main/kotlin/ca/gosyer/ui/base/components/ColorPickerDialog.kt index 7304d0e2..f2917ecd 100644 --- a/src/main/kotlin/ca/gosyer/ui/base/components/ColorPickerDialog.kt +++ b/src/main/kotlin/ca/gosyer/ui/base/components/ColorPickerDialog.kt @@ -62,10 +62,10 @@ import androidx.compose.ui.graphics.toArgb import androidx.compose.ui.input.pointer.PointerInputScope import androidx.compose.ui.input.pointer.pointerInput import androidx.compose.ui.layout.onSizeChanged +import androidx.compose.ui.unit.DpSize import androidx.compose.ui.unit.IntSize import androidx.compose.ui.unit.dp import androidx.compose.ui.util.fastForEachIndexed -import androidx.compose.ui.window.WindowSize import ca.gosyer.ui.base.WindowDialog import kotlinx.coroutines.flow.MutableStateFlow import kotlin.math.round @@ -81,7 +81,7 @@ fun ColorPickerDialog( WindowDialog( onCloseRequest = onCloseRequest, - size = WindowSize(300.dp, 520.dp), + size = DpSize(300.dp, 520.dp), title = title, content = { val showPresetsState by showPresets.collectAsState() diff --git a/src/main/kotlin/ca/gosyer/ui/base/components/CombinedMouseClickable.kt b/src/main/kotlin/ca/gosyer/ui/base/components/CombinedMouseClickable.kt index f32b5e2f..4c65c9af 100644 --- a/src/main/kotlin/ca/gosyer/ui/base/components/CombinedMouseClickable.kt +++ b/src/main/kotlin/ca/gosyer/ui/base/components/CombinedMouseClickable.kt @@ -7,7 +7,6 @@ package ca.gosyer.ui.base.components import androidx.compose.foundation.ContextMenuItem -import androidx.compose.foundation.ExperimentalDesktopApi import androidx.compose.foundation.MouseClickScope import androidx.compose.foundation.mouseClickable import androidx.compose.material.CursorDropdownMenu @@ -28,7 +27,6 @@ import androidx.compose.ui.semantics.Role import androidx.compose.ui.semantics.SemanticsPropertyKey import androidx.compose.ui.semantics.semantics -@OptIn(ExperimentalDesktopApi::class) fun Modifier.contextMenuClickable( items: () -> List, onClickLabel: String? = null, @@ -75,7 +73,6 @@ fun Modifier.contextMenuClickable( ) } -@OptIn(ExperimentalDesktopApi::class) fun Modifier.combinedMouseClickable( enabled: Boolean = true, onClickLabel: String? = null, @@ -116,7 +113,6 @@ fun Modifier.combinedMouseClickable( } } -@OptIn(ExperimentalDesktopApi::class) private object DesktopSemanticsActions { val onRightClick = ActionPropertyKey Boolean>("OnRightClick") val onMiddleClick = ActionPropertyKey Boolean>("OnMiddleClick") diff --git a/src/main/kotlin/ca/gosyer/ui/base/prefs/PreferencesUiBuilder.kt b/src/main/kotlin/ca/gosyer/ui/base/prefs/PreferencesUiBuilder.kt index d448bb13..875866d8 100644 --- a/src/main/kotlin/ca/gosyer/ui/base/prefs/PreferencesUiBuilder.kt +++ b/src/main/kotlin/ca/gosyer/ui/base/prefs/PreferencesUiBuilder.kt @@ -235,32 +235,31 @@ fun ChoiceDialog( WindowDialog( onCloseRequest = onCloseRequest, buttons = buttons, - title = title, - content = { - LazyColumn(Modifier.fillMaxSize()) { - items(items) { (value, text) -> - Row( - modifier = Modifier.requiredHeight(48.dp).fillMaxWidth().clickable( - onClick = { - onSelected(value) - it() - } - ), - verticalAlignment = Alignment.CenterVertically - ) { - RadioButton( - selected = value == selected, - onClick = { - onSelected(value) - it() - }, - ) - Text(text = text, modifier = Modifier.padding(start = 24.dp)) - } + title = title + ) { + LazyColumn(Modifier.fillMaxSize()) { + items(items) { (value, text) -> + Row( + modifier = Modifier.requiredHeight(48.dp).fillMaxWidth().clickable( + onClick = { + onSelected(value) + it() + } + ), + verticalAlignment = Alignment.CenterVertically + ) { + RadioButton( + selected = value == selected, + onClick = { + onSelected(value) + it() + }, + ) + Text(text = text, modifier = Modifier.padding(start = 24.dp)) } } } - ) + } } @Composable diff --git a/src/main/kotlin/ca/gosyer/ui/base/theme/AppTheme.kt b/src/main/kotlin/ca/gosyer/ui/base/theme/AppTheme.kt index 9479efca..0c7e807a 100644 --- a/src/main/kotlin/ca/gosyer/ui/base/theme/AppTheme.kt +++ b/src/main/kotlin/ca/gosyer/ui/base/theme/AppTheme.kt @@ -7,15 +7,20 @@ package ca.gosyer.ui.base.theme import androidx.compose.desktop.DesktopMaterialTheme +import androidx.compose.foundation.LocalScrollbarStyle +import androidx.compose.foundation.ScrollbarStyle import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.material.Colors +import androidx.compose.material.MaterialTheme import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.luminance import androidx.compose.ui.graphics.takeOrElse +import androidx.compose.ui.unit.dp import ca.gosyer.data.ui.UiPreferences import ca.gosyer.data.ui.model.ThemeMode import ca.gosyer.ui.base.vm.ViewModel @@ -36,7 +41,19 @@ fun AppTheme(content: @Composable () -> Unit) { val colors = vm.getColors() /*val systemUiController = rememberSystemUiController()*/ - DesktopMaterialTheme(colors = colors, content = content) + MaterialTheme(colors = colors) { + CompositionLocalProvider( + LocalScrollbarStyle provides ScrollbarStyle( + minimalHeight = 16.dp, + thickness = 8.dp, + shape = MaterialTheme.shapes.small, + hoverDurationMillis = 300, + unhoverColor = MaterialTheme.colors.onSurface.copy(alpha = 0.12f), + hoverColor = MaterialTheme.colors.onSurface.copy(alpha = 0.50f) + ), + content = content + ) + } } private class AppThemeViewModel @Inject constructor( diff --git a/src/main/kotlin/ca/gosyer/ui/extensions/ExtensionsMenu.kt b/src/main/kotlin/ca/gosyer/ui/extensions/ExtensionsMenu.kt index 7e21b368..305800c0 100644 --- a/src/main/kotlin/ca/gosyer/ui/extensions/ExtensionsMenu.kt +++ b/src/main/kotlin/ca/gosyer/ui/extensions/ExtensionsMenu.kt @@ -42,9 +42,9 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.withStyle +import androidx.compose.ui.unit.DpSize import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import androidx.compose.ui.window.WindowSize import androidx.compose.ui.window.rememberWindowState import ca.gosyer.build.BuildConfig import ca.gosyer.data.models.Extension @@ -66,7 +66,7 @@ import java.util.Locale @OptIn(DelicateCoroutinesApi::class) fun openExtensionsMenu() { launchApplication { - val state = rememberWindowState(size = WindowSize(550.dp, 700.dp)) + val state = rememberWindowState(size = DpSize(550.dp, 700.dp)) ThemedWindow(::exitApplication, state, title = BuildConfig.NAME) { Surface { ExtensionsMenu() diff --git a/src/main/kotlin/ca/gosyer/ui/sources/SourcesMenu.kt b/src/main/kotlin/ca/gosyer/ui/sources/SourcesMenu.kt index 9e77052e..ce900c57 100644 --- a/src/main/kotlin/ca/gosyer/ui/sources/SourcesMenu.kt +++ b/src/main/kotlin/ca/gosyer/ui/sources/SourcesMenu.kt @@ -7,7 +7,8 @@ package ca.gosyer.ui.sources import androidx.compose.animation.Crossfade -import androidx.compose.foundation.BoxWithTooltip +import androidx.compose.foundation.TooltipArea +import androidx.compose.foundation.TooltipPlacement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row @@ -34,6 +35,7 @@ import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.shadow +import androidx.compose.ui.unit.DpOffset import androidx.compose.ui.unit.dp import ca.gosyer.build.BuildConfig import ca.gosyer.ui.base.components.ActionIcon @@ -133,7 +135,7 @@ fun SourcesMenu(bundle: Bundle, onSourceSettingsClick: (Long) -> Unit, onMangaCl Surface(elevation = 1.dp) { LazyColumn(Modifier.fillMaxHeight().width(64.dp)) { items(sourceTabs) { source -> - BoxWithTooltip( + TooltipArea( { Surface( modifier = Modifier.shadow(4.dp), @@ -143,7 +145,10 @@ fun SourcesMenu(bundle: Bundle, onSourceSettingsClick: (Long) -> Unit, onMangaCl Text(source?.name ?: stringResource("sources_home"), modifier = Modifier.padding(10.dp)) } }, - modifier = Modifier.size(64.dp) + modifier = Modifier.size(64.dp), + tooltipPlacement = TooltipPlacement.CursorPoint( + offset = DpOffset(0.dp, 16.dp) + ) ) { Box(Modifier.fillMaxSize()) { val modifier = Modifier diff --git a/src/main/kotlin/ca/gosyer/ui/sources/components/SourceHomeScreen.kt b/src/main/kotlin/ca/gosyer/ui/sources/components/SourceHomeScreen.kt index a52f0abf..82f95b0c 100644 --- a/src/main/kotlin/ca/gosyer/ui/sources/components/SourceHomeScreen.kt +++ b/src/main/kotlin/ca/gosyer/ui/sources/components/SourceHomeScreen.kt @@ -6,7 +6,7 @@ package ca.gosyer.ui.sources.components -import androidx.compose.foundation.BoxWithTooltip +import androidx.compose.foundation.TooltipArea import androidx.compose.foundation.VerticalScrollbar import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box @@ -97,7 +97,7 @@ fun SourceItem( serverUrl: String, onSourceClicked: (Source) -> Unit ) { - BoxWithTooltip( + TooltipArea( { Surface( modifier = Modifier.shadow(4.dp), diff --git a/src/main/kotlin/ca/gosyer/util/compose/Image.kt b/src/main/kotlin/ca/gosyer/util/compose/Image.kt index c93b78ae..8faf56ac 100644 --- a/src/main/kotlin/ca/gosyer/util/compose/Image.kt +++ b/src/main/kotlin/ca/gosyer/util/compose/Image.kt @@ -7,19 +7,19 @@ package ca.gosyer.util.compose import androidx.compose.ui.graphics.ImageBitmap -import androidx.compose.ui.graphics.asImageBitmap +import androidx.compose.ui.graphics.toComposeImageBitmap import ca.gosyer.data.server.Http import io.ktor.client.request.HttpRequestBuilder import io.ktor.client.request.get import io.ktor.utils.io.ByteReadChannel import io.ktor.utils.io.jvm.javaio.copyTo -import org.jetbrains.skija.Image +import org.jetbrains.skia.Image import java.io.ByteArrayOutputStream import java.nio.file.Path import kotlin.io.path.readBytes fun imageFromFile(file: Path): ImageBitmap { - return Image.makeFromEncoded(file.readBytes()).asImageBitmap() + return Image.makeFromEncoded(file.readBytes()).toComposeImageBitmap() } suspend fun imageFromUrl(client: Http, url: String, block: HttpRequestBuilder.() -> Unit): ImageBitmap { @@ -27,5 +27,5 @@ suspend fun imageFromUrl(client: Http, url: String, block: HttpRequestBuilder.() client.get(url, block).copyTo(it) it.toByteArray() } - return Image.makeFromEncoded(bytes).asImageBitmap() + return Image.makeFromEncoded(bytes).toComposeImageBitmap() } diff --git a/src/main/kotlin/ca/gosyer/util/compose/Theme.kt b/src/main/kotlin/ca/gosyer/util/compose/Theme.kt index 5bd2233a..283eb1ff 100644 --- a/src/main/kotlin/ca/gosyer/util/compose/Theme.kt +++ b/src/main/kotlin/ca/gosyer/util/compose/Theme.kt @@ -29,6 +29,7 @@ fun ThemedWindow( title: String = "Untitled", icon: Painter? = null, undecorated: Boolean = false, + transparent: Boolean = false, resizable: Boolean = true, enabled: Boolean = true, focusable: Boolean = true, @@ -39,18 +40,19 @@ fun ThemedWindow( ) { val resources = remember { AppScope.getInstance() } Window( - onCloseRequest, - state, - visible, - title, - icon, - undecorated, - resizable, - enabled, - focusable, - alwaysOnTop, - onPreviewKeyEvent, - onKeyEvent + onCloseRequest = onCloseRequest, + state = state, + visible = visible, + title = title, + icon = icon, + undecorated = undecorated, + transparent = transparent, + resizable = resizable, + enabled = enabled, + focusable = focusable, + alwaysOnTop = alwaysOnTop, + onPreviewKeyEvent = onPreviewKeyEvent, + onKeyEvent = onKeyEvent ) { setIcon() CompositionLocalProvider(