diff --git a/.github/scripts/generate-version.sh b/.github/scripts/generate-version.sh index 4196e4e0..ff2e5967 100755 --- a/.github/scripts/generate-version.sh +++ b/.github/scripts/generate-version.sh @@ -3,48 +3,88 @@ set -e # Generate CalVer version in YY.WW.MICRO format (always 3 segments for Rust/Tauri) # Example: 25.48.0 (initial), 25.48.1 (first patch), 25.48.2 (second patch) +# +# Patch mode: when merging a patch/* branch into main, bump the latest tag's +# micro version instead of generating a new CalVer based on today's date. -# Get current year (last 2 digits) and week number (zero-padded) -YEAR=$(date +%y) -WEEK=$(date +%V) -WEEK_NO_PAD=$((10#$WEEK)) # Remove leading zero for semver compliance -BASE_VERSION="${YEAR}.${WEEK}" +PATCH_MODE=false -echo "Base version: ${BASE_VERSION}" +# Look up the source branch via GitHub API (works with squash merges) +if [ -n "$GITHUB_REPOSITORY" ] && [ -n "$GH_TOKEN" ]; then + SOURCE_BRANCH=$(gh api "/repos/${GITHUB_REPOSITORY}/commits/$(git rev-parse HEAD)/pulls" --jq '.[0].head.ref' 2>/dev/null || echo "") -# Find all tags matching this week's base version (both YY.WW and YY.WW.MICRO) -EXISTING_TAGS=$(git tag -l "${BASE_VERSION}" "${BASE_VERSION}.*" 2>/dev/null || echo "") + if echo "$SOURCE_BRANCH" | grep -q "^patch/"; then + PATCH_MODE=true + echo "Patch mode detected from source branch: ${SOURCE_BRANCH}" + fi +fi + +if [ "$PATCH_MODE" = true ]; then + # Find the latest existing tag (by version, not date) + LATEST_TAG=$(git tag -l --sort=-v:refname | grep -E '^[0-9]{2}\.[0-9]{1,2}(\.[0-9]+)?$' | head -1) + + if [ -z "$LATEST_TAG" ]; then + echo "Error: No existing CalVer tags found for patching" + exit 1 + fi + + echo "Patching from latest tag: ${LATEST_TAG}" -if [ -z "$EXISTING_TAGS" ]; then - # No tags exist for this week, start with .0 - VERSION="${BASE_VERSION}.0" - MICRO=0 + # Parse the latest tag: could be YY.WW or YY.WW.MICRO + YEAR=$(echo "$LATEST_TAG" | cut -d. -f1) + WEEK=$(echo "$LATEST_TAG" | cut -d. -f2) + CURRENT_MICRO=$(echo "$LATEST_TAG" | cut -d. -f3) + + # If no micro segment (bare YY.WW tag), treat as .0 + if [ -z "$CURRENT_MICRO" ]; then + CURRENT_MICRO=0 + fi + + MICRO=$((CURRENT_MICRO + 1)) + WEEK_NO_PAD=$((10#$WEEK)) + VERSION="${YEAR}.${WEEK}.${MICRO}" + SEMVER="${YEAR}.${WEEK_NO_PAD}.${MICRO}" + + echo "Patch version: ${VERSION} (semver: ${SEMVER})" else - # Find the highest micro version - # Filter out the base version and extract micro numbers - MICRO_TAGS=$(echo "$EXISTING_TAGS" | grep -E "^${BASE_VERSION}\.[0-9]+$" || echo "") + # Standard CalVer: generate from current date + YEAR=$(date +%y) + WEEK=$(date +%V) + WEEK_NO_PAD=$((10#$WEEK)) + BASE_VERSION="${YEAR}.${WEEK}" + + echo "Base version: ${BASE_VERSION}" + + # Find all tags matching this week's base version (both YY.WW and YY.WW.MICRO) + EXISTING_TAGS=$(git tag -l "${BASE_VERSION}" "${BASE_VERSION}.*" 2>/dev/null || echo "") - if [ -z "$MICRO_TAGS" ]; then - # Only base version exists (YY.WW), start patches at .1 - MICRO=1 + if [ -z "$EXISTING_TAGS" ]; then + # No tags exist for this week, start with .0 + MICRO=0 else - # Find highest existing micro version - HIGHEST_MICRO=$(echo "$MICRO_TAGS" | sed "s/${BASE_VERSION}\\.//g" | sort -n | tail -1) - MICRO=$((HIGHEST_MICRO + 1)) + # Find the highest micro version + MICRO_TAGS=$(echo "$EXISTING_TAGS" | grep -E "^${BASE_VERSION}\.[0-9]+$" || echo "") + + if [ -z "$MICRO_TAGS" ]; then + # Only base version exists (YY.WW), start patches at .1 + MICRO=1 + else + # Find highest existing micro version + HIGHEST_MICRO=$(echo "$MICRO_TAGS" | sed "s/${BASE_VERSION}\\.//g" | sort -n | tail -1) + MICRO=$((HIGHEST_MICRO + 1)) + fi fi VERSION="${BASE_VERSION}.${MICRO}" -fi + SEMVER="${YEAR}.${WEEK_NO_PAD}.${MICRO}" -# Semver version without leading zeros (for Cargo.toml, tauri.conf.json, package.json) -SEMVER="${YEAR}.${WEEK_NO_PAD}.${MICRO}" + echo "Generated version: ${VERSION} (semver: ${SEMVER})" +fi -echo "Generated version: ${VERSION} (semver: ${SEMVER})" echo "VERSION=${VERSION}" >> $GITHUB_OUTPUT echo "SEMVER=${SEMVER}" >> $GITHUB_OUTPUT echo "TAG=${VERSION}" >> $GITHUB_OUTPUT # Also calculate versionCode (YYWWMMMM format for Android) -# Example: 25480000 (25.48), 25480001 (25.48.1), 25480002 (25.48.2) VERSION_CODE=$(printf "%02d%02d%04d" $YEAR $WEEK $MICRO) echo "VERSION_CODE=${VERSION_CODE}" >> $GITHUB_OUTPUT diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index 0acf095b..d112ebff 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -28,6 +28,8 @@ jobs: run: | chmod +x .github/scripts/generate-version.sh .github/scripts/generate-version.sh + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: 'Display version info' run: | diff --git a/CHANGELOG.md b/CHANGELOG.md index 123720e6..e7a60bd8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,13 @@ All notable changes to LibreFit will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project uses [Calendar Versioning](https://calver.org/) (YY.WW.MICRO format). +## [26.07.3] - 2026-02-16 + +### Fixed + +- Background color for Android system bar in edge 2 edge +- Disabled Android app window overscrolling + ## [26.07.2] - 2026-02-15 ### Changed @@ -85,6 +92,7 @@ and this project uses [Calendar Versioning](https://calver.org/) (YY.WW.MICRO fo - F-Droid compatible build process - Reproducible builds support +[26.07.3] https://github.com/thwbh/librefit/releases/tag/26.07.3 [26.07.2]: https://github.com/thwbh/librefit/releases/tag/26.07.2 [26.07.1]: https://github.com/thwbh/librefit/releases/tag/26.07.1 [26.07]: https://github.com/thwbh/librefit/releases/tag/26.07 diff --git a/src-tauri/android-templates/MainActivity.kt b/src-tauri/android-templates/MainActivity.kt new file mode 100644 index 00000000..9553dbe2 --- /dev/null +++ b/src-tauri/android-templates/MainActivity.kt @@ -0,0 +1,30 @@ +package io.tohowabohu.librefit + +import android.os.Bundle +import android.view.View +import androidx.activity.enableEdgeToEdge + +class MainActivity : TauriActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + enableEdgeToEdge() + super.onCreate(savedInstanceState) + } + + override fun onResume() { + super.onResume() + // Disable WebView overscroll to prevent bouncing that reveals gaps behind system bars + val webView = findWebView(window.decorView) + webView?.overScrollMode = View.OVER_SCROLL_NEVER + } + + private fun findWebView(view: View): View? { + if (view is android.webkit.WebView) return view + if (view is android.view.ViewGroup) { + for (i in 0 until view.childCount) { + val found = findWebView(view.getChildAt(i)) + if (found != null) return found + } + } + return null + } +} diff --git a/src-tauri/android-templates/colors.xml b/src-tauri/android-templates/colors.xml new file mode 100644 index 00000000..b5cfac42 --- /dev/null +++ b/src-tauri/android-templates/colors.xml @@ -0,0 +1,12 @@ + + + #FFBB86FC + #FF6200EE + #FF3700B3 + #FF03DAC5 + #FF018786 + #FF000000 + #FFFFFFFF + #FF1A7A8A + #FFF9F8F6 + diff --git a/src-tauri/android-templates/setup-android.sh b/src-tauri/android-templates/setup-android.sh index 57e54531..e0cfb2f0 100755 --- a/src-tauri/android-templates/setup-android.sh +++ b/src-tauri/android-templates/setup-android.sh @@ -73,7 +73,40 @@ else echo " ⚠️ AndroidManifest.xml template not found" fi -# 5. Force correct NDK path and version in local.properties and build.gradle.kts +# 5. Apply custom MainActivity.kt (edge-to-edge + overscroll fix) +if [ -f "$SCRIPT_DIR/MainActivity.kt" ]; then + echo "📱 Applying custom MainActivity.kt..." + MAIN_ACTIVITY_DIR="$ANDROID_DIR/app/src/main/java/io/tohowabohu/librefit" + cp "$SCRIPT_DIR/MainActivity.kt" "$MAIN_ACTIVITY_DIR/MainActivity.kt" + echo " ✅ MainActivity.kt applied (edge-to-edge + overscroll disabled)" +else + echo " ⚠️ MainActivity.kt template not found" +fi + +# 6. Apply custom themes.xml (window background + transparent system bars) +if [ -f "$SCRIPT_DIR/themes.xml" ]; then + echo "🎨 Applying custom themes.xml..." + cp "$SCRIPT_DIR/themes.xml" "$ANDROID_DIR/app/src/main/res/values/themes.xml" + # Also apply to night theme + NIGHT_DIR="$ANDROID_DIR/app/src/main/res/values-night" + if [ -d "$NIGHT_DIR" ]; then + cp "$SCRIPT_DIR/themes.xml" "$NIGHT_DIR/themes.xml" + fi + echo " ✅ themes.xml applied (primary window background)" +else + echo " ⚠️ themes.xml template not found" +fi + +# 7. Apply custom colors.xml (app color definitions) +if [ -f "$SCRIPT_DIR/colors.xml" ]; then + echo "🎨 Applying custom colors.xml..." + cp "$SCRIPT_DIR/colors.xml" "$ANDROID_DIR/app/src/main/res/values/colors.xml" + echo " ✅ colors.xml applied (includes primary color)" +else + echo " ⚠️ colors.xml template not found" +fi + +# 8. Force correct NDK path and version in local.properties and build.gradle.kts if [ -n "$NDK_PATH" ]; then echo "🔧 Setting NDK path in local.properties..." diff --git a/src-tauri/android-templates/themes.xml b/src-tauri/android-templates/themes.xml new file mode 100644 index 00000000..1893944c --- /dev/null +++ b/src-tauri/android-templates/themes.xml @@ -0,0 +1,8 @@ + + + diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 7be191ed..3e334d23 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -10,7 +10,8 @@ "height": 800, "resizable": true, "title": "librefit", - "width": 420 + "width": 420, + "backgroundColor": [249, 248, 246, 255] } ] }, diff --git a/src/routes/(app)/+page.svelte b/src/routes/(app)/+page.svelte index 13057ae5..dc5572c7 100644 --- a/src/routes/(app)/+page.svelte +++ b/src/routes/(app)/+page.svelte @@ -187,7 +187,7 @@

