diff --git a/.flutter b/.flutter index 5874a72aa..2663184aa 160000 --- a/.flutter +++ b/.flutter @@ -1 +1 @@ -Subproject commit 5874a72aa4c779a02553007c47dacbefba2374dc +Subproject commit 2663184aa79047d0a33a14a3b607954f8fdd8730 diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml deleted file mode 100644 index 0b4a26569..000000000 --- a/.github/workflows/check.yml +++ /dev/null @@ -1,36 +0,0 @@ -name: Quality check - -on: - push: - branches: - - develop - pull_request: - types: [ opened, synchronize, reopened ] - -permissions: - contents: read - -jobs: - build: - name: Check code quality. - runs-on: ubuntu-latest - steps: - - name: Harden Runner - uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1 - with: - egress-policy: audit - - - name: Clone the repository. - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - - - name: Get packages for the Flutter project. - run: scripts/pub_get_all.sh - - - name: Update the flutter version file. - run: scripts/update_flutter_version.sh - - - name: Static analysis. - run: ./flutterw analyze - - - name: Unit tests. - run: ./flutterw test diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index bf2dcfbae..c1209291a 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -17,7 +17,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1 + uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1 with: egress-policy: audit diff --git a/.github/workflows/quality-check.yml b/.github/workflows/quality-check.yml new file mode 100644 index 000000000..80bc4a5ca --- /dev/null +++ b/.github/workflows/quality-check.yml @@ -0,0 +1,88 @@ +name: Quality check + +on: + push: + branches: [ "develop", "main" ] + pull_request: + branches: [ "develop", "main" ] + types: [ opened, synchronize, reopened ] + schedule: + - cron: '17 8 * * 3' + +# Declare default permissions as read only. +permissions: read-all + +jobs: + analyze_flutter: + name: Flutter analysis + runs-on: ubuntu-latest + steps: + - name: Harden Runner + uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1 + with: + egress-policy: audit + + - name: Checkout repository + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + + - name: Get Flutter packages + run: scripts/pub_get_all.sh + + - name: Static analysis. + run: ./flutterw analyze + + - name: Unit tests. + run: ./flutterw test + + analyze_codeql: + name: CodeQL analysis (${{ matrix.language }}) + runs-on: ubuntu-latest + permissions: + # required for all workflows + security-events: write + + # required to fetch internal or private CodeQL packs + packages: read + + strategy: + fail-fast: false + matrix: + include: + - language: java-kotlin + build-mode: manual + steps: + - name: Harden Runner + uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1 + with: + egress-policy: audit + + # Building relies on the Android Gradle plugin, + # which requires a modern Java version (not the default one). + - name: Set up JDK for Android Gradle plugin + uses: actions/setup-java@2dfa2011c5b2a0f1489bf9e433881c92c1631f88 # v4.3.0 + with: + distribution: 'temurin' + java-version: '21' + + - name: Checkout repository + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@8214744c546c1e5c8f03dde8fab3a7353211988d # v3.26.7 + with: + languages: ${{ matrix.language }} + build-mode: ${{ matrix.build-mode }} + + - if: matrix.build-mode == 'manual' + shell: bash + # build in profile mode, instead of release, + # so that setting up signing environment variables is not required + run: | + scripts/apply_flavor_play.sh + ./flutterw build apk --profile -t lib/main_play.dart --flavor play + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@8214744c546c1e5c8f03dde8fab3a7353211988d # v3.26.7 + with: + category: "/language:${{matrix.language}}" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index eed50c1ec..da00c1886 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -5,37 +5,39 @@ on: tags: - v* +# Declare default permissions as read only. +permissions: read-all + jobs: - build: - name: Build and release artifacts. + release_github: + name: GitHub release runs-on: ubuntu-latest + permissions: + contents: write steps: - name: Harden Runner - uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1 + uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1 with: egress-policy: audit - - uses: actions/setup-java@6a0805fcefea3d4657a47ac4c165951e33482018 # v4.2.2 + # Building relies on the Android Gradle plugin, + # which requires a modern Java version (not the default one). + - name: Set up JDK for Android Gradle plugin + uses: actions/setup-java@2dfa2011c5b2a0f1489bf9e433881c92c1631f88 # v4.3.0 with: - distribution: 'zulu' - java-version: '17' + distribution: 'temurin' + java-version: '21' - - name: Clone the repository. + - name: Checkout repository uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - - name: Get packages for the Flutter project. + - name: Get Flutter packages run: scripts/pub_get_all.sh - - name: Update the flutter version file. + - name: Update Flutter version file run: scripts/update_flutter_version.sh - - name: Static analysis. - run: ./flutterw analyze - - - name: Unit tests. - run: ./flutterw test - - - name: Build signed artifacts. + - name: Build signed artifacts # `KEY_JKS` should contain the result of: # gpg -c --armor keystore.jks # `KEY_JKS_PASSPHRASE` should contain the passphrase used for the command above @@ -70,7 +72,7 @@ jobs: AVES_KEY_PASSWORD: ${{ secrets.AVES_KEY_PASSWORD }} AVES_GOOGLE_API_KEY: ${{ secrets.AVES_GOOGLE_API_KEY }} - - name: Create a release with the APK and App Bundle. + - name: Create GitHub release uses: ncipollo/release-action@2c591bcc8ecdcd2db72b97d6147f871fcd833ba5 # v1.14.0 with: artifacts: "outputs/*" @@ -78,29 +80,30 @@ jobs: token: ${{ secrets.GITHUB_TOKEN }} - name: Upload app bundle - uses: actions/upload-artifact@834a144ee995460fba8ed112a2fc961b36a5ec5a # v4.3.6 + uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0 with: name: appbundle path: outputs/app-play-release.aab - release: - name: Create beta release on Play Store. + release_play: + name: Play Store beta release needs: [ build ] runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1 + uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1 with: egress-policy: audit - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - name: Checkout repository + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - - name: Get appbundle from artifacts. + - name: Get appbundle from artifacts uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 with: name: appbundle - - name: Release app to beta channel. + - name: Release to beta channel uses: r0adkll/upload-google-play@935ef9c68bb393a8e6116b1575626a7f5be3a7fb # v1.1.3 with: serviceAccountJsonPlainText: ${{ secrets.PLAYSTORE_ACCOUNT_KEY }} diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml index 284577b60..a71b2294a 100644 --- a/.github/workflows/scorecards.yml +++ b/.github/workflows/scorecards.yml @@ -31,7 +31,7 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1 + uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1 with: egress-policy: audit @@ -63,7 +63,7 @@ jobs: # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF # format to the repository Actions tab. - name: "Upload artifact" - uses: actions/upload-artifact@834a144ee995460fba8ed112a2fc961b36a5ec5a # v4.3.6 + uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0 with: name: SARIF file path: results.sarif @@ -71,6 +71,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@4dd16135b69a43b6c8efb853346f8437d92d3c93 # v3.26.6 + uses: github/codeql-action/upload-sarif@8214744c546c1e5c8f03dde8fab3a7353211988d # v3.26.7 with: sarif_file: results.sarif diff --git a/CHANGELOG.md b/CHANGELOG.md index 5e442ed26..8dbf7c1c5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,21 @@ All notable changes to this project will be documented in this file. ## [Unreleased] +## [v1.11.11] - 2024-09-16 + +### Added + +- support opening from the lock screen + +### Changed + +- upgraded Flutter to stable v3.24.3 + +### Fixed + +- crash when cataloguing some malformed MP4 files +- inconsistent launch screen + ## [v1.11.10] - 2024-09-01 ### Added diff --git a/android/app/build.gradle b/android/app/build.gradle index 2a68ac2c7..fe76fbbec 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -49,8 +49,8 @@ android { ndkVersion '26.1.10909125' compileOptions { - sourceCompatibility JavaVersion.VERSION_17 - targetCompatibility JavaVersion.VERSION_17 + sourceCompatibility JavaVersion.VERSION_21 + targetCompatibility JavaVersion.VERSION_21 } lint { @@ -156,12 +156,12 @@ android { } tasks.withType(KotlinCompile).configureEach { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 + sourceCompatibility = JavaVersion.VERSION_21 + targetCompatibility = JavaVersion.VERSION_21 } kotlin { - jvmToolchain(17) + jvmToolchain(21) } flutter { @@ -189,11 +189,11 @@ dependencies { implementation "androidx.appcompat:appcompat:1.7.0" implementation 'androidx.core:core-ktx:1.13.1' - implementation 'androidx.lifecycle:lifecycle-process:2.8.4' + implementation 'androidx.lifecycle:lifecycle-process:2.8.5' implementation 'androidx.media:media:1.7.0' implementation 'androidx.multidex:multidex:2.0.1' implementation 'androidx.security:security-crypto:1.1.0-alpha06' - implementation 'androidx.work:work-runtime-ktx:2.9.0' + implementation 'androidx.work:work-runtime-ktx:2.9.1' implementation 'com.caverock:androidsvg-aar:1.4' implementation 'com.commonsware.cwac:document:0.5.0' @@ -208,14 +208,14 @@ dependencies { // - https://jitpack.io/p/deckerst/mp4parser // - https://jitpack.io/p/deckerst/pixymeta-android implementation 'com.github.deckerst:Android-TiffBitmapFactory:90c06eebf4' - implementation 'com.github.deckerst.mp4parser:isoparser:4cc0c5d06c' - implementation 'com.github.deckerst.mp4parser:muxer:4cc0c5d06c' + implementation 'com.github.deckerst.mp4parser:isoparser:86d4b6baa1' + implementation 'com.github.deckerst.mp4parser:muxer:86d4b6baa1' implementation 'com.github.deckerst:pixymeta-android:9ec7097f17' implementation project(':exifinterface') testImplementation 'org.junit.jupiter:junit-jupiter-engine:5.10.3' - kapt 'androidx.annotation:annotation:1.8.1' + kapt 'androidx.annotation:annotation:1.8.2' ksp "com.github.bumptech.glide:ksp:$glide_version" compileOnly rootProject.findProject(':streams_channel') diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 434def855..ac6a039d2 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -128,6 +128,7 @@ android:exported="true" android:hardwareAccelerated="true" android:launchMode="singleTop" + android:showWhenLocked="true" android:supportsPictureInPicture="true" android:theme="@style/NormalTheme" android:windowSoftInputMode="adjustResize"> diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/MainActivity.kt b/android/app/src/main/kotlin/deckers/thibault/aves/MainActivity.kt index 696e0ebe3..0e7a68ecd 100644 --- a/android/app/src/main/kotlin/deckers/thibault/aves/MainActivity.kt +++ b/android/app/src/main/kotlin/deckers/thibault/aves/MainActivity.kt @@ -4,6 +4,7 @@ import android.annotation.SuppressLint import android.app.SearchManager import android.appwidget.AppWidgetManager import android.content.ClipData +import android.content.Context import android.content.Intent import android.net.Uri import android.os.Build @@ -229,6 +230,7 @@ open class MainActivity : FlutterFragmentActivity() { intentStreamHandler.notifyNewIntent(extractIntentData(intent)) } + @Deprecated("Deprecated in Java") override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) when (requestCode) { @@ -316,6 +318,13 @@ open class MainActivity : FlutterFragmentActivity() { INTENT_DATA_KEY_URI to uri.toString(), ) + val keyguardManager = getSystemService(Context.KEYGUARD_SERVICE) as android.app.KeyguardManager + val isLocked = keyguardManager.isKeyguardLocked + if (isLocked) { + // device is locked, so access to content is limited to intent URI by default + fields[INTENT_DATA_KEY_SECURE_URIS] = listOf(uri.toString()) + } + if (action == MediaStore.ACTION_REVIEW_SECURE) { val uris = ArrayList() intent.clipData?.let { clipData -> @@ -323,7 +332,9 @@ open class MainActivity : FlutterFragmentActivity() { clipData.getItemAt(i).uri?.let { uris.add(it.toString()) } } } - fields[INTENT_DATA_KEY_SECURE_URIS] = uris + if (uris.isNotEmpty()) { + fields[INTENT_DATA_KEY_SECURE_URIS] = uris + } } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && intent.hasExtra(MediaStore.EXTRA_BRIGHTNESS)) { fields[INTENT_DATA_KEY_BRIGHTNESS] = intent.getFloatExtra(MediaStore.EXTRA_BRIGHTNESS, 0f) diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/DeviceHandler.kt b/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/DeviceHandler.kt index 603739bde..3fe35ae01 100644 --- a/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/DeviceHandler.kt +++ b/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/DeviceHandler.kt @@ -33,6 +33,7 @@ class DeviceHandler(private val context: Context) : MethodCallHandler { "getDefaultTimeZoneRawOffsetMillis" -> safe(call, result, ::getDefaultTimeZoneRawOffsetMillis) "getLocales" -> safe(call, result, ::getLocales) "getPerformanceClass" -> safe(call, result, ::getPerformanceClass) + "isLocked" -> safe(call, result, ::isLocked) "isSystemFilePickerEnabled" -> safe(call, result, ::isSystemFilePickerEnabled) "requestMediaManagePermission" -> safe(call, result, ::requestMediaManagePermission) "getAvailableHeapSize" -> safe(call, result, ::getAvailableHeapSize) @@ -49,13 +50,11 @@ class DeviceHandler(private val context: Context) : MethodCallHandler { val sdkInt = Build.VERSION.SDK_INT result.success( hashMapOf( - "canGrantDirectoryAccess" to (sdkInt >= Build.VERSION_CODES.LOLLIPOP), "canPinShortcut" to ShortcutManagerCompat.isRequestPinShortcutSupported(context), "canRenderFlagEmojis" to (sdkInt >= Build.VERSION_CODES.M), "canRenderSubdivisionFlagEmojis" to (sdkInt >= Build.VERSION_CODES.O), "canRequestManageMedia" to (sdkInt >= Build.VERSION_CODES.S), "canSetLockScreenWallpaper" to (sdkInt >= Build.VERSION_CODES.N), - "canUseCrypto" to (sdkInt >= Build.VERSION_CODES.LOLLIPOP), "hasGeocoder" to Geocoder.isPresent(), "isDynamicColorAvailable" to DynamicColors.isDynamicColorAvailable(), "showPinShortcutFeedback" to (sdkInt >= Build.VERSION_CODES.O), @@ -100,6 +99,12 @@ class DeviceHandler(private val context: Context) : MethodCallHandler { result.success(Build.VERSION.SDK_INT) } + private fun isLocked(@Suppress("unused_parameter") call: MethodCall, result: MethodChannel.Result) { + val keyguardManager = context.getSystemService(Context.KEYGUARD_SERVICE) as android.app.KeyguardManager + val isLocked = keyguardManager.isKeyguardLocked + result.success(isLocked) + } + private fun isSystemFilePickerEnabled(@Suppress("unused_parameter") call: MethodCall, result: MethodChannel.Result) { val enabled = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE).resolveActivity(context.packageManager) != null result.success(enabled) diff --git a/android/app/src/main/res/drawable-v21/ic_notification.xml b/android/app/src/main/res/drawable/ic_notification.xml similarity index 100% rename from android/app/src/main/res/drawable-v21/ic_notification.xml rename to android/app/src/main/res/drawable/ic_notification.xml diff --git a/android/app/src/main/res/drawable-v21/ic_shortcut_collection.xml b/android/app/src/main/res/drawable/ic_shortcut_collection.xml similarity index 100% rename from android/app/src/main/res/drawable-v21/ic_shortcut_collection.xml rename to android/app/src/main/res/drawable/ic_shortcut_collection.xml diff --git a/android/app/src/main/res/drawable-v21/ic_shortcut_movie.xml b/android/app/src/main/res/drawable/ic_shortcut_movie.xml similarity index 100% rename from android/app/src/main/res/drawable-v21/ic_shortcut_movie.xml rename to android/app/src/main/res/drawable/ic_shortcut_movie.xml diff --git a/android/app/src/main/res/drawable-v21/ic_shortcut_safe_mode.xml b/android/app/src/main/res/drawable/ic_shortcut_safe_mode.xml similarity index 100% rename from android/app/src/main/res/drawable-v21/ic_shortcut_safe_mode.xml rename to android/app/src/main/res/drawable/ic_shortcut_safe_mode.xml diff --git a/android/app/src/main/res/drawable-v21/ic_shortcut_search.xml b/android/app/src/main/res/drawable/ic_shortcut_search.xml similarity index 100% rename from android/app/src/main/res/drawable-v21/ic_shortcut_search.xml rename to android/app/src/main/res/drawable/ic_shortcut_search.xml diff --git a/android/app/src/main/res/values-night/styles.xml b/android/app/src/main/res/values-night/styles.xml index edd8ddab8..807a30b31 100644 --- a/android/app/src/main/res/values-night/styles.xml +++ b/android/app/src/main/res/values-night/styles.xml @@ -1,7 +1,9 @@