diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7220e53..72a00ab 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -5,19 +5,17 @@ on: branches: [ main ] pull_request: branches: [ main ] - release: - types: [ created ] jobs: check: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - - name: Set up JDK 17 - uses: actions/setup-java@v4 + - name: Set up JDK 21 + uses: actions/setup-java@v5 with: - java-version: '17' + java-version: '21' distribution: 'temurin' - name: Grant execute permission for gradlew @@ -31,40 +29,3 @@ jobs: - name: Build debug APK run: ./gradlew assembleDebug --stacktrace - - release: - runs-on: ubuntu-latest - if: github.event_name == 'release' - steps: - - uses: actions/checkout@v4 - with: - ref: ${{ github.event.release.tag_name }} - fetch-depth: 0 - - - name: Set up JDK 17 - uses: actions/setup-java@v4 - with: - java-version: '17' - distribution: 'temurin' - - - name: Grant execute permission for gradlew - run: chmod +x gradlew - - - name: Build release bundle - run: ./gradlew bundleRelease --stacktrace - - - name: Rename bundle - run: mv app/build/outputs/bundle/release/app-release.aab prism.aab - - - name: Upload release bundle - uses: actions/upload-artifact@v4 - with: - name: prism-bundle - path: prism.aab - - - name: Upload to release - uses: softprops/action-gh-release@v1 - with: - files: prism.aab - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..33bd494 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,42 @@ +name: Release + +on: + release: + types: [ created ] + +jobs: + release: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + with: + ref: ${{ github.event.release.tag_name }} + fetch-depth: 0 + + - name: Set up JDK 21 + uses: actions/setup-java@v5 + with: + java-version: '21' + distribution: 'temurin' + + - name: Grant execute permission for gradlew + run: chmod +x gradlew + + - name: Build release bundle + run: ./gradlew bundleRelease --stacktrace + + - name: Rename bundle + run: mv app/build/outputs/bundle/release/app-release.aab prism.aab + + - name: Upload release bundle + uses: actions/upload-artifact@v6 + with: + name: prism-bundle + path: prism.aab + + - name: Upload to release + uses: softprops/action-gh-release@v2 + with: + files: prism.aab + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore index 8f13c87..9202bc3 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,4 @@ build local.properties .idea prism-release.keystore +.kotlin/sessions/kotlin-compiler-* diff --git a/app-compressed.apk b/app-compressed.apk deleted file mode 100644 index fbd24f8..0000000 Binary files a/app-compressed.apk and /dev/null differ diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 7f9f6e1..50259a7 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -16,15 +16,19 @@ detekt { buildUponDefaultConfig = true } +kotlin { + jvmToolchain(21) +} + android { compileOptions { - targetCompatibility = JavaVersion.VERSION_17 - sourceCompatibility = JavaVersion.VERSION_17 + sourceCompatibility = JavaVersion.VERSION_21 + targetCompatibility = JavaVersion.VERSION_21 } kotlin { compilerOptions { - jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17) + jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_21) } } diff --git a/app/src/main/java/app/lonecloud/prism/activities/ui/AppPickerDialog.kt b/app/src/main/java/app/lonecloud/prism/activities/ui/AppPickerDialog.kt index 18f9757..9ab44b0 100644 --- a/app/src/main/java/app/lonecloud/prism/activities/ui/AppPickerDialog.kt +++ b/app/src/main/java/app/lonecloud/prism/activities/ui/AppPickerDialog.kt @@ -48,7 +48,7 @@ fun AppPickerDialog( AlertDialog( onDismissRequest = onDismiss, - modifier = Modifier.fillMaxWidth(0.98f), + modifier = Modifier.fillMaxWidth(), title = { Text(stringResource(R.string.select_target_app_title)) }, text = { Column { diff --git a/app/src/main/java/app/lonecloud/prism/activities/ui/PrismPreferences.kt b/app/src/main/java/app/lonecloud/prism/activities/ui/PrismPreferences.kt new file mode 100644 index 0000000..d89cd34 --- /dev/null +++ b/app/src/main/java/app/lonecloud/prism/activities/ui/PrismPreferences.kt @@ -0,0 +1,57 @@ +package app.lonecloud.prism.activities.ui + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.material3.Switch +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.RectangleShape +import androidx.compose.ui.unit.dp + +@Composable +fun PrismTogglePreference( + title: String, + description: String? = null, + checked: Boolean, + onCheckedChange: (Boolean) -> Unit +) { + Surface( + onClick = { onCheckedChange(!checked) }, + modifier = Modifier.fillMaxWidth(), + shape = RectangleShape + ) { + Row( + modifier = Modifier.padding(16.dp), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ) { + Column( + modifier = Modifier.weight(1f), + verticalArrangement = Arrangement.spacedBy(4.dp) + ) { + Text( + text = title, + style = MaterialTheme.typography.bodyLarge + ) + description?.let { + Text( + text = it, + style = MaterialTheme.typography.bodySmall, + color = MaterialTheme.colorScheme.onSurfaceVariant + ) + } + } + Switch( + checked = checked, + onCheckedChange = null + ) + } + } +} diff --git a/app/src/main/java/app/lonecloud/prism/activities/ui/RestartServicesPreference.kt b/app/src/main/java/app/lonecloud/prism/activities/ui/RestartServicesPreference.kt index 336984e..3525524 100644 --- a/app/src/main/java/app/lonecloud/prism/activities/ui/RestartServicesPreference.kt +++ b/app/src/main/java/app/lonecloud/prism/activities/ui/RestartServicesPreference.kt @@ -1,14 +1,36 @@ package app.lonecloud.prism.activities.ui -import androidx.compose.material3.Button +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.RectangleShape import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp import app.lonecloud.prism.R @Composable fun RestartServicesPreference(onClick: () -> Unit) { - Button(onClick = onClick) { - Text(stringResource(R.string.restart_service_button)) + Surface( + onClick = onClick, + modifier = Modifier.fillMaxWidth(), + shape = RectangleShape + ) { + Column( + modifier = Modifier.padding(16.dp), + horizontalAlignment = Alignment.Start, + verticalArrangement = Arrangement.spacedBy(4.dp) + ) { + Text( + text = stringResource(R.string.restart_service_button), + style = MaterialTheme.typography.bodyLarge + ) + } } } diff --git a/app/src/main/java/app/lonecloud/prism/activities/ui/SettingsScreen.kt b/app/src/main/java/app/lonecloud/prism/activities/ui/SettingsScreen.kt index 89013b9..4760197 100644 --- a/app/src/main/java/app/lonecloud/prism/activities/ui/SettingsScreen.kt +++ b/app/src/main/java/app/lonecloud/prism/activities/ui/SettingsScreen.kt @@ -2,11 +2,9 @@ package app.lonecloud.prism.activities.ui import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp @@ -14,16 +12,12 @@ import androidx.lifecycle.Lifecycle import androidx.lifecycle.compose.LocalLifecycleOwner import androidx.lifecycle.repeatOnLifecycle import androidx.lifecycle.viewmodel.compose.viewModel -import app.lonecloud.prism.R import app.lonecloud.prism.activities.DistribMigrationViewModel import app.lonecloud.prism.activities.PreviewFactory import app.lonecloud.prism.activities.SettingsViewModel import app.lonecloud.prism.activities.ThemeViewModel import org.unifiedpush.android.distributor.ui.compose.DistribMigrationUi -import org.unifiedpush.android.distributor.ui.compose.DynamicColorsPreferences -import org.unifiedpush.android.distributor.ui.compose.Heading import org.unifiedpush.android.distributor.ui.compose.MigrationPreferences -import org.unifiedpush.android.distributor.ui.compose.ShowToastsPreference @Composable fun SettingsScreen( @@ -39,23 +33,9 @@ fun SettingsScreen( } } Column( - modifier = Modifier - .padding(16.dp), horizontalAlignment = Alignment.Start, verticalArrangement = Arrangement.spacedBy(20.dp) ) { - Heading(R.string.app_name) - - ShowToastsPreference(viewModel.state.showToasts) { - viewModel.toggleShowToasts() - } - - DynamicColorsPreferences(themeViewModel.dynamicColors) { - themeViewModel.toggleDynamicColors() - } - - MigrationPreferences(migrationViewModel) - PrismServerConfigButton( currentUrl = viewModel.state.prismServerUrl, onConfigure = { url, apiKey -> @@ -64,6 +44,21 @@ fun SettingsScreen( } ) + PrismTogglePreference( + title = "Show Toasts", + description = "Display toast notifications for registration and unregistration events", + checked = viewModel.state.showToasts, + onCheckedChange = { viewModel.toggleShowToasts() } + ) + + PrismTogglePreference( + title = "Dynamic Colors", + checked = themeViewModel.dynamicColors, + onCheckedChange = { themeViewModel.toggleDynamicColors() } + ) + + MigrationPreferences(migrationViewModel) + RestartServicesPreference { viewModel.restartService() } diff --git a/app/src/main/java/app/lonecloud/prism/activities/ui/SupServerConfig.kt b/app/src/main/java/app/lonecloud/prism/activities/ui/SupServerConfig.kt index 0c1095d..cc6020f 100644 --- a/app/src/main/java/app/lonecloud/prism/activities/ui/SupServerConfig.kt +++ b/app/src/main/java/app/lonecloud/prism/activities/ui/SupServerConfig.kt @@ -5,12 +5,14 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.material3.AlertDialog import androidx.compose.material3.Button import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedTextField +import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable @@ -20,6 +22,7 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.RectangleShape import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp @@ -29,22 +32,28 @@ import app.lonecloud.prism.R fun PrismServerConfigButton(currentUrl: String, onConfigure: (url: String, apiKey: String) -> Unit) { var showDialog by remember { mutableStateOf(false) } - TextButton( + Surface( onClick = { showDialog = true }, - modifier = Modifier.fillMaxWidth() + modifier = Modifier.fillMaxWidth(), + shape = RectangleShape ) { Column( + modifier = Modifier.padding(16.dp), horizontalAlignment = Alignment.Start, - modifier = Modifier.fillMaxWidth() + verticalArrangement = Arrangement.spacedBy(4.dp) ) { - Text(stringResource(R.string.configure_server)) + Text( + text = stringResource(R.string.configure_server), + style = MaterialTheme.typography.bodyLarge + ) Text( text = if (currentUrl.isNotBlank()) { stringResource(R.string.prism_server_configured, currentUrl) } else { stringResource(R.string.prism_server_not_configured) }, - style = MaterialTheme.typography.bodySmall + style = MaterialTheme.typography.bodySmall, + color = MaterialTheme.colorScheme.onSurfaceVariant ) } } diff --git a/app/src/main/java/app/lonecloud/prism/activities/ui/theme/Color.kt b/app/src/main/java/app/lonecloud/prism/activities/ui/theme/Color.kt index 3272bb6..63cb698 100644 --- a/app/src/main/java/app/lonecloud/prism/activities/ui/theme/Color.kt +++ b/app/src/main/java/app/lonecloud/prism/activities/ui/theme/Color.kt @@ -2,11 +2,11 @@ package app.lonecloud.prism.activities.ui.theme import androidx.compose.ui.graphics.Color -// Prism theme: pleasant sky blue primary with bright, modern accents -val primaryLight = Color(0xFF0288D1) +// Prism theme: modern Twitter/Bluesky blue primary with bright, modern accents +val primaryLight = Color(0xFF1DA1F2) val onPrimaryLight = Color(0xFFFFFFFF) -val primaryContainerLight = Color(0xFFB3E5FC) -val onPrimaryContainerLight = Color(0xFF01579B) +val primaryContainerLight = Color(0xFFB3E0FF) +val onPrimaryContainerLight = Color(0xFF0A4E73) val secondaryLight = Color(0xFF625B71) val onSecondaryLight = Color(0xFFFFFFFF) val secondaryContainerLight = Color(0xFFE8DEF8) @@ -30,7 +30,7 @@ val outlineVariantLight = Color(0xFFCAC4CF) val scrimLight = Color(0xFF000000) val inverseSurfaceLight = Color(0xFF313033) val inverseOnSurfaceLight = Color(0xFFF4EFF4) -val inversePrimaryLight = Color(0xFF81D4FA) +val inversePrimaryLight = Color(0xFF71C9F8) val surfaceDimLight = Color(0xFFDDD8DD) val surfaceBrightLight = Color(0xFFFFFBFF) val surfaceContainerLowestLight = Color(0xFFFFFFFF) @@ -39,10 +39,10 @@ val surfaceContainerLight = Color(0xFFF1ECF1) val surfaceContainerHighLight = Color(0xFFEBE6EB) val surfaceContainerHighestLight = Color(0xFFE6E1E6) -val primaryDark = Color(0xFF81D4FA) -val onPrimaryDark = Color(0xFF004D6F) -val primaryContainerDark = Color(0xFF00668C) -val onPrimaryContainerDark = Color(0xFFB3E5FC) +val primaryDark = Color(0xFF71C9F8) +val onPrimaryDark = Color(0xFF003D5C) +val primaryContainerDark = Color(0xFF0A6EA8) +val onPrimaryContainerDark = Color(0xFFB3E0FF) val secondaryDark = Color(0xFFCBC2DB) val onSecondaryDark = Color(0xFF332D41) val secondaryContainerDark = Color(0xFF4A4458) @@ -66,7 +66,7 @@ val outlineVariantDark = Color(0xFF49454E) val scrimDark = Color(0xFF000000) val inverseSurfaceDark = Color(0xFFE6E1E6) val inverseOnSurfaceDark = Color(0xFF313033) -val inversePrimaryDark = Color(0xFF0288D1) +val inversePrimaryDark = Color(0xFF1DA1F2) val surfaceDimDark = Color(0xFF141218) val surfaceBrightDark = Color(0xFF3A383E) val surfaceContainerLowestDark = Color(0xFF0F0D13)