Dashboard

-
+
Day {dashboard.currentDay + 1} diff --git a/src/routes/(app)/export/+page.svelte b/src/routes/(app)/export/+page.svelte index 1aebf7fd..cdfa8c11 100644 --- a/src/routes/(app)/export/+page.svelte +++ b/src/routes/(app)/export/+page.svelte @@ -203,7 +203,7 @@

Data Export

-
+
Export Data diff --git a/src/routes/(app)/history/+page.svelte b/src/routes/(app)/history/+page.svelte index 408b058a..9083a4b9 100644 --- a/src/routes/(app)/history/+page.svelte +++ b/src/routes/(app)/history/+page.svelte @@ -272,7 +272,7 @@

History

-
+
{#if selectedDateStr} {@const selectedDate = parseStringAsDate(selectedDateStr)}
diff --git a/src/routes/(app)/import/+page.svelte b/src/routes/(app)/import/+page.svelte index 434fc921..0a50c425 100644 --- a/src/routes/(app)/import/+page.svelte +++ b/src/routes/(app)/import/+page.svelte @@ -149,7 +149,7 @@

Data Import

-
+
Import Data diff --git a/src/routes/(app)/profile/+page.svelte b/src/routes/(app)/profile/+page.svelte index 55023d63..a530985d 100644 --- a/src/routes/(app)/profile/+page.svelte +++ b/src/routes/(app)/profile/+page.svelte @@ -58,7 +58,7 @@

User Profile

-
+
Profile diff --git a/src/routes/(app)/progress/+page.svelte b/src/routes/(app)/progress/+page.svelte index 5479e5eb..16e3afe3 100644 --- a/src/routes/(app)/progress/+page.svelte +++ b/src/routes/(app)/progress/+page.svelte @@ -151,7 +151,7 @@

Progress

-
+
Your Progress Day {daysPassed + 1} of {daysTotal + 1} diff --git a/src/routes/(app)/wizard/+page.svelte b/src/routes/(app)/wizard/+page.svelte index b526592e..d313259b 100644 --- a/src/routes/(app)/wizard/+page.svelte +++ b/src/routes/(app)/wizard/+page.svelte @@ -63,7 +63,7 @@

Setup Wizard

-
+
Step {currentStep} of {totalSteps} diff --git a/src/routes/setup/+page.svelte b/src/routes/setup/+page.svelte index 33f79380..2bdc8148 100644 --- a/src/routes/setup/+page.svelte +++ b/src/routes/setup/+page.svelte @@ -54,7 +54,7 @@

Setup Wizard

-
+
Step {currentStep} of {totalSteps} diff --git a/src/style.css b/src/style.css index 0cacb30a..883a4dd8 100644 --- a/src/style.css +++ b/src/style.css @@ -43,9 +43,21 @@ } /* Safe area insets for devices with notches / rounded corners */ +html { + background-color: oklch( + 98% 0.001 106.423 + ); /* --color-base-100, neutral fill behind system bars */ +} + body { - padding-top: env(safe-area-inset-top); - padding-bottom: env(safe-area-inset-bottom); padding-left: env(safe-area-inset-left); padding-right: env(safe-area-inset-right); + overscroll-behavior: none; /* prevent WebView overscroll bounce */ } + +/* Page headers that extend behind the status bar */ +.safe-top { + padding-top: calc(env(safe-area-inset-top) + 2rem); /* safe-area + original pt-8 */ +} + +/* Bottom dock safe area handled by AppShell */