diff --git a/app/build.gradle.kts b/app/build.gradle.kts index a5449935..3fdde6fb 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -1,5 +1,3 @@ -val composeBOM: String by rootProject.extra - kotlin { compilerOptions { extraWarnings.set(true) @@ -13,7 +11,7 @@ plugins { } android { - compileSdk = 36 + compileSdk = 37 defaultConfig { applicationId = "com.geode.launcher" @@ -80,8 +78,8 @@ android { // enables a polyfill for java Instant on api levels < 26 (used for updater) isCoreLibraryDesugaringEnabled = true - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 } buildFeatures { compose = true @@ -103,28 +101,28 @@ android { } dependencies { - implementation (platform("androidx.compose:compose-bom:$composeBOM")) - implementation ("androidx.core:core-ktx:1.18.0") + implementation (platform("androidx.compose:compose-bom:2026.08.00")) + implementation ("androidx.core:core-ktx:1.19.0") implementation ("androidx.compose.ui:ui") implementation ("androidx.compose.material3:material3") implementation ("androidx.compose.ui:ui-tooling-preview") - implementation ("androidx.lifecycle:lifecycle-runtime-ktx:2.10.0") - implementation ("androidx.lifecycle:lifecycle-viewmodel-compose:2.10.0") + implementation ("androidx.lifecycle:lifecycle-runtime-ktx:2.11.0") + implementation ("androidx.lifecycle:lifecycle-viewmodel-compose:2.11.0") implementation ("androidx.activity:activity-compose:1.13.0") implementation ("androidx.activity:activity-ktx:1.13.0") - implementation ("androidx.appcompat:appcompat:1.7.1") + implementation ("androidx.appcompat:appcompat:1.8.0") implementation ("androidx.documentfile:documentfile:1.1.0") - implementation ("com.squareup.okio:okio:3.17.0") - implementation ("com.squareup.okhttp3:okhttp:5.3.2") - implementation ("com.squareup.okhttp3:okhttp-coroutines:5.3.2") + implementation ("com.squareup.okio:okio:3.18.2") + implementation ("com.squareup.okhttp3:okhttp:5.5.0") + implementation ("com.squareup.okhttp3:okhttp-coroutines:5.5.0") - implementation ("org.jetbrains.kotlinx:kotlinx-serialization-json:1.10.0") - implementation ("org.jetbrains.kotlinx:kotlinx-serialization-json-okio:1.10.0") - implementation ("org.jetbrains.kotlinx:kotlinx-datetime:0.7.1") + implementation ("org.jetbrains.kotlinx:kotlinx-serialization-json:1.11.0") + implementation ("org.jetbrains.kotlinx:kotlinx-serialization-json-okio:1.11.0") + implementation ("org.jetbrains.kotlinx:kotlinx-datetime:0.8.0") - implementation ("com.mikepenz:multiplatform-markdown-renderer-android:0.39.2") - implementation ("com.mikepenz:multiplatform-markdown-renderer-m3:0.39.2") + implementation ("com.mikepenz:multiplatform-markdown-renderer-android:0.45.0") + implementation ("com.mikepenz:multiplatform-markdown-renderer-m3:0.45.0") implementation ("androidx.browser:browser:1.10.0") debugImplementation ("androidx.compose.ui:ui-tooling") coreLibraryDesugaring ("com.android.tools:desugar_jdk_libs:2.1.5") diff --git a/app/src/main/java/com/geode/launcher/MainActivity.kt b/app/src/main/java/com/geode/launcher/MainActivity.kt index 1df504ec..0b084ab4 100644 --- a/app/src/main/java/com/geode/launcher/MainActivity.kt +++ b/app/src/main/java/com/geode/launcher/MainActivity.kt @@ -256,7 +256,7 @@ fun mapLaunchStatusToInfo(state: LaunchViewModel.LaunchUIState, inSafeMode: Bool ) } is LaunchViewModel.LaunchUIState.Cancelled -> { - return mapCancelReasonToInfo(state.reason) + mapCancelReasonToInfo(state.reason) } } } diff --git a/app/src/main/java/com/geode/launcher/main/LaunchComponents.kt b/app/src/main/java/com/geode/launcher/main/LaunchComponents.kt index e40e0af8..c2b60784 100644 --- a/app/src/main/java/com/geode/launcher/main/LaunchComponents.kt +++ b/app/src/main/java/com/geode/launcher/main/LaunchComponents.kt @@ -36,6 +36,7 @@ import com.geode.launcher.utils.GeodeUtils import com.geode.launcher.utils.PreferenceUtils import kotlinx.coroutines.delay import kotlinx.coroutines.flow.collectLatest +import kotlin.time.Duration.Companion.milliseconds @Composable @@ -142,7 +143,7 @@ fun onSettings(context: Context) { } @Composable -fun LongPressButton(onClick: () -> Unit, onLongPress: () -> Unit, enabled: Boolean = true, modifier: Modifier = Modifier, content: @Composable RowScope.() -> Unit) { +fun LongPressButton(onClick: () -> Unit, onLongPress: () -> Unit, modifier: Modifier = Modifier, enabled: Boolean = true, content: @Composable RowScope.() -> Unit) { // compose apis don't provide a good way of adding long press to a button var isLongPress by remember { mutableStateOf(false) } @@ -154,11 +155,11 @@ fun LongPressButton(onClick: () -> Unit, onLongPress: () -> Unit, enabled: Boole interactionSource.interactions.collectLatest { interaction -> when (interaction) { is PressInteraction.Press -> { - delay(viewConfiguration.longPressTimeoutMillis) + delay(viewConfiguration.longPressTimeoutMillis.milliseconds) // perform a second delay to make the action more obvious haptics.performHapticFeedback(HapticFeedbackType.LongPress) - delay(viewConfiguration.longPressTimeoutMillis) + delay(viewConfiguration.longPressTimeoutMillis.milliseconds) haptics.performHapticFeedback(HapticFeedbackType.LongPress) diff --git a/app/src/main/java/com/geode/launcher/main/LaunchNotification.kt b/app/src/main/java/com/geode/launcher/main/LaunchNotification.kt index 9456c246..98129a67 100644 --- a/app/src/main/java/com/geode/launcher/main/LaunchNotification.kt +++ b/app/src/main/java/com/geode/launcher/main/LaunchNotification.kt @@ -39,6 +39,8 @@ import com.geode.launcher.utils.GamePackageUtils import com.geode.launcher.utils.GeodeUtils import com.geode.launcher.utils.PreferenceUtils import kotlinx.coroutines.delay +import kotlin.time.Duration +import kotlin.time.Duration.Companion.seconds enum class LaunchNotificationType { GEODE_UPDATED, LAUNCHER_UPDATE_AVAILABLE, UPDATE_FAILED, UNSUPPORTED_VERSION, FAILED_LOAD; @@ -87,7 +89,7 @@ fun NotificationCardFromType(type: LaunchNotificationType) { } AnimatedNotificationCard( - displayLength = 5000L, + displayLength = 5.seconds, onClick = { showInfoDialog = true } @@ -140,15 +142,15 @@ fun LaunchNotification(cards: List) { } @Composable -fun AnimatedNotificationCard(modifier: Modifier = Modifier, visibilityDelay: Long = 0L, displayLength: Long = 3000L, onClick: (() -> Unit)? = null, contents: @Composable () -> Unit) { +fun AnimatedNotificationCard(modifier: Modifier = Modifier, visibilityDelay: Duration = Duration.ZERO, displayLength: Duration = 3.seconds, onClick: (() -> Unit)? = null, contents: @Composable () -> Unit) { val state = remember { MutableTransitionState(false).apply { - targetState = visibilityDelay <= 0 + targetState = visibilityDelay <= Duration.ZERO } } LaunchedEffect(true) { - if (visibilityDelay > 0) { + if (visibilityDelay > Duration.ZERO) { delay(visibilityDelay) state.targetState = true } diff --git a/app/src/main/java/com/geode/launcher/main/UpdateComponents.kt b/app/src/main/java/com/geode/launcher/main/UpdateComponents.kt index b5ad4067..a154a41f 100644 --- a/app/src/main/java/com/geode/launcher/main/UpdateComponents.kt +++ b/app/src/main/java/com/geode/launcher/main/UpdateComponents.kt @@ -4,7 +4,6 @@ import android.app.PendingIntent import android.content.Context import android.content.Intent import android.content.pm.PackageInstaller -import android.os.Build import android.widget.Toast import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box diff --git a/app/src/main/java/com/geode/launcher/updater/ReleaseManager.kt b/app/src/main/java/com/geode/launcher/updater/ReleaseManager.kt index db7f7c3b..6d1a168f 100644 --- a/app/src/main/java/com/geode/launcher/updater/ReleaseManager.kt +++ b/app/src/main/java/com/geode/launcher/updater/ReleaseManager.kt @@ -25,7 +25,6 @@ import okio.sink import okio.source import java.io.File import java.io.FileNotFoundException -import java.io.IOException import java.io.InterruptedIOException import kotlin.math.max import kotlin.time.Clock diff --git a/app/src/main/java/com/geode/launcher/utils/FileUtils.kt b/app/src/main/java/com/geode/launcher/utils/FileUtils.kt index f361d066..b652ef1d 100644 --- a/app/src/main/java/com/geode/launcher/utils/FileUtils.kt +++ b/app/src/main/java/com/geode/launcher/utils/FileUtils.kt @@ -8,6 +8,7 @@ import android.os.Environment import android.provider.DocumentsContract import android.provider.MediaStore import java.io.File +import androidx.core.net.toUri class FileUtils { // copied from https://stackoverflow.com/questions/17546101/get-real-path-for-uri-android @@ -86,7 +87,7 @@ class FileUtils { val file = File(id) if (file.exists()) return id } - val contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), java.lang.Long.valueOf(id)) + val contentUri = ContentUris.withAppendedId("content://downloads/public_downloads".toUri(), java.lang.Long.valueOf(id)) return getDataColumn(context, contentUri, null, null) } diff --git a/app/src/main/java/com/geode/launcher/utils/GeodeUtils.kt b/app/src/main/java/com/geode/launcher/utils/GeodeUtils.kt index bed9c053..4776fa63 100644 --- a/app/src/main/java/com/geode/launcher/utils/GeodeUtils.kt +++ b/app/src/main/java/com/geode/launcher/utils/GeodeUtils.kt @@ -32,7 +32,6 @@ import androidx.core.net.toUri import androidx.documentfile.provider.DocumentFile import com.geode.launcher.BuildConfig import com.geode.launcher.R -import com.geode.launcher.UserDirectoryProvider import com.geode.launcher.activityresult.GeodeOpenFileActivityResult import com.geode.launcher.activityresult.GeodeOpenFilesActivityResult import com.geode.launcher.activityresult.GeodeSaveFileActivityResult @@ -430,7 +429,7 @@ object GeodeUtils { Manifest.permission.WRITE_EXTERNAL_STORAGE ) - return permissions.all { + permissions.all { ContextCompat.checkSelfPermission(context, it) == PackageManager.PERMISSION_GRANTED } } diff --git a/app/src/main/java/com/geode/launcher/utils/IconUtils.kt b/app/src/main/java/com/geode/launcher/utils/IconUtils.kt index 9c5275bc..d3e691f7 100644 --- a/app/src/main/java/com/geode/launcher/utils/IconUtils.kt +++ b/app/src/main/java/com/geode/launcher/utils/IconUtils.kt @@ -15,10 +15,6 @@ import androidx.compose.ui.res.painterResource import androidx.core.content.res.ResourcesCompat import androidx.core.graphics.drawable.toBitmap import com.geode.launcher.R -import kotlinx.datetime.Month -import kotlinx.datetime.TimeZone -import kotlinx.datetime.todayIn -import kotlin.time.Clock // https://gist.github.com/tkuenneth/ddf598663f041dc79960cda503d14448?permalink_comment_id=4660486#gistcomment-4660486 @Composable diff --git a/app/src/main/java/com/geode/launcher/utils/useCountdownTimer.kt b/app/src/main/java/com/geode/launcher/utils/useCountdownTimer.kt index 7ffcfe0a..545a9126 100644 --- a/app/src/main/java/com/geode/launcher/utils/useCountdownTimer.kt +++ b/app/src/main/java/com/geode/launcher/utils/useCountdownTimer.kt @@ -6,17 +6,19 @@ import androidx.lifecycle.Lifecycle import androidx.lifecycle.LifecycleEventObserver import androidx.lifecycle.LifecycleOwner import kotlinx.coroutines.delay +import kotlin.time.Duration +import kotlin.time.Duration.Companion.seconds const val MS_TO_SEC = 1000L @Composable fun useCountdownTimer( lifecycleOwner: LifecycleOwner = LocalLifecycleOwner.current, - time: Long, + time: Duration, onCountdownFinish: () -> Unit ): Long { var millisUntilFinished by remember { - mutableLongStateOf(time) + mutableStateOf(time) } var shouldBeCounting by remember { @@ -28,9 +30,9 @@ fun useCountdownTimer( return@LaunchedEffect } - if (millisUntilFinished > 0) { - delay(MS_TO_SEC) - millisUntilFinished -= MS_TO_SEC + if (millisUntilFinished > Duration.ZERO) { + delay(1.seconds) + millisUntilFinished -= 1.seconds } else { onCountdownFinish() } @@ -58,5 +60,5 @@ fun useCountdownTimer( } } - return millisUntilFinished / MS_TO_SEC + return millisUntilFinished.inWholeSeconds } \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index fee23f29..97f719b8 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,13 +1,9 @@ -buildscript { - val composeBOM by extra("2026.03.01") -} - // Top-level build file where you can add configuration options common to all sub-projects/modules. plugins { - id("com.android.application") version "9.1.0" apply false - id("com.android.library") version "9.1.0" apply false - id("org.jetbrains.kotlin.plugin.serialization") version "2.3.20" apply false - id("org.jetbrains.kotlin.plugin.compose") version "2.3.20" apply false + id("com.android.application") version "9.4.0" apply false + id("com.android.library") version "9.4.0" apply false + id("org.jetbrains.kotlin.plugin.serialization") version "2.4.10" apply false + id("org.jetbrains.kotlin.plugin.compose") version "2.4.10" apply false } tasks.register("clean") { diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 9bbc975c..eddabd2e 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index b8d20365..ad7845be 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,8 +1,9 @@ -#Sun Apr 05 23:29:16 MST 2026 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.7.1-bin.zip networkTimeout=10000 +retries=0 +retryBackOffMs=500 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index faf93008..249efbb0 100755 --- a/gradlew +++ b/gradlew @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright © 2015-2021 the original authors. +# Copyright © 2015 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -20,7 +20,7 @@ ############################################################################## # -# Gradle start up script for POSIX generated by Gradle. +# gradlew start up script for POSIX generated by Gradle. # # Important for running: # @@ -29,7 +29,7 @@ # bash, then to run this script, type that shell name before the whole # command line, like: # -# ksh Gradle +# ksh gradlew # # Busybox and similar reduced shells will NOT work, because this script # requires all of these POSIX shell features: @@ -57,7 +57,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/3d91ce3b8caaf77ad09f381f43615b715b53f72c/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -114,7 +114,6 @@ case "$( uname )" in #( NONSTOP* ) nonstop=true ;; esac -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. @@ -172,7 +171,6 @@ fi # For Cygwin or MSYS, switch paths to Windows format before running java if "$cygwin" || "$msys" ; then APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) - CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) JAVACMD=$( cygpath --unix "$JAVACMD" ) @@ -212,8 +210,7 @@ DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ "$@" # Stop when "xargs" is not available. diff --git a/gradlew.bat b/gradlew.bat index 9b42019c..8508ef68 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -19,12 +19,12 @@ @if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem -@rem Gradle startup script for Windows +@rem gradlew startup script for Windows @rem @rem ########################################################################## -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal +@rem Set local scope for the variables, and ensure extensions are enabled +setlocal EnableExtensions set DIRNAME=%~dp0 if "%DIRNAME%"=="" set DIRNAME=. @@ -51,7 +51,7 @@ echo. 1>&2 echo Please set the JAVA_HOME variable in your environment to match the 1>&2 echo location of your Java installation. 1>&2 -goto fail +"%COMSPEC%" /c exit 1 :findJavaFromJavaHome set JAVA_HOME=%JAVA_HOME:"=% @@ -65,30 +65,18 @@ echo. 1>&2 echo Please set the JAVA_HOME variable in your environment to match the 1>&2 echo location of your Java installation. 1>&2 -goto fail +"%COMSPEC%" /c exit 1 :execute @rem Setup the command line -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* +@rem Execute gradlew +@rem endlocal doesn't take effect until after the line is parsed and variables are expanded +@rem which allows us to clear the local environment before executing the java command +endlocal & "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* & call :exitWithErrorLevel -:end -@rem End local scope for the variables with windows NT shell -if %ERRORLEVEL% equ 0 goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -set EXIT_CODE=%ERRORLEVEL% -if %EXIT_CODE% equ 0 set EXIT_CODE=1 -if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% -exit /b %EXIT_CODE% - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega +:exitWithErrorLevel +@rem Use "%COMSPEC%" /c exit to allow operators to work properly in scripts +"%COMSPEC%" /c exit %ERRORLEVEL%