diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml
index 21a469b13..922916c51 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@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2
+ uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3
with:
egress-policy: audit
diff --git a/.github/workflows/quality-check.yml b/.github/workflows/quality-check.yml
index 600c22410..03a30329d 100644
--- a/.github/workflows/quality-check.yml
+++ b/.github/workflows/quality-check.yml
@@ -18,7 +18,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Harden Runner
- uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2
+ uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3
with:
egress-policy: audit
@@ -52,7 +52,7 @@ jobs:
build-mode: manual
steps:
- name: Harden Runner
- uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2
+ uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3
with:
egress-policy: audit
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index fd8c4b809..88962648e 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -18,7 +18,7 @@ jobs:
id-token: write
steps:
- name: Harden Runner
- uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2
+ uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3
with:
egress-policy: audit
@@ -87,7 +87,7 @@ jobs:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Upload app bundle
- uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0
+ uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
name: appbundle
path: outputs/app-play-release.aab
@@ -98,7 +98,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Harden Runner
- uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2
+ uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3
with:
egress-policy: audit
diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml
index e60f97d09..8817a5788 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@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2
+ uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3
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@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0
+ uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
name: SARIF file
path: results.sarif
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ab0c1d46d..a00eab4d1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,23 @@ All notable changes to this project will be documented in this file.
## [Unreleased]
+## [v1.12.2] - 2025-01-13
+
+### Added
+
+- DDM coordinate format option
+
+### Changed
+
+- Video: use `media-kit` instead of `ffmpeg-kit` for metadata fetch
+- Info: show video chapters
+- Accessibility: apply system "touch and hold delay" setting
+
+### Fixed
+
+- crash when cataloguing some videos
+- switching to PiP for any inactive app state
+
## [v1.12.1] - 2025-01-05
### Added
diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/AccessibilityHandler.kt b/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/AccessibilityHandler.kt
index 248fdcce1..0e61c1fa3 100644
--- a/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/AccessibilityHandler.kt
+++ b/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/AccessibilityHandler.kt
@@ -6,6 +6,7 @@ import android.content.res.Configuration
import android.os.Build
import android.provider.Settings
import android.util.Log
+import android.view.ViewConfiguration
import android.view.accessibility.AccessibilityManager
import deckers.thibault.aves.channel.calls.Coresult.Companion.safe
import deckers.thibault.aves.utils.LogUtils
@@ -17,6 +18,7 @@ class AccessibilityHandler(private val contextWrapper: ContextWrapper) : MethodC
override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
when (call.method) {
"areAnimationsRemoved" -> safe(call, result, ::areAnimationsRemoved)
+ "getLongPressTimeout" -> safe(call, result, ::getLongPressTimeout)
"hasRecommendedTimeouts" -> safe(call, result, ::hasRecommendedTimeouts)
"getRecommendedTimeoutMillis" -> safe(call, result, ::getRecommendedTimeoutMillis)
"shouldUseBoldFont" -> safe(call, result, ::shouldUseBoldFont)
@@ -34,6 +36,10 @@ class AccessibilityHandler(private val contextWrapper: ContextWrapper) : MethodC
result.success(removed)
}
+ private fun getLongPressTimeout(@Suppress("unused_parameter") call: MethodCall, result: MethodChannel.Result) {
+ result.success(ViewConfiguration.getLongPressTimeout())
+ }
+
private fun hasRecommendedTimeouts(@Suppress("unused_parameter") call: MethodCall, result: MethodChannel.Result) {
result.success(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
}
diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/channel/streams/SettingsChangeStreamHandler.kt b/android/app/src/main/kotlin/deckers/thibault/aves/channel/streams/SettingsChangeStreamHandler.kt
index 915f900c5..09ed1451f 100644
--- a/android/app/src/main/kotlin/deckers/thibault/aves/channel/streams/SettingsChangeStreamHandler.kt
+++ b/android/app/src/main/kotlin/deckers/thibault/aves/channel/streams/SettingsChangeStreamHandler.kt
@@ -7,6 +7,7 @@ import android.os.Handler
import android.os.Looper
import android.provider.Settings
import android.util.Log
+import android.view.ViewConfiguration
import deckers.thibault.aves.model.FieldMap
import deckers.thibault.aves.utils.LogUtils
import io.flutter.plugin.common.EventChannel
@@ -21,6 +22,7 @@ class SettingsChangeStreamHandler(private val context: Context) : EventChannel.S
private val contentObserver = object : ContentObserver(null) {
private var accelerometerRotation: Int = 0
private var transitionAnimationScale: Float = 1f
+ private var longPressTimeoutMillis: Int = 0
init {
update()
@@ -36,6 +38,7 @@ class SettingsChangeStreamHandler(private val context: Context) : EventChannel.S
hashMapOf(
Settings.System.ACCELEROMETER_ROTATION to accelerometerRotation,
Settings.Global.TRANSITION_ANIMATION_SCALE to transitionAnimationScale,
+ KEY_LONG_PRESS_TIMEOUT_MILLIS to longPressTimeoutMillis,
)
)
}
@@ -54,6 +57,11 @@ class SettingsChangeStreamHandler(private val context: Context) : EventChannel.S
transitionAnimationScale = newTransitionAnimationScale
changed = true
}
+ val newLongPressTimeout = ViewConfiguration.getLongPressTimeout()
+ if (longPressTimeoutMillis != newLongPressTimeout) {
+ longPressTimeoutMillis = newLongPressTimeout
+ changed = true
+ }
} catch (e: Exception) {
Log.w(LOG_TAG, "failed to get settings with error=${e.message}", null)
}
@@ -93,5 +101,8 @@ class SettingsChangeStreamHandler(private val context: Context) : EventChannel.S
companion object {
private val LOG_TAG = LogUtils.createTag()
const val CHANNEL = "deckers.thibault/aves/settings_change"
+
+ // cf `Settings.Secure.LONG_PRESS_TIMEOUT`
+ const val KEY_LONG_PRESS_TIMEOUT_MILLIS = "long_press_timeout"
}
}
\ No newline at end of file
diff --git a/android/app/src/main/res/values-ja/strings.xml b/android/app/src/main/res/values-ja/strings.xml
index 78d3fec7d..1e2a114ed 100644
--- a/android/app/src/main/res/values-ja/strings.xml
+++ b/android/app/src/main/res/values-ja/strings.xml
@@ -8,4 +8,5 @@
メディアスキャン
メディアをスキャン中
停止
+ マップ
\ No newline at end of file
diff --git a/fastlane/metadata/android/en-US/changelogs/142.txt b/fastlane/metadata/android/en-US/changelogs/142.txt
new file mode 100644
index 000000000..d061c30ac
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/142.txt
@@ -0,0 +1,3 @@
+In v1.12.2:
+- enjoy the app in Danish
+Full changelog available on GitHub
\ No newline at end of file
diff --git a/fastlane/metadata/android/en-US/changelogs/14201.txt b/fastlane/metadata/android/en-US/changelogs/14201.txt
new file mode 100644
index 000000000..d061c30ac
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/14201.txt
@@ -0,0 +1,3 @@
+In v1.12.2:
+- enjoy the app in Danish
+Full changelog available on GitHub
\ No newline at end of file
diff --git a/lib/l10n/app_cs.arb b/lib/l10n/app_cs.arb
index 7d2ae8a5a..f4774dc87 100644
--- a/lib/l10n/app_cs.arb
+++ b/lib/l10n/app_cs.arb
@@ -1516,5 +1516,53 @@
"chipActionShowCollection": "Zobrazit ve sbírce",
"@chipActionShowCollection": {},
"mapAttributionOsmData": "Mapová data © [OpenStreetMap](https://www.openstreetmap.org/copyright) přispěvatelé",
- "@mapAttributionOsmData": {}
+ "@mapAttributionOsmData": {},
+ "videoActionShowNextFrame": "Zobrazit další snímek",
+ "@videoActionShowNextFrame": {},
+ "newAlbumDialogAlbumAlreadyExistsHelper": "Album již existuje",
+ "@newAlbumDialogAlbumAlreadyExistsHelper": {},
+ "renameProcessorHash": "Hash",
+ "@renameProcessorHash": {},
+ "albumTierDynamic": "Dynamické",
+ "@albumTierDynamic": {},
+ "collectionActionAddDynamicAlbum": "Přidat dynamické album",
+ "@collectionActionAddDynamicAlbum": {},
+ "sortOrderShortestFirst": "Nejkratší první",
+ "@sortOrderShortestFirst": {},
+ "sortOrderLongestFirst": "Nejdelší první",
+ "@sortOrderLongestFirst": {},
+ "mapAttributionOpenTopoMap": "[SRTM](https://www.earthdata.nasa.gov/sensors/srtm) | Dlaždice z [OpenTopoMap](https://opentopomap.org/), [CC BY-SA](https://creativecommons.org/licenses/by-sa/3.0/)",
+ "@mapAttributionOpenTopoMap": {},
+ "collectionActionSetHome": "Nastavit jako domov",
+ "@collectionActionSetHome": {},
+ "chipActionRemove": "Odstranit",
+ "@chipActionRemove": {},
+ "videoActionShowPreviousFrame": "Zobrazit předchozí snímek",
+ "@videoActionShowPreviousFrame": {},
+ "dynamicAlbumAlreadyExists": "Dynamické album již existuje",
+ "@dynamicAlbumAlreadyExists": {},
+ "newDynamicAlbumDialogTitle": "Nové dynamické album",
+ "@newDynamicAlbumDialogTitle": {},
+ "selectStorageVolumeDialogTitle": "Vybrat úložiště",
+ "@selectStorageVolumeDialogTitle": {},
+ "explorerActionSelectStorageVolume": "Vyberte úložiště",
+ "@explorerActionSelectStorageVolume": {},
+ "mapStyleOsmLiberty": "OSM Liberty",
+ "@mapStyleOsmLiberty": {},
+ "mapAttributionOsmLiberty": "Dlaždice z [OpenMapTiles](https://www.openmaptiles.org/), [CC BY](http://creativecommons.org/licenses/by/4.0) • Hostované na [OSM Americana](https://tile.ourmap.us)",
+ "@mapAttributionOsmLiberty": {},
+ "setHomeCustom": "Vlastní",
+ "@setHomeCustom": {},
+ "sortByDuration": "Podle trvání",
+ "@sortByDuration": {},
+ "chipActionGoToExplorerPage": "Zobrazit v průzkumníku",
+ "@chipActionGoToExplorerPage": {},
+ "explorerPageTitle": "Průzkumník",
+ "@explorerPageTitle": {},
+ "chipActionDecompose": "Rozdělit",
+ "@chipActionDecompose": {},
+ "appExportDynamicAlbums": "Dynamická alba",
+ "@appExportDynamicAlbums": {},
+ "mapStyleOpenTopoMap": "OpenTopoMap",
+ "@mapStyleOpenTopoMap": {}
}
diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb
index 7ab3fc430..2cced4ee7 100644
--- a/lib/l10n/app_en.arb
+++ b/lib/l10n/app_en.arb
@@ -210,6 +210,7 @@
"albumTierRegular": "Others",
"coordinateFormatDms": "DMS",
+ "coordinateFormatDdm": "DDM",
"coordinateFormatDecimal": "Decimal degrees",
"coordinateDms": "{coordinate} {direction}",
"@coordinateDms": {
diff --git a/lib/l10n/app_ja.arb b/lib/l10n/app_ja.arb
index 38065cee7..1ff00fcfa 100644
--- a/lib/l10n/app_ja.arb
+++ b/lib/l10n/app_ja.arb
@@ -1155,7 +1155,7 @@
"@vaultDialogLockModeWhenScreenOff": {},
"newVaultDialogTitle": "新しい保管庫",
"@newVaultDialogTitle": {},
- "authenticateToConfigureVault": "保管庫を設定するための認証",
+ "authenticateToConfigureVault": "認証して保管庫を設定",
"@authenticateToConfigureVault": {},
"vaultDialogLockTypeLabel": "ロックの種類",
"@vaultDialogLockTypeLabel": {},
@@ -1167,7 +1167,7 @@
"@pinDialogConfirm": {},
"passwordDialogEnter": "パスワードを入力",
"@passwordDialogEnter": {},
- "authenticateToUnlockVault": "認証して保管庫のロックを解除する",
+ "authenticateToUnlockVault": "認証して保管庫を解除",
"@authenticateToUnlockVault": {},
"passwordDialogConfirm": "パスワードの確認",
"@passwordDialogConfirm": {},
@@ -1360,5 +1360,41 @@
"filterLocatedLabel": "位置情報あり",
"@filterLocatedLabel": {},
"mapAttributionOsmData": "地図データ © [OpenStreetMap](https://www.openstreetmap.org/copyright) contributors",
- "@mapAttributionOsmData": {}
+ "@mapAttributionOsmData": {},
+ "sortByDuration": "期間順",
+ "@sortByDuration": {},
+ "explorerActionSelectStorageVolume": "ストレージを選択",
+ "@explorerActionSelectStorageVolume": {},
+ "newAlbumDialogAlbumAlreadyExistsHelper": "アルバムはすでに存在します",
+ "@newAlbumDialogAlbumAlreadyExistsHelper": {},
+ "videoActionShowPreviousFrame": "前のフレームを表示",
+ "@videoActionShowPreviousFrame": {},
+ "videoActionShowNextFrame": "次のフレームを表示",
+ "@videoActionShowNextFrame": {},
+ "albumTierDynamic": "ダイナミック",
+ "@albumTierDynamic": {},
+ "dynamicAlbumAlreadyExists": "ダイナミックアルバムはすでに存在します",
+ "@dynamicAlbumAlreadyExists": {},
+ "stateEmpty": "州なし",
+ "@stateEmpty": {},
+ "appExportDynamicAlbums": "ダイナミックアルバム",
+ "@appExportDynamicAlbums": {},
+ "chipActionRemove": "削除",
+ "@chipActionRemove": {},
+ "newDynamicAlbumDialogTitle": "新規ダイナミックアルバム",
+ "@newDynamicAlbumDialogTitle": {},
+ "setHomeCustom": "カスタム",
+ "@setHomeCustom": {},
+ "mapStyleOsmLiberty": "OSM Liberty",
+ "@mapStyleOsmLiberty": {},
+ "mapStyleOpenTopoMap": "OpenTopoMap",
+ "@mapStyleOpenTopoMap": {},
+ "selectStorageVolumeDialogTitle": "ストレージを選択",
+ "@selectStorageVolumeDialogTitle": {},
+ "sortOrderShortestFirst": "短いものから表示",
+ "@sortOrderShortestFirst": {},
+ "sortOrderLongestFirst": "長いものから表示",
+ "@sortOrderLongestFirst": {},
+ "collectionActionAddDynamicAlbum": "ダイナミックアルバムを追加",
+ "@collectionActionAddDynamicAlbum": {}
}
diff --git a/lib/l10n/app_sk.arb b/lib/l10n/app_sk.arb
index a85964f7f..d6d3864cc 100644
--- a/lib/l10n/app_sk.arb
+++ b/lib/l10n/app_sk.arb
@@ -1562,5 +1562,7 @@
"newDynamicAlbumDialogTitle": "Nový dynamický album",
"@newDynamicAlbumDialogTitle": {},
"dynamicAlbumAlreadyExists": "Dynamický album už existuje",
- "@dynamicAlbumAlreadyExists": {}
+ "@dynamicAlbumAlreadyExists": {},
+ "chipActionDecompose": "Rozdeliť",
+ "@chipActionDecompose": {}
}
diff --git a/lib/model/app/dependencies.dart b/lib/model/app/dependencies.dart
index d09b2b933..5171e7fbb 100644
--- a/lib/model/app/dependencies.dart
+++ b/lib/model/app/dependencies.dart
@@ -73,11 +73,6 @@ class Dependencies {
licenseUrl: 'https://github.com/material-foundation/flutter-packages/blob/main/packages/dynamic_color/LICENSE',
sourceUrl: 'https://github.com/material-foundation/flutter-packages/tree/main/packages/dynamic_color',
),
- Dependency(
- name: 'FFmpegKit (Aves fork)',
- license: lgpl3,
- sourceUrl: 'https://github.com/deckerst/ffmpeg-kit',
- ),
Dependency(
name: 'Floating',
license: mit,
diff --git a/lib/model/entry/entry.dart b/lib/model/entry/entry.dart
index 0a3f6ab98..d5698a903 100644
--- a/lib/model/entry/entry.dart
+++ b/lib/model/entry/entry.dart
@@ -232,6 +232,7 @@ class AvesEntry with AvesEntryBase {
// the MIME type reported by the Media Store is unreliable
// so we use the one found during cataloguing if possible
+ @override
String get mimeType => _catalogMetadata?.mimeType ?? sourceMimeType;
bool get isCatalogued => _catalogMetadata != null;
diff --git a/lib/model/entry/extensions/info.dart b/lib/model/entry/extensions/info.dart
index 7353a0726..81fc0bf3e 100644
--- a/lib/model/entry/extensions/info.dart
+++ b/lib/model/entry/extensions/info.dart
@@ -9,6 +9,7 @@ import 'package:aves/ref/mime_types.dart';
import 'package:aves/services/common/services.dart';
import 'package:aves/services/metadata/svg_metadata_service.dart';
import 'package:aves/theme/colors.dart';
+import 'package:aves/theme/format.dart';
import 'package:aves/theme/text.dart';
import 'package:aves/widgets/viewer/info/metadata/metadata_dir.dart';
import 'package:aves_model/aves_model.dart';
@@ -82,6 +83,21 @@ extension ExtraAvesEntryInfo on AvesEntry {
directories.add(MetadataDirectory(MetadataDirectory.mediaDirectory, _toSortedTags(formattedMediaTags)));
}
+ if (mediaInfo.containsKey(Keys.chapters)) {
+ final allChapters = (mediaInfo.remove(Keys.chapters) as List).cast