From a8650ead4e766ee991bb85c31ba472fe5624384b Mon Sep 17 00:00:00 2001 From: VizXtreme Date: Tue, 14 Jul 2026 19:01:56 +0000 Subject: [PATCH 01/19] ui: Customize dropdown menu styling to match Material card design --- .../droidspaces/app/ui/component/DsDropdown.kt | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/Android/app/src/main/java/com/droidspaces/app/ui/component/DsDropdown.kt b/Android/app/src/main/java/com/droidspaces/app/ui/component/DsDropdown.kt index 74adf9b6..a8437429 100644 --- a/Android/app/src/main/java/com/droidspaces/app/ui/component/DsDropdown.kt +++ b/Android/app/src/main/java/com/droidspaces/app/ui/component/DsDropdown.kt @@ -1,5 +1,7 @@ package com.droidspaces.app.ui.component +import androidx.compose.foundation.background +import androidx.compose.foundation.border import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.size import androidx.compose.foundation.shape.RoundedCornerShape @@ -8,6 +10,7 @@ import androidx.compose.material.icons.filled.Check import androidx.compose.material3.* import androidx.compose.runtime.* import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.text.font.FontWeight @@ -30,7 +33,7 @@ fun DsDropdown( var expanded by remember { mutableStateOf(false) } val focusManager = LocalFocusManager.current - val fieldShape = RoundedCornerShape(16.dp) + val fieldShape = RoundedCornerShape(20.dp) val fieldColors = OutlinedTextFieldDefaults.colors( unfocusedBorderColor = MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.5f), focusedBorderColor = MaterialTheme.colorScheme.primary.copy(alpha = 0.8f), @@ -68,7 +71,15 @@ fun DsDropdown( onDismissRequest = { expanded = false focusManager.clearFocus() - } + }, + modifier = Modifier + .clip(RoundedCornerShape(20.dp)) + .background(MaterialTheme.colorScheme.surfaceContainerHigh) + .border( + width = 1.dp, + color = MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.5f), + shape = RoundedCornerShape(20.dp) + ) ) { options.forEach { option -> DropdownMenuItem( From 6b66b7b1806f9e1e68a04488369929b9a3b66601 Mon Sep 17 00:00:00 2001 From: VizXtreme Date: Tue, 14 Jul 2026 19:10:42 +0000 Subject: [PATCH 02/19] ci: Add test builds vizx workflow --- .github/workflows/ci_test.yml | 217 ++++++++++++++++++++++++++++++++++ 1 file changed, 217 insertions(+) create mode 100644 .github/workflows/ci_test.yml diff --git a/.github/workflows/ci_test.yml b/.github/workflows/ci_test.yml new file mode 100644 index 00000000..11968c9e --- /dev/null +++ b/.github/workflows/ci_test.yml @@ -0,0 +1,217 @@ +name: test builds vizx + +on: + push: + branches: [ "main", "master" ] + pull_request: + branches: [ "main", "master" ] + workflow_dispatch: + inputs: + create_release: + description: 'Create an Official GitHub Release?' + required: true + type: boolean + default: false + tag_name: + description: 'Tag name (Only used if Release is checked)' + required: false + default: 'test' + +jobs: + build: + name: Build Backend & Android App + runs-on: ubuntu-latest + env: + HAS_TELEGRAM: ${{ secrets.API_ID != '' && secrets.API_HASH != '' }} + steps: + - uses: actions/checkout@v4 + + - name: Set up JDK 17 + uses: actions/setup-java@v4 + with: + java-version: '17' + distribution: 'temurin' + cache: gradle + + - name: Cache Toolchains + id: cache-toolchains + uses: actions/cache@v4 + with: + path: ~/toolchains + key: ${{ runner.os }}-toolchains-25843896720 + + - name: Download Toolchains + if: steps.cache-toolchains.outputs.cache-hit != 'true' + run: | + mkdir -p $HOME/toolchains + cd $HOME/toolchains + BASE_URL="https://github.com/ravindu644/Droidspaces-OSS/releases/download/compilers-25843896720" + + echo "[*] Downloading toolchains in parallel..." + wget -q $BASE_URL/aarch64-linux-musl-cross.tar.zst & + wget -q $BASE_URL/arm-linux-musleabihf-cross.tar.zst & + wget -q $BASE_URL/i686-linux-musl-cross.tar.zst & + wget -q $BASE_URL/x86_64-linux-musl-cross.tar.zst & + wget -q $BASE_URL/riscv64-linux-musl-cross.tar.zst & + wait + + echo "[*] Extracting toolchains in parallel..." + for f in *.tar.zst; do + tar -xf "$f" & + done + wait + + rm -f *.tar.zst + echo "[+] Toolchains ready." + + - name: List Toolchains (Debug) + run: | + find $HOME/toolchains -maxdepth 3 + + - name: Build All Tarball, Debian Packages & Sync to Android + run: | + make all-tarball + scripts/mkdeb.sh + + - name: Decode Keystore + env: + RELEASE_KEYSTORE: ${{ secrets.RELEASE_KEYSTORE }} + if: "${{ env.RELEASE_KEYSTORE != '' }}" + run: echo "${{ env.RELEASE_KEYSTORE }}" | base64 -d > droidspaces.keystore + + - name: Grant execute permission for gradlew + run: chmod +x Android/gradlew + + - name: Generate Contributors + continue-on-error: true + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + pip install -q requests + python3 scripts/generate_contributors.py + + - name: Build Android App with Gradle + env: + KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }} + KEY_ALIAS: ${{ secrets.KEY_ALIAS }} + KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }} + run: | + cd Android + ./gradlew assembleRelease \ + -PKEYSTORE_PASSWORD="${{ secrets.KEYSTORE_PASSWORD }}" \ + -PKEY_ALIAS="${{ secrets.KEY_ALIAS }}" \ + -PKEY_PASSWORD="${{ secrets.KEY_PASSWORD }}" + + - name: Stage & Rename Artifacts + run: | + TAG="${{ github.event.inputs.tag_name || 'CI' }}" + COMMIT_HASH=$(git log -1 --pretty=%h) + APK_NAME="Droidspaces-universal-${TAG}-${COMMIT_HASH}.apk" + TAR_NAME=$(ls droidspaces-v*-*.tar.gz) + mkdir -p dist + mv Android/app/build/outputs/apk/release/app-release.apk dist/${APK_NAME} + mv ${TAR_NAME} dist/ + mv droidspaces_*.deb dist/ + echo "APK_FILE=dist/${APK_NAME}" >> $GITHUB_ENV + echo "TAR_FILE=dist/${TAR_NAME}" >> $GITHUB_ENV + + - name: Generate Telegram Message + if: github.event_name != 'pull_request' + run: | + EVENT_TYPE="${{ github.event_name == 'workflow_dispatch' && github.event.inputs.create_release == 'true' && 'Official Release' || 'Git Push' }}" + COMMIT_MSG=$(git log -1 --pretty=format:%s) + { + echo "TELEGRAM_MESSAGE<> "$GITHUB_ENV" + + - name: Upload Final Artifacts (APK, Tarball & Debian Packages) + uses: actions/upload-artifact@v4 + with: + name: droidspaces-artifacts + path: dist/ + + - name: Send Telegram Notification + if: | + github.event_name != 'pull_request' && + env.HAS_TELEGRAM == 'true' + uses: xz-dev/TelegramFileUploader@v1 + with: + to-who: ${{ secrets.TELEGRAM_TO }} + message: ${{ env.TELEGRAM_MESSAGE }} + files: | + ${{ env.APK_FILE }} + ${{ env.TAR_FILE }} + env: + API_ID: ${{ secrets.API_ID }} + API_HASH: ${{ secrets.API_HASH }} + BOT_TOKEN: ${{ secrets.TELEGRAM_TOKEN }} + + release: + name: Create GitHub Release + needs: [build] + if: | + github.event_name == 'workflow_dispatch' && + github.event.inputs.create_release == 'true' && + github.event.inputs.tag_name != '' && + github.event.inputs.tag_name != 'test' + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Download Artifacts + uses: actions/download-artifact@v4 + with: + path: release-assets + merge-multiple: true + + - name: Generate Changelog + id: changelog + run: | + PREV_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "") + echo "Previous tag: $PREV_TAG" + + if [ -z "$PREV_TAG" ]; then + CHANGELOG=$(git log --oneline --pretty=format:"* %s (%h)") + else + CHANGELOG=$(git log ${PREV_TAG}..HEAD --oneline --pretty=format:"* %s (%h)") + fi + + { + echo "notes<> "$GITHUB_OUTPUT" + + - name: Create Release + uses: softprops/action-gh-release@v2 + with: + tag_name: ${{ github.event.inputs.tag_name }} + name: Droidspaces ${{ github.event.inputs.tag_name || 'Development Build' }} + target_commitish: ${{ github.sha }} + body: | + ## What's Changed + ${{ steps.changelog.outputs.notes }} + + --- + **Automated Release by Droidspaces CI** + files: | + release-assets/*.apk + release-assets/*.tar.gz + release-assets/*.deb From c8f4c7ff8fdaf68dad533694e3a35fe1a2c19b32 Mon Sep 17 00:00:00 2001 From: VizXtreme Date: Tue, 14 Jul 2026 19:20:08 +0000 Subject: [PATCH 03/19] ui: Refactor components for localization, standard borders, and double-toggle fixes --- .../app/ui/component/AccentColorPicker.kt | 4 +++- .../app/ui/component/DsDropdown.kt | 4 ++-- .../droidspaces/app/ui/component/HelpCard.kt | 22 +++++-------------- .../app/ui/component/SettingsRowCard.kt | 2 +- .../app/ui/component/SwitchItem.kt | 2 +- .../app/ui/component/ToggleCard.kt | 4 ++-- Android/app/src/main/res/values/strings.xml | 1 + 7 files changed, 15 insertions(+), 24 deletions(-) diff --git a/Android/app/src/main/java/com/droidspaces/app/ui/component/AccentColorPicker.kt b/Android/app/src/main/java/com/droidspaces/app/ui/component/AccentColorPicker.kt index 62e90968..1868fbda 100644 --- a/Android/app/src/main/java/com/droidspaces/app/ui/component/AccentColorPicker.kt +++ b/Android/app/src/main/java/com/droidspaces/app/ui/component/AccentColorPicker.kt @@ -9,8 +9,10 @@ import androidx.compose.material3.* import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp +import com.droidspaces.app.R import com.droidspaces.app.ui.theme.ThemePalette /** @@ -37,7 +39,7 @@ fun AccentColorPicker( }, headlineContent = { Text( - text = "Accent Color", + text = stringResource(R.string.accent_color), style = MaterialTheme.typography.titleMedium, fontWeight = FontWeight.SemiBold ) diff --git a/Android/app/src/main/java/com/droidspaces/app/ui/component/DsDropdown.kt b/Android/app/src/main/java/com/droidspaces/app/ui/component/DsDropdown.kt index a8437429..448c5257 100644 --- a/Android/app/src/main/java/com/droidspaces/app/ui/component/DsDropdown.kt +++ b/Android/app/src/main/java/com/droidspaces/app/ui/component/DsDropdown.kt @@ -35,7 +35,7 @@ fun DsDropdown( val fieldShape = RoundedCornerShape(20.dp) val fieldColors = OutlinedTextFieldDefaults.colors( - unfocusedBorderColor = MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.5f), + unfocusedBorderColor = MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.35f), focusedBorderColor = MaterialTheme.colorScheme.primary.copy(alpha = 0.8f), unfocusedContainerColor = MaterialTheme.colorScheme.surfaceContainerLow, focusedContainerColor = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.5f) @@ -77,7 +77,7 @@ fun DsDropdown( .background(MaterialTheme.colorScheme.surfaceContainerHigh) .border( width = 1.dp, - color = MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.5f), + color = MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.35f), shape = RoundedCornerShape(20.dp) ) ) { diff --git a/Android/app/src/main/java/com/droidspaces/app/ui/component/HelpCard.kt b/Android/app/src/main/java/com/droidspaces/app/ui/component/HelpCard.kt index ac53ca4f..ebcbb466 100644 --- a/Android/app/src/main/java/com/droidspaces/app/ui/component/HelpCard.kt +++ b/Android/app/src/main/java/com/droidspaces/app/ui/component/HelpCard.kt @@ -2,14 +2,10 @@ package com.droidspaces.app.ui.component import android.content.Intent import android.net.Uri -import androidx.compose.foundation.clickable -import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.* import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.ripple.rememberRipple import androidx.compose.material3.* import androidx.compose.runtime.Composable -import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip @@ -26,20 +22,12 @@ fun HelpCard( val url = context.getString(R.string.help_card_url) val cardShape = RoundedCornerShape(20.dp) - val interactionSource = remember { MutableInteractionSource() } - Surface( - modifier = modifier - .fillMaxWidth() - .clip(cardShape) - .clickable( - interactionSource = interactionSource, - indication = rememberRipple(bounded = true), - onClick = { - val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url)) - context.startActivity(intent) - } - ), + onClick = { + val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url)) + context.startActivity(intent) + }, + modifier = modifier.fillMaxWidth(), shape = cardShape, color = MaterialTheme.colorScheme.surfaceContainer, border = androidx.compose.foundation.BorderStroke(1.dp, MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.35f)) diff --git a/Android/app/src/main/java/com/droidspaces/app/ui/component/SettingsRowCard.kt b/Android/app/src/main/java/com/droidspaces/app/ui/component/SettingsRowCard.kt index 2eaaeb65..432ebc68 100644 --- a/Android/app/src/main/java/com/droidspaces/app/ui/component/SettingsRowCard.kt +++ b/Android/app/src/main/java/com/droidspaces/app/ui/component/SettingsRowCard.kt @@ -33,7 +33,7 @@ fun SettingsRowCard( enabled = enabled, shape = RoundedCornerShape(20.dp), color = MaterialTheme.colorScheme.surfaceContainerHigh, - border = androidx.compose.foundation.BorderStroke(1.dp, MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.5f)) + border = androidx.compose.foundation.BorderStroke(1.dp, MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.35f)) ) { Row( modifier = Modifier diff --git a/Android/app/src/main/java/com/droidspaces/app/ui/component/SwitchItem.kt b/Android/app/src/main/java/com/droidspaces/app/ui/component/SwitchItem.kt index b94134ff..3e4a97e0 100644 --- a/Android/app/src/main/java/com/droidspaces/app/ui/component/SwitchItem.kt +++ b/Android/app/src/main/java/com/droidspaces/app/ui/component/SwitchItem.kt @@ -52,7 +52,7 @@ fun SwitchItem( Switch( checked = checked, enabled = enabled, - onCheckedChange = onCheckedChange, + onCheckedChange = null, interactionSource = interactionSource, colors = SwitchDefaults.colors( checkedThumbColor = MaterialTheme.colorScheme.onPrimary, diff --git a/Android/app/src/main/java/com/droidspaces/app/ui/component/ToggleCard.kt b/Android/app/src/main/java/com/droidspaces/app/ui/component/ToggleCard.kt index 8ba8a3c6..d18a11e6 100644 --- a/Android/app/src/main/java/com/droidspaces/app/ui/component/ToggleCard.kt +++ b/Android/app/src/main/java/com/droidspaces/app/ui/component/ToggleCard.kt @@ -34,7 +34,7 @@ fun ToggleCard( enabled = enabled, shape = RoundedCornerShape(20.dp), color = MaterialTheme.colorScheme.surfaceContainerHigh, - border = androidx.compose.foundation.BorderStroke(1.dp, MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.5f)) + border = androidx.compose.foundation.BorderStroke(1.dp, MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.35f)) ) { Row( modifier = Modifier @@ -81,7 +81,7 @@ fun ToggleCard( } Switch( checked = checked, - onCheckedChange = onCheckedChange, + onCheckedChange = null, enabled = enabled, colors = SwitchDefaults.colors( checkedThumbColor = MaterialTheme.colorScheme.onPrimary, diff --git a/Android/app/src/main/res/values/strings.xml b/Android/app/src/main/res/values/strings.xml index bd68d63c..0adf29e9 100644 --- a/Android/app/src/main/res/values/strings.xml +++ b/Android/app/src/main/res/values/strings.xml @@ -86,6 +86,7 @@ Pure black background for OLED displays Apply System\'s Default Color Palette Use Android 12+ Monet theming (Material You) + Accent Color Daemon Mode Run Droidspaces as a persistent system-level daemon to bypass seccomp blocks from Magisk/APatch, GrapheneOS, etc. This enables high-privilege operations by fetching and running commands from userspace (Reboot required). Integrate Droidspaces to the system path From d2f1ea68fcab78d120bfe59df3b8c0949f878253 Mon Sep 17 00:00:00 2001 From: VizXtreme Date: Tue, 14 Jul 2026 19:21:51 +0000 Subject: [PATCH 04/19] ci: Add ui branch to trigger list in ci_test.yml --- .github/workflows/ci_test.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci_test.yml b/.github/workflows/ci_test.yml index 11968c9e..f46b74f3 100644 --- a/.github/workflows/ci_test.yml +++ b/.github/workflows/ci_test.yml @@ -2,9 +2,9 @@ name: test builds vizx on: push: - branches: [ "main", "master" ] + branches: [ "main", "master", "ui" ] pull_request: - branches: [ "main", "master" ] + branches: [ "main", "master", "ui" ] workflow_dispatch: inputs: create_release: From f17f29916aec765645adbdf518cae5e29df9673c Mon Sep 17 00:00:00 2001 From: VizXtreme Date: Tue, 14 Jul 2026 19:35:08 +0000 Subject: [PATCH 05/19] ui: Wrap dropdown popup in custom MaterialTheme to fix corner radius clipping --- .../app/ui/component/DsDropdown.kt | 74 ++++++++++--------- 1 file changed, 41 insertions(+), 33 deletions(-) diff --git a/Android/app/src/main/java/com/droidspaces/app/ui/component/DsDropdown.kt b/Android/app/src/main/java/com/droidspaces/app/ui/component/DsDropdown.kt index 448c5257..c21c97a3 100644 --- a/Android/app/src/main/java/com/droidspaces/app/ui/component/DsDropdown.kt +++ b/Android/app/src/main/java/com/droidspaces/app/ui/component/DsDropdown.kt @@ -66,40 +66,48 @@ fun DsDropdown( .menuAnchor() .fillMaxWidth() ) - ExposedDropdownMenu( - expanded = expanded, - onDismissRequest = { - expanded = false - focusManager.clearFocus() - }, - modifier = Modifier - .clip(RoundedCornerShape(20.dp)) - .background(MaterialTheme.colorScheme.surfaceContainerHigh) - .border( - width = 1.dp, - color = MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.35f), - shape = RoundedCornerShape(20.dp) - ) + MaterialTheme( + colorScheme = MaterialTheme.colorScheme.copy( + surface = MaterialTheme.colorScheme.surfaceContainerHigh, + surfaceContainer = MaterialTheme.colorScheme.surfaceContainerHigh + ), + shapes = MaterialTheme.shapes.copy( + extraSmall = RoundedCornerShape(20.dp) + ) ) { - options.forEach { option -> - DropdownMenuItem( - text = { Text(displayName(option), fontWeight = FontWeight.Medium) }, - onClick = { - onSelect(option) - expanded = false - focusManager.clearFocus() - }, - leadingIcon = if (option == selected) { - { - Icon( - Icons.Default.Check, - contentDescription = null, - modifier = Modifier.size(18.dp), - tint = MaterialTheme.colorScheme.primary - ) - } - } else null - ) + ExposedDropdownMenu( + expanded = expanded, + onDismissRequest = { + expanded = false + focusManager.clearFocus() + }, + modifier = Modifier + .border( + width = 1.dp, + color = MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.35f), + shape = RoundedCornerShape(20.dp) + ) + ) { + options.forEach { option -> + DropdownMenuItem( + text = { Text(displayName(option), fontWeight = FontWeight.Medium) }, + onClick = { + onSelect(option) + expanded = false + focusManager.clearFocus() + }, + leadingIcon = if (option == selected) { + { + Icon( + Icons.Default.Check, + contentDescription = null, + modifier = Modifier.size(18.dp), + tint = MaterialTheme.colorScheme.primary + ) + } + } else null + ) + } } } } From c0f42f1bb62155acefd8179419493ae7429ad062 Mon Sep 17 00:00:00 2001 From: VizXtreme Date: Tue, 14 Jul 2026 19:39:18 +0000 Subject: [PATCH 06/19] ci: Optimize ci_test.yml for faster builds --- .github/workflows/ci_test.yml | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/.github/workflows/ci_test.yml b/.github/workflows/ci_test.yml index f46b74f3..109264b1 100644 --- a/.github/workflows/ci_test.yml +++ b/.github/workflows/ci_test.yml @@ -23,6 +23,7 @@ jobs: runs-on: ubuntu-latest env: HAS_TELEGRAM: ${{ secrets.API_ID != '' && secrets.API_HASH != '' }} + GRADLE_OPTS: "-Dorg.gradle.daemon=false -Dorg.gradle.workers.max=4" steps: - uses: actions/checkout@v4 @@ -64,23 +65,20 @@ jobs: rm -f *.tar.zst echo "[+] Toolchains ready." - - name: List Toolchains (Debug) - run: | - find $HOME/toolchains -maxdepth 3 - - name: Build All Tarball, Debian Packages & Sync to Android run: | make all-tarball scripts/mkdeb.sh - - name: Decode Keystore + - name: Prepare Android Build env: RELEASE_KEYSTORE: ${{ secrets.RELEASE_KEYSTORE }} - if: "${{ env.RELEASE_KEYSTORE != '' }}" - run: echo "${{ env.RELEASE_KEYSTORE }}" | base64 -d > droidspaces.keystore - - - name: Grant execute permission for gradlew - run: chmod +x Android/gradlew + run: | + # Decode keystore if available + if [ -n "$RELEASE_KEYSTORE" ]; then + echo "$RELEASE_KEYSTORE" | base64 -d > droidspaces.keystore + fi + chmod +x Android/gradlew - name: Generate Contributors continue-on-error: true @@ -97,7 +95,7 @@ jobs: KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }} run: | cd Android - ./gradlew assembleRelease \ + ./gradlew assembleRelease --no-daemon --build-cache \ -PKEYSTORE_PASSWORD="${{ secrets.KEYSTORE_PASSWORD }}" \ -PKEY_ALIAS="${{ secrets.KEY_ALIAS }}" \ -PKEY_PASSWORD="${{ secrets.KEY_PASSWORD }}" From 83ba7a1f8571943463a83a80457880c784e45dc2 Mon Sep 17 00:00:00 2001 From: VizXtreme Date: Wed, 15 Jul 2026 03:26:13 +0000 Subject: [PATCH 07/19] ui: Fix dropdown menu not respecting amoled black mode --- .../main/java/com/droidspaces/app/ui/component/DsDropdown.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Android/app/src/main/java/com/droidspaces/app/ui/component/DsDropdown.kt b/Android/app/src/main/java/com/droidspaces/app/ui/component/DsDropdown.kt index c21c97a3..c7a89933 100644 --- a/Android/app/src/main/java/com/droidspaces/app/ui/component/DsDropdown.kt +++ b/Android/app/src/main/java/com/droidspaces/app/ui/component/DsDropdown.kt @@ -69,7 +69,8 @@ fun DsDropdown( MaterialTheme( colorScheme = MaterialTheme.colorScheme.copy( surface = MaterialTheme.colorScheme.surfaceContainerHigh, - surfaceContainer = MaterialTheme.colorScheme.surfaceContainerHigh + surfaceContainer = MaterialTheme.colorScheme.surfaceContainerHigh, + surfaceTint = Color.Transparent ), shapes = MaterialTheme.shapes.copy( extraSmall = RoundedCornerShape(20.dp) From 703f8792ec1c3de5ff8f9227595aa66f68c1fdf6 Mon Sep 17 00:00:00 2001 From: VizXtreme Date: Wed, 15 Jul 2026 03:33:20 +0000 Subject: [PATCH 08/19] fix: Add missing Color import in DsDropdown --- .../src/main/java/com/droidspaces/app/ui/component/DsDropdown.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/Android/app/src/main/java/com/droidspaces/app/ui/component/DsDropdown.kt b/Android/app/src/main/java/com/droidspaces/app/ui/component/DsDropdown.kt index c7a89933..84f00b73 100644 --- a/Android/app/src/main/java/com/droidspaces/app/ui/component/DsDropdown.kt +++ b/Android/app/src/main/java/com/droidspaces/app/ui/component/DsDropdown.kt @@ -11,6 +11,7 @@ import androidx.compose.material3.* import androidx.compose.runtime.* import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.text.font.FontWeight From ecb251fc3aa2576ca96a9386c0bd25311de91b13 Mon Sep 17 00:00:00 2001 From: VizXtreme Date: Wed, 15 Jul 2026 03:40:11 +0000 Subject: [PATCH 09/19] ui: Style 3-dot menus in init systems to match DropdownMenu --- .../droidspaces/app/ui/screen/OpenRCScreen.kt | 30 ++++++++++--- .../droidspaces/app/ui/screen/ProcdScreen.kt | 44 ++++++++++++++----- .../app/ui/screen/SystemdScreen.kt | 26 +++++++++-- 3 files changed, 80 insertions(+), 20 deletions(-) diff --git a/Android/app/src/main/java/com/droidspaces/app/ui/screen/OpenRCScreen.kt b/Android/app/src/main/java/com/droidspaces/app/ui/screen/OpenRCScreen.kt index aa856534..6b189cc3 100644 --- a/Android/app/src/main/java/com/droidspaces/app/ui/screen/OpenRCScreen.kt +++ b/Android/app/src/main/java/com/droidspaces/app/ui/screen/OpenRCScreen.kt @@ -401,12 +401,32 @@ private fun OpenRCServiceCard( ) { Box(contentAlignment = Alignment.Center) { Icon(Icons.Default.MoreVert, null, tint = MaterialTheme.colorScheme.onSurfaceVariant) } } - DropdownMenu(expanded = showMenu, onDismissRequest = { showMenu = false }) { - DropdownMenuItem( - text = { Text(context.getString(R.string.restart_service)) }, - leadingIcon = { Icon(Icons.Default.Refresh, null) }, - onClick = { showMenu = false; onAction(context.getString(R.string.restart_service)) { ContainerOpenRCManager.restartService(containerName, service.name) } } + MaterialTheme( + colorScheme = MaterialTheme.colorScheme.copy( + surface = MaterialTheme.colorScheme.surfaceContainerHigh, + surfaceContainer = MaterialTheme.colorScheme.surfaceContainerHigh, + surfaceTint = Color.Transparent + ), + shapes = MaterialTheme.shapes.copy( + extraSmall = RoundedCornerShape(20.dp) ) + ) { + DropdownMenu( + expanded = showMenu, + onDismissRequest = { showMenu = false }, + modifier = Modifier + .border( + width = 1.dp, + color = MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.35f), + shape = RoundedCornerShape(20.dp) + ) + ) { + DropdownMenuItem( + text = { Text(context.getString(R.string.restart_service)) }, + leadingIcon = { Icon(Icons.Default.Refresh, null) }, + onClick = { showMenu = false; onAction(context.getString(R.string.restart_service)) { ContainerOpenRCManager.restartService(containerName, service.name) } } + ) + } } } } diff --git a/Android/app/src/main/java/com/droidspaces/app/ui/screen/ProcdScreen.kt b/Android/app/src/main/java/com/droidspaces/app/ui/screen/ProcdScreen.kt index 2d5be973..f9f02720 100644 --- a/Android/app/src/main/java/com/droidspaces/app/ui/screen/ProcdScreen.kt +++ b/Android/app/src/main/java/com/droidspaces/app/ui/screen/ProcdScreen.kt @@ -404,19 +404,39 @@ private fun ProcdServiceCard( ) { Box(contentAlignment = Alignment.Center) { Icon(Icons.Default.MoreVert, null, tint = MaterialTheme.colorScheme.onSurfaceVariant) } } - DropdownMenu(expanded = showMenu, onDismissRequest = { showMenu = false }) { - DropdownMenuItem( - text = { Text(context.getString(R.string.restart_service)) }, - leadingIcon = { Icon(Icons.Default.Refresh, null) }, - onClick = { showMenu = false; onAction(context.getString(R.string.restart_service)) { ContainerProcdManager.restartService(containerName, service.name) } } - ) - DropdownMenuItem( - text = { Text(context.getString(R.string.reload_service)) }, - leadingIcon = { Icon(Icons.Default.Refresh, null) }, - onClick = { showMenu = false; onAction(context.getString(R.string.reload_service)) { ContainerProcdManager.reloadService(containerName, service.name) } } - ) + MaterialTheme( + colorScheme = MaterialTheme.colorScheme.copy( + surface = MaterialTheme.colorScheme.surfaceContainerHigh, + surfaceContainer = MaterialTheme.colorScheme.surfaceContainerHigh, + surfaceTint = Color.Transparent + ), + shapes = MaterialTheme.shapes.copy( + extraSmall = RoundedCornerShape(20.dp) + ) + ) { + DropdownMenu( + expanded = showMenu, + onDismissRequest = { showMenu = false }, + modifier = Modifier + .border( + width = 1.dp, + color = MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.35f), + shape = RoundedCornerShape(20.dp) + ) + ) { + DropdownMenuItem( + text = { Text(context.getString(R.string.restart_service)) }, + leadingIcon = { Icon(Icons.Default.Refresh, null) }, + onClick = { showMenu = false; onAction(context.getString(R.string.restart_service)) { ContainerProcdManager.restartService(containerName, service.name) } } + ) + DropdownMenuItem( + text = { Text(context.getString(R.string.reload_service)) }, + leadingIcon = { Icon(Icons.Default.Refresh, null) }, + onClick = { showMenu = false; onAction(context.getString(R.string.reload_service)) { ContainerProcdManager.reloadService(containerName, service.name) } } + ) + } + } } - } } } } diff --git a/Android/app/src/main/java/com/droidspaces/app/ui/screen/SystemdScreen.kt b/Android/app/src/main/java/com/droidspaces/app/ui/screen/SystemdScreen.kt index f37037f0..0edc64e0 100644 --- a/Android/app/src/main/java/com/droidspaces/app/ui/screen/SystemdScreen.kt +++ b/Android/app/src/main/java/com/droidspaces/app/ui/screen/SystemdScreen.kt @@ -377,9 +377,29 @@ private fun ServiceCard( } Box { Surface(onClick = { showMenu = true }, modifier = Modifier.size(48.dp), shape = RoundedCornerShape(16.dp), color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.05f), border = BorderStroke(1.dp, MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.2f))) { Box(contentAlignment = Alignment.Center) { Icon(Icons.Default.MoreVert, null, tint = MaterialTheme.colorScheme.onSurfaceVariant) } } - DropdownMenu(expanded = showMenu, onDismissRequest = { showMenu = false }) { - if (service.isRunning) { DropdownMenuItem(text = { Text(context.getString(R.string.restart_service)) }, leadingIcon = { Icon(Icons.Default.Refresh, null) }, onClick = { showMenu = false; onAction(context.getString(R.string.restart_service)) { ContainerSystemdManager.restartService(containerName, service.name) } }) } - DropdownMenuItem(text = { Text(context.getString(R.string.mask_service)) }, leadingIcon = { Icon(Icons.Default.Lock, null) }, onClick = { showMenu = false; onAction(context.getString(R.string.mask_service)) { ContainerSystemdManager.maskService(containerName, service.name) } }) + MaterialTheme( + colorScheme = MaterialTheme.colorScheme.copy( + surface = MaterialTheme.colorScheme.surfaceContainerHigh, + surfaceContainer = MaterialTheme.colorScheme.surfaceContainerHigh, + surfaceTint = Color.Transparent + ), + shapes = MaterialTheme.shapes.copy( + extraSmall = RoundedCornerShape(20.dp) + ) + ) { + DropdownMenu( + expanded = showMenu, + onDismissRequest = { showMenu = false }, + modifier = Modifier + .border( + width = 1.dp, + color = MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.35f), + shape = RoundedCornerShape(20.dp) + ) + ) { + if (service.isRunning) { DropdownMenuItem(text = { Text(context.getString(R.string.restart_service)) }, leadingIcon = { Icon(Icons.Default.Refresh, null) }, onClick = { showMenu = false; onAction(context.getString(R.string.restart_service)) { ContainerSystemdManager.restartService(containerName, service.name) } }) } + DropdownMenuItem(text = { Text(context.getString(R.string.mask_service)) }, leadingIcon = { Icon(Icons.Default.Lock, null) }, onClick = { showMenu = false; onAction(context.getString(R.string.mask_service)) { ContainerSystemdManager.maskService(containerName, service.name) } }) + } } } } From 48126810d75926970e92059f24c969c9c31d4c5f Mon Sep 17 00:00:00 2001 From: VizXtreme Date: Wed, 15 Jul 2026 03:59:40 +0000 Subject: [PATCH 10/19] ui: Fix PullToRefresh teleport animation on release --- .../app/ui/component/PullToRefreshWrapper.kt | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/Android/app/src/main/java/com/droidspaces/app/ui/component/PullToRefreshWrapper.kt b/Android/app/src/main/java/com/droidspaces/app/ui/component/PullToRefreshWrapper.kt index 9de5be5e..70d4c77b 100644 --- a/Android/app/src/main/java/com/droidspaces/app/ui/component/PullToRefreshWrapper.kt +++ b/Android/app/src/main/java/com/droidspaces/app/ui/component/PullToRefreshWrapper.kt @@ -8,8 +8,13 @@ import androidx.compose.material3.pulltorefresh.rememberPullToRefreshState import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.animation.core.LinearEasing +import androidx.compose.animation.core.animateFloatAsState +import androidx.compose.animation.core.tween import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.input.nestedscroll.nestedScroll +import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.unit.dp import kotlinx.coroutines.delay /** @@ -34,6 +39,15 @@ fun PullToRefreshWrapper( content: @Composable () -> Unit ) { val pullToRefreshState = rememberPullToRefreshState() + val density = LocalDensity.current + + // Smooth out the progress value to prevent the indicator from teleporting when released + val smoothedProgress by animateFloatAsState( + targetValue = pullToRefreshState.progress, + animationSpec = tween(durationMillis = 250, easing = LinearEasing), + label = "SmoothProgress" + ) + val thresholdPx = with(density) { 80.dp.toPx() } // Handle pull-to-refresh with minimum visible spin time LaunchedEffect(pullToRefreshState.isRefreshing) { @@ -69,6 +83,8 @@ fun PullToRefreshWrapper( .graphicsLayer { // Enable hardware layer for smooth 60fps animation shadowElevation = 0f + // Counteract the teleporting jump by adding the smoothed difference + translationY = (smoothedProgress - pullToRefreshState.progress) * thresholdPx }, containerColor = MaterialTheme.colorScheme.primaryContainer, contentColor = MaterialTheme.colorScheme.primary From 5526d4d1503f858e9b821a488aa230c94e147629 Mon Sep 17 00:00:00 2001 From: VizXtreme Date: Wed, 15 Jul 2026 04:07:55 +0000 Subject: [PATCH 11/19] ui: Fix corner radius mismatch in ContainerCard unified control pill --- .../main/java/com/droidspaces/app/ui/component/ContainerCard.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Android/app/src/main/java/com/droidspaces/app/ui/component/ContainerCard.kt b/Android/app/src/main/java/com/droidspaces/app/ui/component/ContainerCard.kt index dab97359..a349363c 100644 --- a/Android/app/src/main/java/com/droidspaces/app/ui/component/ContainerCard.kt +++ b/Android/app/src/main/java/com/droidspaces/app/ui/component/ContainerCard.kt @@ -199,7 +199,7 @@ fun ContainerCard( .fillMaxWidth() .padding(horizontal = 4.dp), color = MaterialTheme.colorScheme.surfaceContainerHigh, // Depth for secondary actions - shape = RoundedCornerShape(12.dp), + shape = RoundedCornerShape(20.dp), border = BorderStroke(1.dp, MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.2f)) ) { Row(modifier = Modifier.fillMaxWidth().padding(4.dp), horizontalArrangement = Arrangement.spacedBy(4.dp)) { From b0d658217ee187ce1d6ecc52c7a0cbbf2fafe7ad Mon Sep 17 00:00:00 2001 From: VizXtreme Date: Wed, 15 Jul 2026 04:11:06 +0000 Subject: [PATCH 12/19] ui: Revert PullToRefresh animation fix --- .../app/ui/component/PullToRefreshWrapper.kt | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/Android/app/src/main/java/com/droidspaces/app/ui/component/PullToRefreshWrapper.kt b/Android/app/src/main/java/com/droidspaces/app/ui/component/PullToRefreshWrapper.kt index 70d4c77b..9de5be5e 100644 --- a/Android/app/src/main/java/com/droidspaces/app/ui/component/PullToRefreshWrapper.kt +++ b/Android/app/src/main/java/com/droidspaces/app/ui/component/PullToRefreshWrapper.kt @@ -8,13 +8,8 @@ import androidx.compose.material3.pulltorefresh.rememberPullToRefreshState import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.animation.core.LinearEasing -import androidx.compose.animation.core.animateFloatAsState -import androidx.compose.animation.core.tween import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.input.nestedscroll.nestedScroll -import androidx.compose.ui.platform.LocalDensity -import androidx.compose.ui.unit.dp import kotlinx.coroutines.delay /** @@ -39,15 +34,6 @@ fun PullToRefreshWrapper( content: @Composable () -> Unit ) { val pullToRefreshState = rememberPullToRefreshState() - val density = LocalDensity.current - - // Smooth out the progress value to prevent the indicator from teleporting when released - val smoothedProgress by animateFloatAsState( - targetValue = pullToRefreshState.progress, - animationSpec = tween(durationMillis = 250, easing = LinearEasing), - label = "SmoothProgress" - ) - val thresholdPx = with(density) { 80.dp.toPx() } // Handle pull-to-refresh with minimum visible spin time LaunchedEffect(pullToRefreshState.isRefreshing) { @@ -83,8 +69,6 @@ fun PullToRefreshWrapper( .graphicsLayer { // Enable hardware layer for smooth 60fps animation shadowElevation = 0f - // Counteract the teleporting jump by adding the smoothed difference - translationY = (smoothedProgress - pullToRefreshState.progress) * thresholdPx }, containerColor = MaterialTheme.colorScheme.primaryContainer, contentColor = MaterialTheme.colorScheme.primary From 3a2680cbafdf1934b350e1cc2b447e76b49f9f7b Mon Sep 17 00:00:00 2001 From: VizXtreme Date: Wed, 15 Jul 2026 04:27:37 +0000 Subject: [PATCH 13/19] ui: Revamp settings page with grouped cards and separators, reduce About Dialog button spacing --- .../app/ui/screen/SettingsScreen.kt | 86 ++++++++++++++----- 1 file changed, 65 insertions(+), 21 deletions(-) diff --git a/Android/app/src/main/java/com/droidspaces/app/ui/screen/SettingsScreen.kt b/Android/app/src/main/java/com/droidspaces/app/ui/screen/SettingsScreen.kt index fb78bce1..821ebcdb 100644 --- a/Android/app/src/main/java/com/droidspaces/app/ui/screen/SettingsScreen.kt +++ b/Android/app/src/main/java/com/droidspaces/app/ui/screen/SettingsScreen.kt @@ -163,13 +163,20 @@ fun SettingsScreen( // Backend Reinstallation Section Text( text = context.getString(R.string.backend_section), - style = MaterialTheme.typography.titleMedium, - fontWeight = FontWeight.SemiBold, - modifier = Modifier.padding(horizontal = 16.dp, vertical = 16.dp), + style = MaterialTheme.typography.titleSmall, + fontWeight = FontWeight.Bold, + modifier = Modifier.padding(start = 24.dp, bottom = 8.dp, top = 8.dp), color = MaterialTheme.colorScheme.primary ) - ListItem( + Surface( + modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp), + shape = RoundedCornerShape(24.dp), + color = MaterialTheme.colorScheme.surfaceContainerHigh, + border = BorderStroke(1.dp, MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.35f)) + ) { + Column { + ListItem( leadingContent = { Icon( imageVector = Icons.Default.Build, @@ -215,6 +222,8 @@ fun SettingsScreen( ) ) + HorizontalDivider(modifier = Modifier.padding(horizontal = 16.dp), color = MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.35f)) + // Daemon Mode Toggle SwitchItem( icon = Icons.Default.SettingsBackupRestore, @@ -227,6 +236,8 @@ fun SettingsScreen( } ) + HorizontalDivider(modifier = Modifier.padding(horizontal = 16.dp), color = MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.35f)) + val isBackendAvailable = appStateViewModel.isBackendAvailable SwitchItem( icon = Icons.Default.Link, @@ -246,6 +257,8 @@ fun SettingsScreen( } ) + HorizontalDivider(modifier = Modifier.padding(horizontal = 16.dp), color = MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.35f)) + // Auto Boot Priority - clickable to navigate to the boot-order screen ListItem( leadingContent = { @@ -273,23 +286,34 @@ fun SettingsScreen( modifier = Modifier.clickable { onNavigateToAutoBootPriority() } ) + HorizontalDivider(modifier = Modifier.padding(horizontal = 16.dp), color = MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.35f)) + // Requirements Card - clickable to navigate to requirements page RequirementsCard( onNavigateToRequirements = onNavigateToRequirements ) + } + } - HorizontalDivider(modifier = Modifier.padding(vertical = 8.dp)) + Spacer(modifier = Modifier.height(8.dp)) // Theme Section Text( text = context.getString(R.string.appearance_section), - style = MaterialTheme.typography.titleMedium, - fontWeight = FontWeight.SemiBold, - modifier = Modifier.padding(horizontal = 16.dp, vertical = 16.dp), + style = MaterialTheme.typography.titleSmall, + fontWeight = FontWeight.Bold, + modifier = Modifier.padding(start = 24.dp, bottom = 8.dp, top = 8.dp), color = MaterialTheme.colorScheme.primary ) - // Language Picker + Surface( + modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp), + shape = RoundedCornerShape(24.dp), + color = MaterialTheme.colorScheme.surfaceContainerHigh, + border = BorderStroke(1.dp, MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.35f)) + ) { + Column { + // Language Picker val currentLanguageDisplay = remember(currentAppLocale) { val currentLanguageCode = LocaleHelper.getCurrentLanguageCode() if (currentLanguageCode == "system") { @@ -324,6 +348,8 @@ fun SettingsScreen( } ) + HorizontalDivider(modifier = Modifier.padding(horizontal = 16.dp), color = MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.35f)) + // Follow System Theme SwitchItem( icon = Icons.Default.BrightnessAuto, @@ -337,6 +363,7 @@ fun SettingsScreen( // Dark Theme (only shown when not following system) if (!followSystemTheme) { + HorizontalDivider(modifier = Modifier.padding(horizontal = 16.dp), color = MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.35f)) SwitchItem( icon = Icons.Default.DarkMode, title = context.getString(R.string.dark_theme), @@ -350,6 +377,7 @@ fun SettingsScreen( // AMOLED Mode (shown when followSystemTheme is true OR manual darkTheme is true) if (followSystemTheme || darkTheme) { + HorizontalDivider(modifier = Modifier.padding(horizontal = 16.dp), color = MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.35f)) SwitchItem( icon = Icons.Default.RadioButtonUnchecked, title = context.getString(R.string.amoled_mode), @@ -365,6 +393,7 @@ fun SettingsScreen( // Use Dynamic Color (Monet theming) - Only show on Android 12+ if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) { + HorizontalDivider(modifier = Modifier.padding(horizontal = 16.dp), color = MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.35f)) SwitchItem( icon = Icons.Default.ColorLens, title = context.getString(R.string.dynamic_color), @@ -380,6 +409,7 @@ fun SettingsScreen( // Accent Color Picker - show when dynamic color is off, // or always show on devices below Android 12 (no dynamic color support) if (!useDynamicColor || android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.S) { + HorizontalDivider(modifier = Modifier.padding(horizontal = 16.dp), color = MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.35f)) AccentColorPicker( selectedPalette = themeState.themePalette, isDarkTheme = darkTheme, @@ -388,11 +418,19 @@ fun SettingsScreen( } ) } + } + } - HorizontalDivider(modifier = Modifier.padding(vertical = 8.dp)) + Spacer(modifier = Modifier.height(8.dp)) // Bug Report Section - ListItem( + Surface( + modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp), + shape = RoundedCornerShape(24.dp), + color = MaterialTheme.colorScheme.surfaceContainerHigh, + border = BorderStroke(1.dp, MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.35f)) + ) { + ListItem( leadingContent = { Icon( imageVector = Icons.Default.BugReport, @@ -436,20 +474,26 @@ fun SettingsScreen( Modifier } ) - ) + } - HorizontalDivider(modifier = Modifier.padding(vertical = 8.dp)) + Spacer(modifier = Modifier.height(8.dp)) // About Section Text( text = context.getString(R.string.about_section), - style = MaterialTheme.typography.titleMedium, - fontWeight = FontWeight.SemiBold, - modifier = Modifier.padding(horizontal = 16.dp, vertical = 16.dp), + style = MaterialTheme.typography.titleSmall, + fontWeight = FontWeight.Bold, + modifier = Modifier.padding(start = 24.dp, bottom = 8.dp, top = 8.dp), color = MaterialTheme.colorScheme.primary ) - ListItem( + Surface( + modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp), + shape = RoundedCornerShape(24.dp), + color = MaterialTheme.colorScheme.surfaceContainerHigh, + border = BorderStroke(1.dp, MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.35f)) + ) { + ListItem( leadingContent = { Icon( imageVector = Icons.Default.Info, @@ -469,9 +513,10 @@ fun SettingsScreen( modifier = Modifier.clickable { showAboutDialog = true } - ) + ) + } - Spacer(modifier = Modifier.height(16.dp)) + Spacer(modifier = Modifier.height(24.dp)) } } @@ -523,7 +568,7 @@ private fun AboutDialog(onDismiss: () -> Unit) { Column( modifier = Modifier .fillMaxSize() - .padding(24.dp) + .padding(top = 24.dp, start = 24.dp, end = 24.dp, bottom = 8.dp) ) { // Title Text( @@ -680,7 +725,6 @@ private fun AboutDialog(onDismiss: () -> Unit) { } // OK Button - Spacer(modifier = Modifier.height(8.dp)) TextButton( onClick = onDismiss, modifier = Modifier.align(Alignment.End) From eef595d350db591b548bf32d2563422e37f955ee Mon Sep 17 00:00:00 2001 From: VizXtreme Date: Wed, 15 Jul 2026 04:36:03 +0000 Subject: [PATCH 14/19] ui: Fix syntax error in SettingsScreen bug report card --- .../main/java/com/droidspaces/app/ui/screen/SettingsScreen.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/Android/app/src/main/java/com/droidspaces/app/ui/screen/SettingsScreen.kt b/Android/app/src/main/java/com/droidspaces/app/ui/screen/SettingsScreen.kt index 821ebcdb..132d47bb 100644 --- a/Android/app/src/main/java/com/droidspaces/app/ui/screen/SettingsScreen.kt +++ b/Android/app/src/main/java/com/droidspaces/app/ui/screen/SettingsScreen.kt @@ -474,6 +474,7 @@ fun SettingsScreen( Modifier } ) + ) } Spacer(modifier = Modifier.height(8.dp)) From 9ca0bda3f1a0917962848e1b7535a6993dbf4866 Mon Sep 17 00:00:00 2001 From: VizXtreme Date: Wed, 15 Jul 2026 04:51:14 +0000 Subject: [PATCH 15/19] ui: Fix overlapping separators and match Settings card background with ContainerCard --- .../app/ui/component/SwitchItem.kt | 1 + .../app/ui/screen/SettingsScreen.kt | 38 +++++++++---------- 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/Android/app/src/main/java/com/droidspaces/app/ui/component/SwitchItem.kt b/Android/app/src/main/java/com/droidspaces/app/ui/component/SwitchItem.kt index 3e4a97e0..f0948293 100644 --- a/Android/app/src/main/java/com/droidspaces/app/ui/component/SwitchItem.kt +++ b/Android/app/src/main/java/com/droidspaces/app/ui/component/SwitchItem.kt @@ -24,6 +24,7 @@ fun SwitchItem( val stateAlpha = Modifier.alpha(if (enabled) 1f else 0.5f) ListItem( + colors = ListItemDefaults.colors(containerColor = androidx.compose.ui.graphics.Color.Transparent), modifier = Modifier .toggleable( value = checked, diff --git a/Android/app/src/main/java/com/droidspaces/app/ui/screen/SettingsScreen.kt b/Android/app/src/main/java/com/droidspaces/app/ui/screen/SettingsScreen.kt index 132d47bb..50082e8c 100644 --- a/Android/app/src/main/java/com/droidspaces/app/ui/screen/SettingsScreen.kt +++ b/Android/app/src/main/java/com/droidspaces/app/ui/screen/SettingsScreen.kt @@ -172,11 +172,11 @@ fun SettingsScreen( Surface( modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp), shape = RoundedCornerShape(24.dp), - color = MaterialTheme.colorScheme.surfaceContainerHigh, + color = if (darkTheme) MaterialTheme.colorScheme.surfaceContainerHigh else MaterialTheme.colorScheme.surfaceContainer, border = BorderStroke(1.dp, MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.35f)) ) { Column { - ListItem( + ListItem(colors = ListItemDefaults.colors(containerColor = Color.Transparent), leadingContent = { Icon( imageVector = Icons.Default.Build, @@ -222,7 +222,7 @@ fun SettingsScreen( ) ) - HorizontalDivider(modifier = Modifier.padding(horizontal = 16.dp), color = MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.35f)) + HorizontalDivider(modifier = Modifier.padding(horizontal = 16.dp), color = MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.3f)) // Daemon Mode Toggle SwitchItem( @@ -236,7 +236,7 @@ fun SettingsScreen( } ) - HorizontalDivider(modifier = Modifier.padding(horizontal = 16.dp), color = MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.35f)) + HorizontalDivider(modifier = Modifier.padding(horizontal = 16.dp), color = MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.3f)) val isBackendAvailable = appStateViewModel.isBackendAvailable SwitchItem( @@ -257,10 +257,10 @@ fun SettingsScreen( } ) - HorizontalDivider(modifier = Modifier.padding(horizontal = 16.dp), color = MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.35f)) + HorizontalDivider(modifier = Modifier.padding(horizontal = 16.dp), color = MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.3f)) // Auto Boot Priority - clickable to navigate to the boot-order screen - ListItem( + ListItem(colors = ListItemDefaults.colors(containerColor = Color.Transparent), leadingContent = { Icon( imageVector = Icons.Default.LowPriority, @@ -286,7 +286,7 @@ fun SettingsScreen( modifier = Modifier.clickable { onNavigateToAutoBootPriority() } ) - HorizontalDivider(modifier = Modifier.padding(horizontal = 16.dp), color = MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.35f)) + HorizontalDivider(modifier = Modifier.padding(horizontal = 16.dp), color = MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.3f)) // Requirements Card - clickable to navigate to requirements page RequirementsCard( @@ -309,7 +309,7 @@ fun SettingsScreen( Surface( modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp), shape = RoundedCornerShape(24.dp), - color = MaterialTheme.colorScheme.surfaceContainerHigh, + color = if (darkTheme) MaterialTheme.colorScheme.surfaceContainerHigh else MaterialTheme.colorScheme.surfaceContainer, border = BorderStroke(1.dp, MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.35f)) ) { Column { @@ -326,7 +326,7 @@ fun SettingsScreen( } } - ListItem( + ListItem(colors = ListItemDefaults.colors(containerColor = Color.Transparent), leadingContent = { Icon( imageVector = Icons.Default.Translate, @@ -348,7 +348,7 @@ fun SettingsScreen( } ) - HorizontalDivider(modifier = Modifier.padding(horizontal = 16.dp), color = MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.35f)) + HorizontalDivider(modifier = Modifier.padding(horizontal = 16.dp), color = MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.3f)) // Follow System Theme SwitchItem( @@ -363,7 +363,7 @@ fun SettingsScreen( // Dark Theme (only shown when not following system) if (!followSystemTheme) { - HorizontalDivider(modifier = Modifier.padding(horizontal = 16.dp), color = MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.35f)) + HorizontalDivider(modifier = Modifier.padding(horizontal = 16.dp), color = MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.3f)) SwitchItem( icon = Icons.Default.DarkMode, title = context.getString(R.string.dark_theme), @@ -377,7 +377,7 @@ fun SettingsScreen( // AMOLED Mode (shown when followSystemTheme is true OR manual darkTheme is true) if (followSystemTheme || darkTheme) { - HorizontalDivider(modifier = Modifier.padding(horizontal = 16.dp), color = MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.35f)) + HorizontalDivider(modifier = Modifier.padding(horizontal = 16.dp), color = MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.3f)) SwitchItem( icon = Icons.Default.RadioButtonUnchecked, title = context.getString(R.string.amoled_mode), @@ -393,7 +393,7 @@ fun SettingsScreen( // Use Dynamic Color (Monet theming) - Only show on Android 12+ if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) { - HorizontalDivider(modifier = Modifier.padding(horizontal = 16.dp), color = MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.35f)) + HorizontalDivider(modifier = Modifier.padding(horizontal = 16.dp), color = MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.3f)) SwitchItem( icon = Icons.Default.ColorLens, title = context.getString(R.string.dynamic_color), @@ -409,7 +409,7 @@ fun SettingsScreen( // Accent Color Picker - show when dynamic color is off, // or always show on devices below Android 12 (no dynamic color support) if (!useDynamicColor || android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.S) { - HorizontalDivider(modifier = Modifier.padding(horizontal = 16.dp), color = MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.35f)) + HorizontalDivider(modifier = Modifier.padding(horizontal = 16.dp), color = MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.3f)) AccentColorPicker( selectedPalette = themeState.themePalette, isDarkTheme = darkTheme, @@ -427,10 +427,10 @@ fun SettingsScreen( Surface( modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp), shape = RoundedCornerShape(24.dp), - color = MaterialTheme.colorScheme.surfaceContainerHigh, + color = if (darkTheme) MaterialTheme.colorScheme.surfaceContainerHigh else MaterialTheme.colorScheme.surfaceContainer, border = BorderStroke(1.dp, MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.35f)) ) { - ListItem( + ListItem(colors = ListItemDefaults.colors(containerColor = Color.Transparent), leadingContent = { Icon( imageVector = Icons.Default.BugReport, @@ -491,10 +491,10 @@ fun SettingsScreen( Surface( modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp), shape = RoundedCornerShape(24.dp), - color = MaterialTheme.colorScheme.surfaceContainerHigh, + color = if (darkTheme) MaterialTheme.colorScheme.surfaceContainerHigh else MaterialTheme.colorScheme.surfaceContainer, border = BorderStroke(1.dp, MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.35f)) ) { - ListItem( + ListItem(colors = ListItemDefaults.colors(containerColor = Color.Transparent), leadingContent = { Icon( imageVector = Icons.Default.Info, @@ -801,7 +801,7 @@ private fun RequirementsCard( ) { val context = LocalContext.current - ListItem( + ListItem(colors = ListItemDefaults.colors(containerColor = Color.Transparent), leadingContent = { Icon( imageVector = Icons.Default.Code, From 55bb1a9e2c251bf85040b07d3080cb1628ec4dd9 Mon Sep 17 00:00:00 2001 From: VizXtreme Date: Wed, 15 Jul 2026 05:29:05 +0000 Subject: [PATCH 16/19] ui: Add Debugging header and wrap About dialog sections in grouped cards --- .../app/ui/screen/SettingsScreen.kt | 255 ++++++++++-------- Android/app/src/main/res/values/strings.xml | 1 + 2 files changed, 142 insertions(+), 114 deletions(-) diff --git a/Android/app/src/main/java/com/droidspaces/app/ui/screen/SettingsScreen.kt b/Android/app/src/main/java/com/droidspaces/app/ui/screen/SettingsScreen.kt index 50082e8c..786c7e75 100644 --- a/Android/app/src/main/java/com/droidspaces/app/ui/screen/SettingsScreen.kt +++ b/Android/app/src/main/java/com/droidspaces/app/ui/screen/SettingsScreen.kt @@ -423,9 +423,18 @@ fun SettingsScreen( Spacer(modifier = Modifier.height(8.dp)) - // Bug Report Section + // Debugging Section + Text( + text = context.getString(R.string.debugging_section), + style = MaterialTheme.typography.titleSmall, + fontWeight = FontWeight.Bold, + modifier = Modifier.padding(start = 24.dp, bottom = 8.dp, top = 8.dp), + color = MaterialTheme.colorScheme.primary + ) + Surface( modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp), + shape = RoundedCornerShape(24.dp), color = if (darkTheme) MaterialTheme.colorScheme.surfaceContainerHigh else MaterialTheme.colorScheme.surfaceContainer, border = BorderStroke(1.dp, MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.35f)) @@ -591,120 +600,126 @@ private fun AboutDialog(onDismiss: () -> Unit) { style = MaterialTheme.typography.bodyMedium, color = MaterialTheme.colorScheme.onSurfaceVariant ) - Spacer(modifier = Modifier.height(8.dp)) - HorizontalDivider() - Spacer(modifier = Modifier.height(4.dp)) Text( text = context.getString(R.string.developers), style = MaterialTheme.typography.titleSmall, fontWeight = FontWeight.SemiBold, color = MaterialTheme.colorScheme.primary ) - // Developer 1 - Row( - modifier = Modifier - .fillMaxWidth() - .clickable { - val intent = Intent(Intent.ACTION_VIEW, Uri.parse("https://github.com/ravindu644")) - context.startActivity(intent) - }, - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(8.dp) + Surface( + modifier = Modifier.fillMaxWidth(), + shape = RoundedCornerShape(24.dp), + color = MaterialTheme.colorScheme.surfaceContainerHigh, + border = BorderStroke(1.dp, MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.35f)) ) { - Icon( - imageVector = Icons.Default.Person, - contentDescription = null, - modifier = Modifier.size(20.dp), - tint = MaterialTheme.colorScheme.onSurfaceVariant - ) - Column(modifier = Modifier.weight(1f)) { - Text( - text = context.getString(R.string.developer_ravindu644), - style = MaterialTheme.typography.bodyMedium, - fontWeight = FontWeight.Medium - ) - Text( - text = context.getString(R.string.developer_ravindu644_role), - style = MaterialTheme.typography.bodySmall, - color = MaterialTheme.colorScheme.onSurfaceVariant - ) + Column { + // Developer 1 + Row( + modifier = Modifier + .fillMaxWidth() + .clickable { + val intent = Intent(Intent.ACTION_VIEW, Uri.parse("https://github.com/ravindu644")) + context.startActivity(intent) + } + .padding(horizontal = 16.dp, vertical = 12.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(12.dp) + ) { + Icon( + imageVector = Icons.Default.Person, + contentDescription = null, + modifier = Modifier.size(24.dp), + tint = MaterialTheme.colorScheme.onSurfaceVariant + ) + Column(modifier = Modifier.weight(1f)) { + Text( + text = context.getString(R.string.developer_ravindu644), + style = MaterialTheme.typography.bodyMedium, + fontWeight = FontWeight.Medium + ) + Text( + text = context.getString(R.string.developer_ravindu644_role), + style = MaterialTheme.typography.bodySmall, + color = MaterialTheme.colorScheme.onSurfaceVariant + ) + } + Icon( + imageVector = Icons.AutoMirrored.Filled.OpenInNew, + contentDescription = context.getString(R.string.github), + modifier = Modifier.size(18.dp), + tint = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.7f) + ) + } + + HorizontalDivider(modifier = Modifier.padding(horizontal = 16.dp), color = MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.3f)) + + // Telegram channel + Row( + modifier = Modifier + .fillMaxWidth() + .clickable { + val intent = Intent(Intent.ACTION_VIEW, Uri.parse("https://t.me/Droidspaces")) + context.startActivity(intent) + } + .padding(horizontal = 16.dp, vertical = 12.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(12.dp) + ) { + Icon( + painter = painterResource(id = R.drawable.ic_telegram), + contentDescription = null, + modifier = Modifier.size(24.dp), + tint = MaterialTheme.colorScheme.primary + ) + Text( + text = context.getString(R.string.telegram_channel), + style = MaterialTheme.typography.bodyMedium, + fontWeight = FontWeight.Medium, + modifier = Modifier.weight(1f) + ) + Icon( + imageVector = Icons.AutoMirrored.Filled.OpenInNew, + contentDescription = context.getString(R.string.telegram_channel), + modifier = Modifier.size(18.dp), + tint = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.7f) + ) + } + + HorizontalDivider(modifier = Modifier.padding(horizontal = 16.dp), color = MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.3f)) + + // Source Code row + Row( + modifier = Modifier + .fillMaxWidth() + .clickable { + val intent = Intent(Intent.ACTION_VIEW, Uri.parse("https://github.com/ravindu644/Droidspaces-OSS")) + context.startActivity(intent) + } + .padding(horizontal = 16.dp, vertical = 12.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(12.dp) + ) { + Icon( + imageVector = Icons.Default.Code, + contentDescription = null, + modifier = Modifier.size(24.dp), + tint = MaterialTheme.colorScheme.primary + ) + Text( + text = context.getString(R.string.source_code), + style = MaterialTheme.typography.bodyMedium, + fontWeight = FontWeight.Medium, + modifier = Modifier.weight(1f) + ) + Icon( + imageVector = Icons.AutoMirrored.Filled.OpenInNew, + contentDescription = context.getString(R.string.source_code), + modifier = Modifier.size(18.dp), + tint = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.7f) + ) + } } - Icon( - imageVector = Icons.AutoMirrored.Filled.OpenInNew, - contentDescription = context.getString(R.string.github), - modifier = Modifier.size(18.dp), - tint = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.7f) - ) } - Spacer(modifier = Modifier.height(4.dp)) - HorizontalDivider() - Spacer(modifier = Modifier.height(4.dp)) - // Telegram channel - Row( - modifier = Modifier - .fillMaxWidth() - .clickable { - val intent = Intent(Intent.ACTION_VIEW, Uri.parse("https://t.me/Droidspaces")) - context.startActivity(intent) - }, - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(12.dp) - ) { - Icon( - painter = painterResource(id = R.drawable.ic_telegram), - contentDescription = null, - modifier = Modifier.size(24.dp), - tint = MaterialTheme.colorScheme.primary - ) - Text( - text = context.getString(R.string.telegram_channel), - style = MaterialTheme.typography.bodyMedium, - fontWeight = FontWeight.Medium, - modifier = Modifier.weight(1f) - ) - Icon( - imageVector = Icons.AutoMirrored.Filled.OpenInNew, - contentDescription = context.getString(R.string.telegram_channel), - modifier = Modifier.size(18.dp), - tint = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.7f) - ) - } - Spacer(modifier = Modifier.height(4.dp)) - HorizontalDivider() - Spacer(modifier = Modifier.height(4.dp)) - // Source Code row - Row( - modifier = Modifier - .fillMaxWidth() - .clickable { - val intent = Intent(Intent.ACTION_VIEW, Uri.parse("https://github.com/ravindu644/Droidspaces-OSS")) - context.startActivity(intent) - }, - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(12.dp) - ) { - Icon( - imageVector = Icons.Default.Code, - contentDescription = null, - modifier = Modifier.size(24.dp), - tint = MaterialTheme.colorScheme.primary - ) - Text( - text = context.getString(R.string.source_code), - style = MaterialTheme.typography.bodyMedium, - fontWeight = FontWeight.Medium, - modifier = Modifier.weight(1f) - ) - Icon( - imageVector = Icons.AutoMirrored.Filled.OpenInNew, - contentDescription = context.getString(R.string.source_code), - modifier = Modifier.size(18.dp), - tint = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.7f) - ) - } - Spacer(modifier = Modifier.height(4.dp)) - HorizontalDivider() - Spacer(modifier = Modifier.height(4.dp)) // Contributors Text( @@ -714,14 +729,26 @@ private fun AboutDialog(onDismiss: () -> Unit) { color = MaterialTheme.colorScheme.primary ) val contributors = remember { ContributorManager.load(context) } - contributors.forEach { contributor -> - ContributorItem( - contributor = contributor, - onClick = { - val intent = Intent(Intent.ACTION_VIEW, Uri.parse(contributor.githubUrl)) - context.startActivity(intent) + Surface( + modifier = Modifier.fillMaxWidth(), + shape = RoundedCornerShape(24.dp), + color = MaterialTheme.colorScheme.surfaceContainerHigh, + border = BorderStroke(1.dp, MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.35f)) + ) { + Column { + contributors.forEachIndexed { index, contributor -> + ContributorItem( + contributor = contributor, + onClick = { + val intent = Intent(Intent.ACTION_VIEW, Uri.parse(contributor.githubUrl)) + context.startActivity(intent) + } + ) + if (index < contributors.size - 1) { + HorizontalDivider(modifier = Modifier.padding(horizontal = 16.dp), color = MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.3f)) + } } - ) + } } } @@ -747,7 +774,7 @@ private fun ContributorItem(contributor: Contributor, onClick: () -> Unit) { }.getOrNull() else null } Row( - modifier = Modifier.fillMaxWidth().clickable(onClick = onClick), + modifier = Modifier.fillMaxWidth().clickable(onClick = onClick).padding(horizontal = 16.dp, vertical = 12.dp), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(8.dp) ) { diff --git a/Android/app/src/main/res/values/strings.xml b/Android/app/src/main/res/values/strings.xml index 0adf29e9..c9f28bc5 100644 --- a/Android/app/src/main/res/values/strings.xml +++ b/Android/app/src/main/res/values/strings.xml @@ -593,4 +593,5 @@ URL cannot be empty URL must start with https:// No custom repositories subscribed yet. + Debugging From 9c9187907a3b507aa4ed1c87d70e246ed8a88ee4 Mon Sep 17 00:00:00 2001 From: VizXtreme Date: Wed, 15 Jul 2026 06:00:04 +0000 Subject: [PATCH 17/19] ui: Update Dropdown menu background to correctly adapt to light, dark, and AMOLED modes --- .../java/com/droidspaces/app/ui/component/DsDropdown.kt | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Android/app/src/main/java/com/droidspaces/app/ui/component/DsDropdown.kt b/Android/app/src/main/java/com/droidspaces/app/ui/component/DsDropdown.kt index 84f00b73..bde05567 100644 --- a/Android/app/src/main/java/com/droidspaces/app/ui/component/DsDropdown.kt +++ b/Android/app/src/main/java/com/droidspaces/app/ui/component/DsDropdown.kt @@ -12,6 +12,7 @@ import androidx.compose.runtime.* import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.luminance import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.text.font.FontWeight @@ -67,10 +68,13 @@ fun DsDropdown( .menuAnchor() .fillMaxWidth() ) + val isDark = MaterialTheme.colorScheme.background.luminance() < 0.5f + val dropdownColor = if (isDark) MaterialTheme.colorScheme.surfaceContainerHigh else MaterialTheme.colorScheme.surfaceContainer + MaterialTheme( colorScheme = MaterialTheme.colorScheme.copy( - surface = MaterialTheme.colorScheme.surfaceContainerHigh, - surfaceContainer = MaterialTheme.colorScheme.surfaceContainerHigh, + surface = dropdownColor, + surfaceContainer = dropdownColor, surfaceTint = Color.Transparent ), shapes = MaterialTheme.shapes.copy( From 9cb8cd270b479be6ea25ff0740fab922c13f3378 Mon Sep 17 00:00:00 2001 From: VizXtreme Date: Wed, 15 Jul 2026 06:04:00 +0000 Subject: [PATCH 18/19] ui: Update Init system dropdown menus to properly adapt to Light/Dark/AMOLED backgrounds --- .../java/com/droidspaces/app/ui/screen/OpenRCScreen.kt | 7 +++++-- .../main/java/com/droidspaces/app/ui/screen/ProcdScreen.kt | 7 +++++-- .../java/com/droidspaces/app/ui/screen/SystemdScreen.kt | 7 +++++-- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/Android/app/src/main/java/com/droidspaces/app/ui/screen/OpenRCScreen.kt b/Android/app/src/main/java/com/droidspaces/app/ui/screen/OpenRCScreen.kt index 6b189cc3..248eaacf 100644 --- a/Android/app/src/main/java/com/droidspaces/app/ui/screen/OpenRCScreen.kt +++ b/Android/app/src/main/java/com/droidspaces/app/ui/screen/OpenRCScreen.kt @@ -18,6 +18,7 @@ import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.luminance import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.text.font.Font import androidx.compose.ui.text.font.FontFamily @@ -401,10 +402,12 @@ private fun OpenRCServiceCard( ) { Box(contentAlignment = Alignment.Center) { Icon(Icons.Default.MoreVert, null, tint = MaterialTheme.colorScheme.onSurfaceVariant) } } + val isDark = MaterialTheme.colorScheme.background.luminance() < 0.5f + val dropdownColor = if (isDark) MaterialTheme.colorScheme.surfaceContainerHigh else MaterialTheme.colorScheme.surfaceContainer MaterialTheme( colorScheme = MaterialTheme.colorScheme.copy( - surface = MaterialTheme.colorScheme.surfaceContainerHigh, - surfaceContainer = MaterialTheme.colorScheme.surfaceContainerHigh, + surface = dropdownColor, + surfaceContainer = dropdownColor, surfaceTint = Color.Transparent ), shapes = MaterialTheme.shapes.copy( diff --git a/Android/app/src/main/java/com/droidspaces/app/ui/screen/ProcdScreen.kt b/Android/app/src/main/java/com/droidspaces/app/ui/screen/ProcdScreen.kt index f9f02720..0c30b6d3 100644 --- a/Android/app/src/main/java/com/droidspaces/app/ui/screen/ProcdScreen.kt +++ b/Android/app/src/main/java/com/droidspaces/app/ui/screen/ProcdScreen.kt @@ -18,6 +18,7 @@ import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.luminance import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.text.font.Font import androidx.compose.ui.text.font.FontFamily @@ -404,10 +405,12 @@ private fun ProcdServiceCard( ) { Box(contentAlignment = Alignment.Center) { Icon(Icons.Default.MoreVert, null, tint = MaterialTheme.colorScheme.onSurfaceVariant) } } + val isDark = MaterialTheme.colorScheme.background.luminance() < 0.5f + val dropdownColor = if (isDark) MaterialTheme.colorScheme.surfaceContainerHigh else MaterialTheme.colorScheme.surfaceContainer MaterialTheme( colorScheme = MaterialTheme.colorScheme.copy( - surface = MaterialTheme.colorScheme.surfaceContainerHigh, - surfaceContainer = MaterialTheme.colorScheme.surfaceContainerHigh, + surface = dropdownColor, + surfaceContainer = dropdownColor, surfaceTint = Color.Transparent ), shapes = MaterialTheme.shapes.copy( diff --git a/Android/app/src/main/java/com/droidspaces/app/ui/screen/SystemdScreen.kt b/Android/app/src/main/java/com/droidspaces/app/ui/screen/SystemdScreen.kt index 0edc64e0..40a0ccbc 100644 --- a/Android/app/src/main/java/com/droidspaces/app/ui/screen/SystemdScreen.kt +++ b/Android/app/src/main/java/com/droidspaces/app/ui/screen/SystemdScreen.kt @@ -18,6 +18,7 @@ import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.luminance import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.text.font.Font import androidx.compose.ui.text.font.FontFamily @@ -377,10 +378,12 @@ private fun ServiceCard( } Box { Surface(onClick = { showMenu = true }, modifier = Modifier.size(48.dp), shape = RoundedCornerShape(16.dp), color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.05f), border = BorderStroke(1.dp, MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.2f))) { Box(contentAlignment = Alignment.Center) { Icon(Icons.Default.MoreVert, null, tint = MaterialTheme.colorScheme.onSurfaceVariant) } } + val isDark = MaterialTheme.colorScheme.background.luminance() < 0.5f + val dropdownColor = if (isDark) MaterialTheme.colorScheme.surfaceContainerHigh else MaterialTheme.colorScheme.surfaceContainer MaterialTheme( colorScheme = MaterialTheme.colorScheme.copy( - surface = MaterialTheme.colorScheme.surfaceContainerHigh, - surfaceContainer = MaterialTheme.colorScheme.surfaceContainerHigh, + surface = dropdownColor, + surfaceContainer = dropdownColor, surfaceTint = Color.Transparent ), shapes = MaterialTheme.shapes.copy( From bbd37ea227bc231778ca0c756734dc3ba790094e Mon Sep 17 00:00:00 2001 From: VizXtreme Date: Wed, 15 Jul 2026 19:18:09 +0530 Subject: [PATCH 19/19] Delete .github/workflows/ci_test.yml --- .github/workflows/ci_test.yml | 215 ---------------------------------- 1 file changed, 215 deletions(-) delete mode 100644 .github/workflows/ci_test.yml diff --git a/.github/workflows/ci_test.yml b/.github/workflows/ci_test.yml deleted file mode 100644 index 109264b1..00000000 --- a/.github/workflows/ci_test.yml +++ /dev/null @@ -1,215 +0,0 @@ -name: test builds vizx - -on: - push: - branches: [ "main", "master", "ui" ] - pull_request: - branches: [ "main", "master", "ui" ] - workflow_dispatch: - inputs: - create_release: - description: 'Create an Official GitHub Release?' - required: true - type: boolean - default: false - tag_name: - description: 'Tag name (Only used if Release is checked)' - required: false - default: 'test' - -jobs: - build: - name: Build Backend & Android App - runs-on: ubuntu-latest - env: - HAS_TELEGRAM: ${{ secrets.API_ID != '' && secrets.API_HASH != '' }} - GRADLE_OPTS: "-Dorg.gradle.daemon=false -Dorg.gradle.workers.max=4" - steps: - - uses: actions/checkout@v4 - - - name: Set up JDK 17 - uses: actions/setup-java@v4 - with: - java-version: '17' - distribution: 'temurin' - cache: gradle - - - name: Cache Toolchains - id: cache-toolchains - uses: actions/cache@v4 - with: - path: ~/toolchains - key: ${{ runner.os }}-toolchains-25843896720 - - - name: Download Toolchains - if: steps.cache-toolchains.outputs.cache-hit != 'true' - run: | - mkdir -p $HOME/toolchains - cd $HOME/toolchains - BASE_URL="https://github.com/ravindu644/Droidspaces-OSS/releases/download/compilers-25843896720" - - echo "[*] Downloading toolchains in parallel..." - wget -q $BASE_URL/aarch64-linux-musl-cross.tar.zst & - wget -q $BASE_URL/arm-linux-musleabihf-cross.tar.zst & - wget -q $BASE_URL/i686-linux-musl-cross.tar.zst & - wget -q $BASE_URL/x86_64-linux-musl-cross.tar.zst & - wget -q $BASE_URL/riscv64-linux-musl-cross.tar.zst & - wait - - echo "[*] Extracting toolchains in parallel..." - for f in *.tar.zst; do - tar -xf "$f" & - done - wait - - rm -f *.tar.zst - echo "[+] Toolchains ready." - - - name: Build All Tarball, Debian Packages & Sync to Android - run: | - make all-tarball - scripts/mkdeb.sh - - - name: Prepare Android Build - env: - RELEASE_KEYSTORE: ${{ secrets.RELEASE_KEYSTORE }} - run: | - # Decode keystore if available - if [ -n "$RELEASE_KEYSTORE" ]; then - echo "$RELEASE_KEYSTORE" | base64 -d > droidspaces.keystore - fi - chmod +x Android/gradlew - - - name: Generate Contributors - continue-on-error: true - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - pip install -q requests - python3 scripts/generate_contributors.py - - - name: Build Android App with Gradle - env: - KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }} - KEY_ALIAS: ${{ secrets.KEY_ALIAS }} - KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }} - run: | - cd Android - ./gradlew assembleRelease --no-daemon --build-cache \ - -PKEYSTORE_PASSWORD="${{ secrets.KEYSTORE_PASSWORD }}" \ - -PKEY_ALIAS="${{ secrets.KEY_ALIAS }}" \ - -PKEY_PASSWORD="${{ secrets.KEY_PASSWORD }}" - - - name: Stage & Rename Artifacts - run: | - TAG="${{ github.event.inputs.tag_name || 'CI' }}" - COMMIT_HASH=$(git log -1 --pretty=%h) - APK_NAME="Droidspaces-universal-${TAG}-${COMMIT_HASH}.apk" - TAR_NAME=$(ls droidspaces-v*-*.tar.gz) - mkdir -p dist - mv Android/app/build/outputs/apk/release/app-release.apk dist/${APK_NAME} - mv ${TAR_NAME} dist/ - mv droidspaces_*.deb dist/ - echo "APK_FILE=dist/${APK_NAME}" >> $GITHUB_ENV - echo "TAR_FILE=dist/${TAR_NAME}" >> $GITHUB_ENV - - - name: Generate Telegram Message - if: github.event_name != 'pull_request' - run: | - EVENT_TYPE="${{ github.event_name == 'workflow_dispatch' && github.event.inputs.create_release == 'true' && 'Official Release' || 'Git Push' }}" - COMMIT_MSG=$(git log -1 --pretty=format:%s) - { - echo "TELEGRAM_MESSAGE<> "$GITHUB_ENV" - - - name: Upload Final Artifacts (APK, Tarball & Debian Packages) - uses: actions/upload-artifact@v4 - with: - name: droidspaces-artifacts - path: dist/ - - - name: Send Telegram Notification - if: | - github.event_name != 'pull_request' && - env.HAS_TELEGRAM == 'true' - uses: xz-dev/TelegramFileUploader@v1 - with: - to-who: ${{ secrets.TELEGRAM_TO }} - message: ${{ env.TELEGRAM_MESSAGE }} - files: | - ${{ env.APK_FILE }} - ${{ env.TAR_FILE }} - env: - API_ID: ${{ secrets.API_ID }} - API_HASH: ${{ secrets.API_HASH }} - BOT_TOKEN: ${{ secrets.TELEGRAM_TOKEN }} - - release: - name: Create GitHub Release - needs: [build] - if: | - github.event_name == 'workflow_dispatch' && - github.event.inputs.create_release == 'true' && - github.event.inputs.tag_name != '' && - github.event.inputs.tag_name != 'test' - runs-on: ubuntu-latest - permissions: - contents: write - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Download Artifacts - uses: actions/download-artifact@v4 - with: - path: release-assets - merge-multiple: true - - - name: Generate Changelog - id: changelog - run: | - PREV_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "") - echo "Previous tag: $PREV_TAG" - - if [ -z "$PREV_TAG" ]; then - CHANGELOG=$(git log --oneline --pretty=format:"* %s (%h)") - else - CHANGELOG=$(git log ${PREV_TAG}..HEAD --oneline --pretty=format:"* %s (%h)") - fi - - { - echo "notes<> "$GITHUB_OUTPUT" - - - name: Create Release - uses: softprops/action-gh-release@v2 - with: - tag_name: ${{ github.event.inputs.tag_name }} - name: Droidspaces ${{ github.event.inputs.tag_name || 'Development Build' }} - target_commitish: ${{ github.sha }} - body: | - ## What's Changed - ${{ steps.changelog.outputs.notes }} - - --- - **Automated Release by Droidspaces CI** - files: | - release-assets/*.apk - release-assets/*.tar.gz - release-assets/*.deb