diff --git a/.flutter b/.flutter
index 9e1c85788..78666c8dc 160000
--- a/.flutter
+++ b/.flutter
@@ -1 +1 @@
-Subproject commit 9e1c857886f07d342cf106f2cd588bcd5e031bb2
+Subproject commit 78666c8dc57e9f7548ca9f8dd0740fbf0c658dc9
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9b6c75139..71011bf79 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,19 @@ All notable changes to this project will be documented in this file.
## [Unreleased]
+## [v1.10.1] - 2023-12-21
+
+- Cataloguing: detect/filter `Ultra HDR`
+- Viewer: show JPEG MPF dependent images (except thumbnails and HDR gain maps)
+- Info: show metadata from JPEG MPF
+- Info: open images embedded via JPEG MPF
+- Arabic translation (thanks Mohamed Zeroug)
+- Belarusian translation (thanks Макар Разин)
+
+### Changed
+
+- upgraded Flutter to stable v3.16.5
+
## [v1.10.0] - 2023-12-02
### Added
diff --git a/android/app/build.gradle b/android/app/build.gradle
index 797d29e5a..1ff9698d7 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -214,7 +214,7 @@ dependencies {
implementation "androidx.appcompat:appcompat:1.6.1"
implementation 'androidx.core:core-ktx:1.12.0'
- implementation 'androidx.exifinterface:exifinterface:1.3.6'
+ implementation 'androidx.exifinterface:exifinterface:1.3.7'
implementation 'androidx.lifecycle:lifecycle-process:2.6.2'
implementation 'androidx.media:media:1.7.0'
implementation 'androidx.multidex:multidex:2.0.1'
@@ -225,6 +225,7 @@ dependencies {
implementation 'com.commonsware.cwac:document:0.5.0'
implementation 'com.drewnoakes:metadata-extractor:2.19.0'
implementation "com.github.bumptech.glide:glide:$glide_version"
+ implementation 'com.google.android.material:material:1.11.0'
// SLF4J implementation for `mp4parser`
implementation 'org.slf4j:slf4j-simple:2.0.9'
@@ -242,7 +243,7 @@ dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter-engine:5.10.1'
- kapt 'androidx.annotation:annotation:1.7.0'
+ kapt 'androidx.annotation:annotation:1.7.1'
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 140a47077..c9fa9370a 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -7,6 +7,9 @@
+
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 a6843a95a..ccc38f8b1 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
@@ -9,6 +9,7 @@ import android.os.Build
import android.provider.MediaStore
import android.provider.Settings
import androidx.core.content.pm.ShortcutManagerCompat
+import com.google.android.material.color.DynamicColors
import deckers.thibault.aves.channel.calls.Coresult.Companion.safe
import deckers.thibault.aves.model.FieldMap
import io.flutter.plugin.common.MethodCall
@@ -18,7 +19,8 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.launch
-import java.util.*
+import java.util.Locale
+import java.util.TimeZone
class DeviceHandler(private val context: Context) : MethodCallHandler {
private val defaultScope = CoroutineScope(SupervisorJob() + Dispatchers.Default)
@@ -52,7 +54,7 @@ class DeviceHandler(private val context: Context) : MethodCallHandler {
"canSetLockScreenWallpaper" to (sdkInt >= Build.VERSION_CODES.N),
"canUseCrypto" to (sdkInt >= Build.VERSION_CODES.LOLLIPOP),
"hasGeocoder" to Geocoder.isPresent(),
- "isDynamicColorAvailable" to (sdkInt >= Build.VERSION_CODES.S),
+ "isDynamicColorAvailable" to DynamicColors.isDynamicColorAvailable(),
"showPinShortcutFeedback" to (sdkInt >= Build.VERSION_CODES.O),
"supportEdgeToEdgeUIMode" to (sdkInt >= Build.VERSION_CODES.Q),
)
diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/EmbeddedDataHandler.kt b/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/EmbeddedDataHandler.kt
index e956a25aa..9d34011ea 100644
--- a/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/EmbeddedDataHandler.kt
+++ b/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/EmbeddedDataHandler.kt
@@ -11,21 +11,28 @@ import com.bumptech.glide.load.resource.bitmap.TransformationUtils
import com.drew.metadata.xmp.XmpDirectory
import deckers.thibault.aves.channel.calls.Coresult.Companion.safe
import deckers.thibault.aves.channel.calls.Coresult.Companion.safeSuspend
-import deckers.thibault.aves.metadata.*
+import deckers.thibault.aves.metadata.GoogleDeviceContainer
+import deckers.thibault.aves.metadata.Metadata
+import deckers.thibault.aves.metadata.MultiPage
+import deckers.thibault.aves.metadata.XMP
import deckers.thibault.aves.metadata.XMP.doesPropPathExist
import deckers.thibault.aves.metadata.XMP.getSafeStructField
+import deckers.thibault.aves.metadata.XMPPropName
import deckers.thibault.aves.metadata.metadataextractor.Helper
import deckers.thibault.aves.model.FieldMap
-import deckers.thibault.aves.model.provider.ContentImageProvider
import deckers.thibault.aves.model.provider.ImageProvider
-import deckers.thibault.aves.utils.*
+import deckers.thibault.aves.model.provider.ImageProviderFactory.getProvider
+import deckers.thibault.aves.utils.BitmapUtils
import deckers.thibault.aves.utils.BitmapUtils.getBytes
import deckers.thibault.aves.utils.FileUtils.transferFrom
+import deckers.thibault.aves.utils.LogUtils
+import deckers.thibault.aves.utils.MimeTypes
import deckers.thibault.aves.utils.MimeTypes.canReadWithExifInterface
import deckers.thibault.aves.utils.MimeTypes.canReadWithMetadataExtractor
import deckers.thibault.aves.utils.MimeTypes.extensionFor
import deckers.thibault.aves.utils.MimeTypes.isImage
import deckers.thibault.aves.utils.MimeTypes.isVideo
+import deckers.thibault.aves.utils.StorageUtils
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
@@ -42,6 +49,7 @@ class EmbeddedDataHandler(private val context: Context) : MethodCallHandler {
when (call.method) {
"getExifThumbnails" -> ioScope.launch { safeSuspend(call, result, ::getExifThumbnails) }
"extractGoogleDeviceItem" -> ioScope.launch { safe(call, result, ::extractGoogleDeviceItem) }
+ "extractJpegMpfItem" -> ioScope.launch { safe(call, result, ::extractJpegMpfItem) }
"extractMotionPhotoImage" -> ioScope.launch { safe(call, result, ::extractMotionPhotoImage) }
"extractMotionPhotoVideo" -> ioScope.launch { safe(call, result, ::extractMotionPhotoVideo) }
"extractVideoEmbeddedPicture" -> ioScope.launch { safe(call, result, ::extractVideoEmbeddedPicture) }
@@ -141,6 +149,40 @@ class EmbeddedDataHandler(private val context: Context) : MethodCallHandler {
result.error("extractGoogleDeviceItem-empty", "failed to extract item from Google Device XMP at uri=$uri dataUri=$dataUri", null)
}
+ private fun extractJpegMpfItem(call: MethodCall, result: MethodChannel.Result) {
+ val mimeType = call.argument("mimeType")
+ val uri = call.argument("uri")?.let { Uri.parse(it) }
+ val sizeBytes = call.argument("sizeBytes")?.toLong()
+ val displayName = call.argument("displayName")
+ val id = call.argument("id")
+ if (mimeType == null || uri == null || sizeBytes == null || id == null) {
+ result.error("extractJpegMpfItem-args", "missing arguments", null)
+ return
+ }
+
+ val pageIndex = id - 1
+ val mpEntries = MultiPage.getJpegMpfEntries(context, uri)
+ if (mpEntries != null && pageIndex < mpEntries.size) {
+ val mpEntry = mpEntries[pageIndex]
+ mpEntry.mimeType?.let { embedMimeType ->
+ var dataOffset = mpEntry.dataOffset
+ if (dataOffset > 0) {
+ val baseOffset = MultiPage.getJpegMpfBaseOffset(context, uri)
+ if (baseOffset != null) {
+ dataOffset += baseOffset
+ }
+ }
+ StorageUtils.openInputStream(context, uri)?.let { input ->
+ input.skip(dataOffset)
+ copyEmbeddedBytes(result, embedMimeType, displayName, input, mpEntry.size)
+ }
+ return
+ }
+ }
+
+ result.error("extractJpegMpfItem-empty", "failed to extract file index=$id from MPF at uri=$uri", null)
+ }
+
private fun extractMotionPhotoImage(call: MethodCall, result: MethodChannel.Result) {
val mimeType = call.argument("mimeType")
val uri = call.argument("uri")?.let { Uri.parse(it) }
@@ -299,8 +341,14 @@ class EmbeddedDataHandler(private val context: Context) : MethodCallHandler {
"mimeType" to mimeType,
)
if (isImage(mimeType) || isVideo(mimeType)) {
+ val provider = getProvider(context, uri)
+ if (provider == null) {
+ result.error("copyEmbeddedBytes-provider", "failed to find provider for uri=$uri", null)
+ return
+ }
+
ioScope.launch {
- ContentImageProvider().fetchSingle(context, uri, mimeType, object : ImageProvider.ImageOpCallback {
+ provider.fetchSingle(context, uri, mimeType, object : ImageProvider.ImageOpCallback {
override fun onSuccess(fields: FieldMap) {
resultFields.putAll(fields)
result.success(resultFields)
diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/MediaEditHandler.kt b/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/MediaEditHandler.kt
index 533a078b4..9e40b4199 100644
--- a/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/MediaEditHandler.kt
+++ b/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/MediaEditHandler.kt
@@ -55,7 +55,7 @@ class MediaEditHandler(private val contextWrapper: ContextWrapper) : MethodCallH
return
}
- val provider = getProvider(uri)
+ val provider = getProvider(contextWrapper, uri)
if (provider == null) {
result.error("captureFrame-provider", "failed to find provider for uri=$uri", null)
return
diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/MediaFetchObjectHandler.kt b/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/MediaFetchObjectHandler.kt
index 665d17a17..d0d317c2a 100644
--- a/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/MediaFetchObjectHandler.kt
+++ b/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/MediaFetchObjectHandler.kt
@@ -34,7 +34,7 @@ class MediaFetchObjectHandler(private val context: Context) : MethodCallHandler
return
}
- val provider = getProvider(uri)
+ val provider = getProvider(context, uri)
if (provider == null) {
result.error("getEntry-provider", "failed to find provider for uri=$uri", null)
return
diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/MetadataEditHandler.kt b/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/MetadataEditHandler.kt
index f8915a8f6..9d1704b27 100644
--- a/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/MetadataEditHandler.kt
+++ b/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/MetadataEditHandler.kt
@@ -62,7 +62,7 @@ class MetadataEditHandler(private val contextWrapper: ContextWrapper) : MethodCa
return
}
- val provider = getProvider(uri)
+ val provider = getProvider(contextWrapper, uri)
if (provider == null) {
result.error("editOrientation-provider", "failed to find provider for uri=$uri", null)
return
@@ -90,7 +90,7 @@ class MetadataEditHandler(private val contextWrapper: ContextWrapper) : MethodCa
return
}
- val provider = getProvider(uri)
+ val provider = getProvider(contextWrapper, uri)
if (provider == null) {
result.error("editDate-provider", "failed to find provider for uri=$uri", null)
return
@@ -117,7 +117,7 @@ class MetadataEditHandler(private val contextWrapper: ContextWrapper) : MethodCa
return
}
- val provider = getProvider(uri)
+ val provider = getProvider(contextWrapper, uri)
if (provider == null) {
result.error("editMetadata-provider", "failed to find provider for uri=$uri", null)
return
@@ -142,7 +142,7 @@ class MetadataEditHandler(private val contextWrapper: ContextWrapper) : MethodCa
return
}
- val provider = getProvider(uri)
+ val provider = getProvider(contextWrapper, uri)
if (provider == null) {
result.error("removeTrailerVideo-provider", "failed to find provider for uri=$uri", null)
return
@@ -168,7 +168,7 @@ class MetadataEditHandler(private val contextWrapper: ContextWrapper) : MethodCa
return
}
- val provider = getProvider(uri)
+ val provider = getProvider(contextWrapper, uri)
if (provider == null) {
result.error("removeTypes-provider", "failed to find provider for uri=$uri", null)
return
diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/MetadataFetchHandler.kt b/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/MetadataFetchHandler.kt
index e04dc7241..b86b2d636 100644
--- a/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/MetadataFetchHandler.kt
+++ b/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/MetadataFetchHandler.kt
@@ -57,6 +57,7 @@ import deckers.thibault.aves.metadata.XMP.getSafeDateMillis
import deckers.thibault.aves.metadata.XMP.getSafeInt
import deckers.thibault.aves.metadata.XMP.getSafeLocalizedText
import deckers.thibault.aves.metadata.XMP.getSafeString
+import deckers.thibault.aves.metadata.XMP.hasHdrGainMap
import deckers.thibault.aves.metadata.XMP.isMotionPhoto
import deckers.thibault.aves.metadata.XMP.isPanorama
import deckers.thibault.aves.metadata.metadataextractor.Helper
@@ -76,6 +77,7 @@ import deckers.thibault.aves.metadata.metadataextractor.Helper.getSafeRational
import deckers.thibault.aves.metadata.metadataextractor.Helper.getSafeString
import deckers.thibault.aves.metadata.metadataextractor.Helper.isPngTextDir
import deckers.thibault.aves.metadata.metadataextractor.PngActlDirectory
+import deckers.thibault.aves.metadata.metadataextractor.mpf.MpEntryDirectory
import deckers.thibault.aves.model.FieldMap
import deckers.thibault.aves.utils.ContextUtils.queryContentPropValue
import deckers.thibault.aves.utils.LogUtils
@@ -225,7 +227,7 @@ class MetadataFetchHandler(private val context: Context) : MethodCallHandler {
foundMp4Uuid = metadata.directories.any { it is Mp4UuidBoxDirectory && it.tagCount > 0 }
val dirByName = metadata.directories.filter {
- (it.tagCount > 0 || it.errorCount > 0)
+ (it.tagCount > 0 || it.errorCount > 0 || it is MpEntryDirectory)
&& it !is FileTypeDirectory
&& it !is AviDirectory
}.groupBy { dir -> dir.name }
@@ -344,6 +346,10 @@ class MetadataFetchHandler(private val context: Context) : MethodCallHandler {
}
}
+ dir is MpEntryDirectory -> {
+ dirMap.putAll(dir.describe())
+ }
+
else -> dirMap.putAll(tags.map { Pair(it.tagName, it.description) })
}
}
@@ -551,6 +557,11 @@ class MetadataFetchHandler(private val context: Context) : MethodCallHandler {
if (xmpMeta.isMotionPhoto()) {
flags = flags or MASK_IS_MULTIPAGE or MASK_IS_MOTION_PHOTO
}
+
+ // identification of embedded gain map
+ if (xmpMeta.hasHdrGainMap()) {
+ flags = flags or MASK_HAS_HDR_GAIN_MAP
+ }
} catch (e: XMPException) {
Log.w(LOG_TAG, "failed to read XMP directory for uri=$uri", e)
}
@@ -623,6 +634,11 @@ class MetadataFetchHandler(private val context: Context) : MethodCallHandler {
}
}
+ // JPEG Multi-Picture Format
+ if (metadata.getDirectoriesOfType(MpEntryDirectory::class.java).count { !it.entry.isThumbnail } > 1) {
+ flags = flags or MASK_IS_MULTIPAGE
+ }
+
// XMP
if (!isLargeMp4(mimeType, sizeBytes)) {
metadata.getDirectoriesOfType(XmpDirectory::class.java).map { it.xmpMeta }.forEach {
@@ -913,10 +929,11 @@ class MetadataFetchHandler(private val context: Context) : MethodCallHandler {
}
val pages: ArrayList? = if (isMotionPhoto) {
- MultiPage.getMotionPhotoPages(context, uri, mimeType, sizeBytes = sizeBytes)
+ MultiPage.getMotionPhotoPages(context, uri, mimeType, sizeBytes)
} else {
when (mimeType) {
MimeTypes.HEIC, MimeTypes.HEIF -> MultiPage.getHeicTracks(context, uri)
+ MimeTypes.JPEG -> MultiPage.getJpegMpfPages(context, uri)
MimeTypes.TIFF -> MultiPage.getTiffPages(context, uri)
else -> null
}
@@ -1297,6 +1314,7 @@ class MetadataFetchHandler(private val context: Context) : MethodCallHandler {
private const val MASK_IS_360 = 1 shl 3
private const val MASK_IS_MULTIPAGE = 1 shl 4
private const val MASK_IS_MOTION_PHOTO = 1 shl 5
+ private const val MASK_HAS_HDR_GAIN_MAP = 1 shl 6
private const val XMP_SUBJECTS_SEPARATOR = ";"
// overlay metadata
diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/fetchers/RegionFetcher.kt b/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/fetchers/RegionFetcher.kt
index 65a3af050..b3efb8a3c 100644
--- a/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/fetchers/RegionFetcher.kt
+++ b/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/fetchers/RegionFetcher.kt
@@ -10,7 +10,7 @@ import com.bumptech.glide.Glide
import com.bumptech.glide.load.DecodeFormat
import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.bumptech.glide.request.RequestOptions
-import deckers.thibault.aves.decoder.MultiTrackImage
+import deckers.thibault.aves.decoder.MultiPageImage
import deckers.thibault.aves.utils.BitmapRegionDecoderCompat
import deckers.thibault.aves.utils.BitmapUtils.getBytes
import deckers.thibault.aves.utils.MimeTypes
@@ -40,10 +40,10 @@ class RegionFetcher internal constructor(
imageHeight: Int,
result: MethodChannel.Result,
) {
- if (MimeTypes.isHeic(mimeType) && pageId != null) {
+ if (pageId != null && MultiPageImage.isSupported(mimeType)) {
val id = Pair(uri, pageId)
fetch(
- uri = pageTempUris.getOrPut(id) { createJpegForPage(uri, pageId) },
+ uri = pageTempUris.getOrPut(id) { createJpegForPage(uri, mimeType, pageId) },
mimeType = MimeTypes.JPEG,
pageId = null,
sampleSize = sampleSize,
@@ -104,11 +104,11 @@ class RegionFetcher internal constructor(
}
}
- private fun createJpegForPage(sourceUri: Uri, pageId: Int): Uri {
+ private fun createJpegForPage(sourceUri: Uri, mimeType: String, pageId: Int): Uri {
val target = Glide.with(context)
.asBitmap()
.apply(multiTrackGlideOptions)
- .load(MultiTrackImage(context, sourceUri, pageId))
+ .load(MultiPageImage(context, sourceUri, mimeType, pageId))
.submit()
try {
val bitmap = target.get()
diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/fetchers/ThumbnailFetcher.kt b/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/fetchers/ThumbnailFetcher.kt
index 752633094..98e44e135 100644
--- a/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/fetchers/ThumbnailFetcher.kt
+++ b/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/fetchers/ThumbnailFetcher.kt
@@ -12,7 +12,7 @@ import com.bumptech.glide.load.DecodeFormat
import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.bumptech.glide.request.RequestOptions
import com.bumptech.glide.signature.ObjectKey
-import deckers.thibault.aves.decoder.MultiTrackImage
+import deckers.thibault.aves.decoder.MultiPageImage
import deckers.thibault.aves.decoder.SvgImage
import deckers.thibault.aves.decoder.TiffImage
import deckers.thibault.aves.decoder.VideoThumbnail
@@ -20,7 +20,6 @@ import deckers.thibault.aves.utils.BitmapUtils.applyExifOrientation
import deckers.thibault.aves.utils.BitmapUtils.getBytes
import deckers.thibault.aves.utils.MimeTypes
import deckers.thibault.aves.utils.MimeTypes.SVG
-import deckers.thibault.aves.utils.MimeTypes.isHeic
import deckers.thibault.aves.utils.MimeTypes.isVideo
import deckers.thibault.aves.utils.MimeTypes.needRotationAfterContentResolverThumbnail
import deckers.thibault.aves.utils.MimeTypes.needRotationAfterGlide
@@ -47,8 +46,8 @@ class ThumbnailFetcher internal constructor(
private val height: Int = if (height?.takeIf { it > 0 } != null) height else defaultSize
private val svgFetch = mimeType == SVG
private val tiffFetch = mimeType == MimeTypes.TIFF
- private val multiTrackFetch = isHeic(mimeType) && pageId != null
- private val customFetch = svgFetch || tiffFetch || multiTrackFetch
+ private val multiPageFetch = pageId != null && MultiPageImage.isSupported(mimeType)
+ private val customFetch = svgFetch || tiffFetch || multiPageFetch
suspend fun fetch() {
var bitmap: Bitmap? = null
@@ -135,7 +134,7 @@ class ThumbnailFetcher internal constructor(
val model: Any = when {
svgFetch -> SvgImage(context, uri)
tiffFetch -> TiffImage(context, uri, pageId)
- multiTrackFetch -> MultiTrackImage(context, uri, pageId)
+ multiPageFetch -> MultiPageImage(context, uri, mimeType, pageId)
else -> StorageUtils.getGlideSafeUri(context, uri, mimeType)
}
Glide.with(context)
diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/channel/streams/ImageByteStreamHandler.kt b/android/app/src/main/kotlin/deckers/thibault/aves/channel/streams/ImageByteStreamHandler.kt
index 56e40cc9d..54fc04f9d 100644
--- a/android/app/src/main/kotlin/deckers/thibault/aves/channel/streams/ImageByteStreamHandler.kt
+++ b/android/app/src/main/kotlin/deckers/thibault/aves/channel/streams/ImageByteStreamHandler.kt
@@ -9,7 +9,7 @@ import com.bumptech.glide.Glide
import com.bumptech.glide.load.DecodeFormat
import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.bumptech.glide.request.RequestOptions
-import deckers.thibault.aves.decoder.MultiTrackImage
+import deckers.thibault.aves.decoder.MultiPageImage
import deckers.thibault.aves.decoder.TiffImage
import deckers.thibault.aves.decoder.VideoThumbnail
import deckers.thibault.aves.utils.BitmapUtils.applyExifOrientation
@@ -18,7 +18,6 @@ import deckers.thibault.aves.utils.LogUtils
import deckers.thibault.aves.utils.MemoryUtils
import deckers.thibault.aves.utils.MimeTypes
import deckers.thibault.aves.utils.MimeTypes.canDecodeWithFlutter
-import deckers.thibault.aves.utils.MimeTypes.isHeic
import deckers.thibault.aves.utils.MimeTypes.isVideo
import deckers.thibault.aves.utils.MimeTypes.needRotationAfterGlide
import deckers.thibault.aves.utils.StorageUtils
@@ -100,7 +99,7 @@ class ImageByteStreamHandler(private val context: Context, private val arguments
if (isVideo(mimeType)) {
streamVideoByGlide(uri, mimeType, sizeBytes)
- } else if (!canDecodeWithFlutter(mimeType, rotationDegrees, isFlipped)) {
+ } else if (!canDecodeWithFlutter(mimeType, pageId, rotationDegrees, isFlipped)) {
// decode exotic format on platform side, then encode it in portable format for Flutter
streamImageByGlide(uri, pageId, mimeType, sizeBytes, rotationDegrees, isFlipped)
} else {
@@ -131,8 +130,8 @@ class ImageByteStreamHandler(private val context: Context, private val arguments
rotationDegrees: Int,
isFlipped: Boolean,
) {
- val model: Any = if (isHeic(mimeType) && pageId != null) {
- MultiTrackImage(context, uri, pageId)
+ val model: Any = if (pageId != null && MultiPageImage.isSupported(mimeType)) {
+ MultiPageImage(context, uri, mimeType, pageId)
} else if (mimeType == MimeTypes.TIFF) {
TiffImage(context, uri, pageId)
} else {
diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/channel/streams/ImageOpStreamHandler.kt b/android/app/src/main/kotlin/deckers/thibault/aves/channel/streams/ImageOpStreamHandler.kt
index a2a31e122..c6f10000e 100644
--- a/android/app/src/main/kotlin/deckers/thibault/aves/channel/streams/ImageOpStreamHandler.kt
+++ b/android/app/src/main/kotlin/deckers/thibault/aves/channel/streams/ImageOpStreamHandler.kt
@@ -107,7 +107,7 @@ class ImageOpStreamHandler(private val activity: FragmentActivity, private val a
result["skipped"] = true
} else {
result["success"] = false
- getProvider(uri)?.let { provider ->
+ getProvider(activity, uri)?.let { provider ->
try {
provider.delete(activity, uri, path, mimeType)
result["success"] = true
@@ -142,7 +142,7 @@ class ImageOpStreamHandler(private val activity: FragmentActivity, private val a
// assume same provider for all entries
val firstEntry = entryMapList.first()
- val provider = (firstEntry["uri"] as String?)?.let { Uri.parse(it) }?.let { getProvider(it) }
+ val provider = (firstEntry["uri"] as String?)?.let { Uri.parse(it) }?.let { getProvider(activity, it) }
if (provider == null) {
error("convert-provider", "failed to find provider for entry=$firstEntry", null)
return
@@ -231,7 +231,7 @@ class ImageOpStreamHandler(private val activity: FragmentActivity, private val a
entriesToNewName[AvesEntry(rawEntry)] = newName
}
- val byProvider = entriesToNewName.entries.groupBy { kv -> getProvider(kv.key.uri) }
+ val byProvider = entriesToNewName.entries.groupBy { kv -> getProvider(activity, kv.key.uri) }
for ((provider, entryList) in byProvider) {
if (provider == null) {
error("rename-provider", "failed to find provider for entry=${entryList.firstOrNull()}", null)
diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/decoder/MultiTrackImageGlideModule.kt b/android/app/src/main/kotlin/deckers/thibault/aves/decoder/MultiPageImageGlideModule.kt
similarity index 51%
rename from android/app/src/main/kotlin/deckers/thibault/aves/decoder/MultiTrackImageGlideModule.kt
rename to android/app/src/main/kotlin/deckers/thibault/aves/decoder/MultiPageImageGlideModule.kt
index 63fe82405..c068834c1 100644
--- a/android/app/src/main/kotlin/deckers/thibault/aves/decoder/MultiTrackImageGlideModule.kt
+++ b/android/app/src/main/kotlin/deckers/thibault/aves/decoder/MultiPageImageGlideModule.kt
@@ -17,32 +17,40 @@ import com.bumptech.glide.load.model.ModelLoaderFactory
import com.bumptech.glide.load.model.MultiModelLoaderFactory
import com.bumptech.glide.module.LibraryGlideModule
import com.bumptech.glide.signature.ObjectKey
+import deckers.thibault.aves.metadata.MultiPage
import deckers.thibault.aves.metadata.MultiTrackMedia
+import deckers.thibault.aves.utils.MimeTypes
@GlideModule
-class MultiTrackImageGlideModule : LibraryGlideModule() {
+class MultiPageImageGlideModule : LibraryGlideModule() {
override fun registerComponents(context: Context, glide: Glide, registry: Registry) {
- registry.append(MultiTrackImage::class.java, Bitmap::class.java, MultiTrackThumbnailLoader.Factory())
+ registry.append(MultiPageImage::class.java, Bitmap::class.java, MultiPageThumbnailLoader.Factory())
}
}
-class MultiTrackImage(val context: Context, val uri: Uri, val trackIndex: Int?)
+class MultiPageImage(val context: Context, val uri: Uri, val mimeType: String, val pageId: Int?) {
+ override fun toString(): String = "MultiPageImage#${hashCode()}{uri=$uri, mimeType=$mimeType, pageId=$pageId}"
-internal class MultiTrackThumbnailLoader : ModelLoader {
- override fun buildLoadData(model: MultiTrackImage, width: Int, height: Int, options: Options): ModelLoader.LoadData {
- return ModelLoader.LoadData(ObjectKey(model.uri), MultiTrackImageFetcher(model, width, height))
+ companion object {
+ fun isSupported(mimeType: String) = MimeTypes.isHeic(mimeType) || mimeType == MimeTypes.JPEG
+ }
+}
+
+internal class MultiPageThumbnailLoader : ModelLoader {
+ override fun buildLoadData(model: MultiPageImage, width: Int, height: Int, options: Options): ModelLoader.LoadData {
+ return ModelLoader.LoadData(ObjectKey(model.uri), MultiPageImageFetcher(model, width, height))
}
- override fun handles(model: MultiTrackImage): Boolean = true
+ override fun handles(model: MultiPageImage): Boolean = true
- internal class Factory : ModelLoaderFactory {
- override fun build(multiFactory: MultiModelLoaderFactory): ModelLoader = MultiTrackThumbnailLoader()
+ internal class Factory : ModelLoaderFactory {
+ override fun build(multiFactory: MultiModelLoaderFactory): ModelLoader = MultiPageThumbnailLoader()
override fun teardown() {}
}
}
-internal class MultiTrackImageFetcher(val model: MultiTrackImage, val width: Int, val height: Int) : DataFetcher {
+internal class MultiPageImageFetcher(val model: MultiPageImage, val width: Int, val height: Int) : DataFetcher {
override fun loadData(priority: Priority, callback: DataCallback) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) {
callback.onLoadFailed(Exception("unsupported Android version"))
@@ -51,9 +59,17 @@ internal class MultiTrackImageFetcher(val model: MultiTrackImage, val width: Int
val context = model.context
val uri = model.uri
- val trackIndex = model.trackIndex
+ val mimeType = model.mimeType
+
+ var bitmap: Bitmap? = null
+ if (MimeTypes.isHeic(mimeType)) {
+ val trackIndex = model.pageId
+ bitmap = MultiTrackMedia.getImage(context, uri, trackIndex)
+ } else if (mimeType == MimeTypes.JPEG) {
+ val pageIndex = model.pageId ?: 0
+ bitmap = MultiPage.getJpegMpfBitmap(context, uri, pageIndex)
+ }
- val bitmap = MultiTrackMedia.getImage(context, uri, trackIndex)
if (bitmap == null) {
callback.onLoadFailed(Exception("null bitmap"))
} else {
diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/metadata/Metadata.kt b/android/app/src/main/kotlin/deckers/thibault/aves/metadata/Metadata.kt
index b82f1cf12..4553b2c4f 100644
--- a/android/app/src/main/kotlin/deckers/thibault/aves/metadata/Metadata.kt
+++ b/android/app/src/main/kotlin/deckers/thibault/aves/metadata/Metadata.kt
@@ -10,7 +10,9 @@ import java.io.File
import java.io.InputStream
import java.text.ParseException
import java.text.SimpleDateFormat
-import java.util.*
+import java.util.Date
+import java.util.Locale
+import java.util.TimeZone
import java.util.regex.Pattern
object Metadata {
diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/metadata/MultiPage.kt b/android/app/src/main/kotlin/deckers/thibault/aves/metadata/MultiPage.kt
index 53c5b472d..eab4b5954 100644
--- a/android/app/src/main/kotlin/deckers/thibault/aves/metadata/MultiPage.kt
+++ b/android/app/src/main/kotlin/deckers/thibault/aves/metadata/MultiPage.kt
@@ -1,6 +1,8 @@
package deckers.thibault.aves.metadata
import android.content.Context
+import android.graphics.Bitmap
+import android.graphics.BitmapFactory
import android.media.MediaExtractor
import android.media.MediaFormat
import android.net.Uri
@@ -8,15 +10,19 @@ import android.os.Build
import android.os.ParcelFileDescriptor
import android.util.Log
import com.adobe.internal.xmp.XMPMeta
+import com.drew.imaging.jpeg.JpegSegmentType
import com.drew.metadata.xmp.XmpDirectory
import deckers.thibault.aves.metadata.XMP.countPropArrayItems
import deckers.thibault.aves.metadata.XMP.doesPropExist
import deckers.thibault.aves.metadata.XMP.getSafeLong
import deckers.thibault.aves.metadata.XMP.getSafeStructField
import deckers.thibault.aves.metadata.metadataextractor.Helper
+import deckers.thibault.aves.metadata.metadataextractor.mpf.MpEntry
+import deckers.thibault.aves.metadata.metadataextractor.mpf.MpEntryDirectory
import deckers.thibault.aves.model.FieldMap
import deckers.thibault.aves.utils.LogUtils
import deckers.thibault.aves.utils.MimeTypes
+import deckers.thibault.aves.utils.StorageUtils
import deckers.thibault.aves.utils.indexOfBytes
import org.beyka.tiffbitmapfactory.TiffBitmapFactory
import java.io.DataInputStream
@@ -47,13 +53,13 @@ object MultiPage {
val tracks = ArrayList()
val extractor = MediaExtractor()
extractor.setDataSource(context, uri, null)
- for (i in 0 until extractor.trackCount) {
+ for (pageIndex in 0 until extractor.trackCount) {
try {
- val format = extractor.getTrackFormat(i)
+ val format = extractor.getTrackFormat(pageIndex)
format.getString(MediaFormat.KEY_MIME)?.let { mime ->
val trackMime = if (mime == MediaFormat.MIMETYPE_IMAGE_ANDROID_HEIC) MimeTypes.HEIC else mime
val track: FieldMap = hashMapOf(
- KEY_PAGE to i,
+ KEY_PAGE to pageIndex,
KEY_MIME_TYPE to trackMime,
)
@@ -72,13 +78,115 @@ object MultiPage {
tracks.add(track)
}
} catch (e: Exception) {
- Log.w(LOG_TAG, "failed to get HEIC track information for uri=$uri, track num=$i", e)
+ Log.w(LOG_TAG, "failed to get HEIC track information for uri=$uri, pageIndex=$pageIndex", e)
}
}
extractor.release()
return tracks
}
+ // starts after `[APP2 marker (1 byte)] [segment size (2 bytes)] [MPF marker (4 bytes)]`
+ fun getJpegMpfBaseOffset(context: Context, uri: Uri): Int? {
+ val app2Marker = JpegSegmentType.APP2.byteValue
+ val mpfMarker = "MPF".toByteArray() + 0x00
+
+ try {
+ Metadata.openSafeInputStream(context, uri, MimeTypes.JPEG, null)?.use { input ->
+ var offset = 0
+ while (true) {
+ do {
+ val b = input.read().toByte()
+ offset++
+ } while (b != app2Marker)
+ // skip 2 bytes for segment size
+ input.skip(2)
+ offset += 2
+ val marker = ByteArray(4)
+ input.read(marker, 0, marker.size)
+ offset += 4
+ if (marker.contentEquals(mpfMarker)) {
+ return offset
+ }
+ }
+ }
+ } catch (e: Exception) {
+ Log.w(LOG_TAG, "failed to get MPF base offset from uri=$uri", e)
+ }
+ return null
+ }
+
+ fun getJpegMpfEntries(context: Context, uri: Uri): List? {
+ try {
+ Metadata.openSafeInputStream(context, uri, MimeTypes.JPEG, null)?.use { input ->
+ val metadata = Helper.safeRead(input)
+ return metadata.getDirectoriesOfType(MpEntryDirectory::class.java).map { it.entry }
+ }
+ } catch (e: Exception) {
+ Log.w(LOG_TAG, "failed to find MPF entries", e)
+ } catch (e: NoClassDefFoundError) {
+ Log.w(LOG_TAG, "failed to find MPF entries", e)
+ } catch (e: AssertionError) {
+ Log.w(LOG_TAG, "failed to find MPF entries", e)
+ }
+ return null
+ }
+
+ fun getJpegMpfPages(context: Context, uri: Uri): ArrayList {
+ val pages = ArrayList()
+ val baseOffset = getJpegMpfBaseOffset(context, uri)
+ val mpEntries = getJpegMpfEntries(context, uri)
+ if (mpEntries != null && baseOffset != null) {
+ for ((pageIndex, mpEntry) in mpEntries.withIndex()) {
+ mpEntry.mimeType?.let { embedMimeType ->
+ val page = hashMapOf(
+ KEY_PAGE to pageIndex,
+ KEY_MIME_TYPE to embedMimeType,
+ KEY_IS_DEFAULT to (pageIndex == 0),
+ // TODO TLAD [MPF] page[KEY_ROTATION_DEGREES] = same as primary
+ KEY_ROTATION_DEGREES to 0,
+ )
+
+ var dataOffset = mpEntry.dataOffset
+ if (dataOffset > 0) {
+ dataOffset += baseOffset
+ }
+ StorageUtils.openInputStream(context, uri)?.let { input ->
+ input.skip(dataOffset)
+ val options = BitmapFactory.Options().apply {
+ inJustDecodeBounds = true
+ }
+ BitmapFactory.decodeStream(input, null, options)
+ options.outWidth.takeIf { it >= 0 }?.let { page[KEY_WIDTH] = it }
+ options.outHeight.takeIf { it >= 0 }?.let { page[KEY_HEIGHT] = it }
+
+ pages.add(page)
+ }
+ }
+ }
+ }
+
+ return pages
+ }
+
+ fun getJpegMpfBitmap(context: Context, uri: Uri, pageIndex: Int): Bitmap? {
+ val mpEntries = getJpegMpfEntries(context, uri)
+ if (mpEntries != null && pageIndex < mpEntries.size) {
+ val mpEntry = mpEntries[pageIndex]
+ var dataOffset = mpEntry.dataOffset
+ if (dataOffset > 0) {
+ val baseOffset = getJpegMpfBaseOffset(context, uri)
+ if (baseOffset != null) {
+ dataOffset += baseOffset
+ }
+ }
+ StorageUtils.openInputStream(context, uri)?.let { input ->
+ input.skip(dataOffset)
+ return BitmapFactory.decodeStream(input)
+ }
+ }
+ return null
+ }
+
fun getMotionPhotoPages(context: Context, uri: Uri, mimeType: String, sizeBytes: Long): ArrayList {
fun MediaFormat.getSafeInt(key: String, save: (value: Int) -> Unit) {
if (this.containsKey(key)) save(this.getInteger(key))
@@ -88,7 +196,7 @@ object MultiPage {
if (this.containsKey(key)) save(this.getLong(key))
}
- val tracks = ArrayList()
+ val pages = ArrayList()
val extractor = MediaExtractor()
var pfd: ParcelFileDescriptor? = null
try {
@@ -98,10 +206,10 @@ object MultiPage {
pfd?.fileDescriptor?.let { fd ->
extractor.setDataSource(fd, videoStartOffset, videoSizeBytes)
// set the original image as the first and default track
- var trackCount = 0
- tracks.add(
+ var pageIndex = 0
+ pages.add(
hashMapOf(
- KEY_PAGE to trackCount++,
+ KEY_PAGE to pageIndex++,
KEY_MIME_TYPE to mimeType,
KEY_IS_DEFAULT to true,
)
@@ -114,18 +222,18 @@ object MultiPage {
val format = extractor.getTrackFormat(trackIndex)
format.getString(MediaFormat.KEY_MIME)?.let { mime ->
if (MimeTypes.isVideo(mime)) {
- val track: FieldMap = hashMapOf(
- KEY_PAGE to trackCount++,
+ val page: FieldMap = hashMapOf(
+ KEY_PAGE to pageIndex++,
KEY_MIME_TYPE to MimeTypes.MP4,
KEY_IS_DEFAULT to false,
)
- format.getSafeInt(MediaFormat.KEY_WIDTH) { track[KEY_WIDTH] = it }
- format.getSafeInt(MediaFormat.KEY_HEIGHT) { track[KEY_HEIGHT] = it }
+ format.getSafeInt(MediaFormat.KEY_WIDTH) { page[KEY_WIDTH] = it }
+ format.getSafeInt(MediaFormat.KEY_HEIGHT) { page[KEY_HEIGHT] = it }
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
- format.getSafeInt(MediaFormat.KEY_ROTATION) { track[KEY_ROTATION_DEGREES] = it }
+ format.getSafeInt(MediaFormat.KEY_ROTATION) { page[KEY_ROTATION_DEGREES] = it }
}
- format.getSafeLong(MediaFormat.KEY_DURATION) { track[KEY_DURATION] = it / 1000 }
- tracks.add(track)
+ format.getSafeLong(MediaFormat.KEY_DURATION) { page[KEY_DURATION] = it / 1000 }
+ pages.add(page)
}
}
} catch (e: Exception) {
@@ -140,7 +248,7 @@ object MultiPage {
extractor.release()
pfd?.close()
}
- return tracks
+ return pages
}
fun getMotionPhotoOffset(context: Context, uri: Uri, mimeType: String, sizeBytes: Long): Long? {
@@ -204,9 +312,9 @@ object MultiPage {
}
fun getTiffPages(context: Context, uri: Uri): ArrayList {
- fun toMap(page: Int, options: TiffBitmapFactory.Options): FieldMap {
+ fun toMap(pageIndex: Int, options: TiffBitmapFactory.Options): FieldMap {
return hashMapOf(
- KEY_PAGE to page,
+ KEY_PAGE to pageIndex,
KEY_MIME_TYPE to MimeTypes.TIFF,
KEY_WIDTH to options.outWidth,
KEY_HEIGHT to options.outHeight,
@@ -217,8 +325,8 @@ object MultiPage {
getTiffPageInfo(context, uri, 0)?.let { first ->
pages.add(toMap(0, first))
val pageCount = first.outDirectoryCount
- for (i in 1 until pageCount) {
- getTiffPageInfo(context, uri, i)?.let { pages.add(toMap(i, it)) }
+ for (pageIndex in 1 until pageCount) {
+ getTiffPageInfo(context, uri, pageIndex)?.let { pages.add(toMap(pageIndex, it)) }
}
}
return pages
diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/metadata/XMP.kt b/android/app/src/main/kotlin/deckers/thibault/aves/metadata/XMP.kt
index e593dd16c..2744a70aa 100644
--- a/android/app/src/main/kotlin/deckers/thibault/aves/metadata/XMP.kt
+++ b/android/app/src/main/kotlin/deckers/thibault/aves/metadata/XMP.kt
@@ -49,6 +49,7 @@ object XMP {
private const val GDEVICE_ITEM_NS_URI = "http://ns.google.com/photos/dd/1.0/item/"
private const val GIMAGE_NS_URI = "http://ns.google.com/photos/1.0/image/"
private const val GPANO_NS_URI = "http://ns.google.com/photos/1.0/panorama/"
+ private const val HDRGM_NS_URI = "http://ns.adobe.com/hdr-gain-map/1.0/"
private const val PMTM_NS_URI = "http://www.hdrsoft.com/photomatix_settings01"
val DC_SUBJECT_PROP_NAME = XMPPropName(DC_NS_URI, "subject")
@@ -83,13 +84,20 @@ object XMP {
val GDEVICE_CONTAINER_ITEM_LENGTH_PROP_NAME = XMPPropName(GDEVICE_ITEM_NS_URI, "Length")
val GDEVICE_CONTAINER_ITEM_MIME_PROP_NAME = XMPPropName(GDEVICE_ITEM_NS_URI, "Mime")
- // motion photo
+ // container
val GCAMERA_VIDEO_OFFSET_PROP_NAME = XMPPropName(GCAMERA_NS_URI, "MicroVideoOffset")
val GCONTAINER_DIRECTORY_PROP_NAME = XMPPropName(GCONTAINER_NS_URI, "Directory")
val GCONTAINER_ITEM_PROP_NAME = XMPPropName(GCONTAINER_NS_URI, "Item")
val GCONTAINER_ITEM_LENGTH_PROP_NAME = XMPPropName(GCONTAINER_ITEM_NS_URI, "Length")
val GCONTAINER_ITEM_MIME_PROP_NAME = XMPPropName(GCONTAINER_ITEM_NS_URI, "Mime")
+ private val GCONTAINER_ITEM_SEMANTIC_PROP_NAME = XMPPropName(GCONTAINER_ITEM_NS_URI, "Semantic")
+
+ private const val ITEM_SEMANTIC_GAIN_MAP = "GainMap"
+
+ // HDR gain map
+
+ private val HDRGM_VERSION_PROP_NAME = XMPPropName(HDRGM_NS_URI, "Version")
// panorama
// cf https://developers.google.com/streetview/spherical-metadata
@@ -180,6 +188,35 @@ object XMP {
// extensions
+ fun XMPMeta.hasHdrGainMap(): Boolean {
+ try {
+ // standard HDR gain map
+ if (doesPropExist(HDRGM_VERSION_PROP_NAME)) {
+ return true
+ }
+
+ // `Ultra HDR`
+ if (doesPropExist(GCONTAINER_DIRECTORY_PROP_NAME)) {
+ val count = countPropArrayItems(GCONTAINER_DIRECTORY_PROP_NAME)
+ for (i in 1 until count + 1) {
+ val semantic = getSafeStructField(listOf(GCONTAINER_DIRECTORY_PROP_NAME, i, GCONTAINER_ITEM_PROP_NAME, GCONTAINER_ITEM_SEMANTIC_PROP_NAME))?.value
+ if (semantic == ITEM_SEMANTIC_GAIN_MAP) {
+ return true
+ }
+ }
+ }
+
+ return false
+ } catch (e: XMPException) {
+ if (e.errorCode != XMPError.BADSCHEMA) {
+ // `BADSCHEMA` code is reported when we check a property
+ // from a non standard namespace, and that namespace is not declared in the XMP
+ Log.w(LOG_TAG, "failed to check HDR props from XMP", e)
+ }
+ }
+ return false
+ }
+
fun XMPMeta.isMotionPhoto(): Boolean {
try {
// GCamera motion photo
diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/metadata/metadataextractor/Helper.kt b/android/app/src/main/kotlin/deckers/thibault/aves/metadata/metadataextractor/Helper.kt
index 6bbd418ff..3ee6f18fc 100644
--- a/android/app/src/main/kotlin/deckers/thibault/aves/metadata/metadataextractor/Helper.kt
+++ b/android/app/src/main/kotlin/deckers/thibault/aves/metadata/metadataextractor/Helper.kt
@@ -27,6 +27,7 @@ import com.drew.metadata.xmp.XmpReader
import deckers.thibault.aves.metadata.ExifGeoTiffTags
import deckers.thibault.aves.metadata.GeoTiffKeys
import deckers.thibault.aves.metadata.Metadata
+import deckers.thibault.aves.metadata.metadataextractor.mpf.MpfReader
import deckers.thibault.aves.utils.LogUtils
import java.io.BufferedInputStream
import java.io.IOException
@@ -97,6 +98,7 @@ object Helper {
val readers = ArrayList().apply {
addAll(JpegMetadataReader.ALL_READERS.filter { it !is XmpReader })
add(SafeXmpReader())
+ add(MpfReader())
}
val metadata = com.drew.metadata.Metadata()
diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/metadata/metadataextractor/mpf/MpEntry.kt b/android/app/src/main/kotlin/deckers/thibault/aves/metadata/metadataextractor/mpf/MpEntry.kt
new file mode 100644
index 000000000..dc777dbd2
--- /dev/null
+++ b/android/app/src/main/kotlin/deckers/thibault/aves/metadata/metadataextractor/mpf/MpEntry.kt
@@ -0,0 +1,37 @@
+package deckers.thibault.aves.metadata.metadataextractor.mpf
+
+import deckers.thibault.aves.utils.MimeTypes
+
+class MpEntry(val flags: Int, val format: Int, val type: Int, val size: Long, val dataOffset: Long, val dep1: Short, val dep2: Short) {
+ val mimeType: String?
+ get() = getMimeType(format)
+
+ val isThumbnail: Boolean
+ get() = when (type) {
+ TYPE_THUMBNAIL_VGA, TYPE_THUMBNAIL_FULL_HD -> true
+ else -> false
+ }
+
+ override fun toString(): String = "MpEntry#${hashCode()}{flags=$flags, format=$format, type=$type, size=$size, dataOffset=$dataOffset, dep1=$dep1, dep2=$dep2}"
+
+ companion object {
+ const val FLAG_REPRESENTATIVE = 1 shl 2
+ const val FLAG_DEPENDENT_CHILD = 1 shl 3
+ const val FLAG_DEPENDENT_PARENT = 1 shl 4
+
+ const val TYPE_PRIMARY = 0x030000
+ const val TYPE_THUMBNAIL_VGA = 0x010001
+ const val TYPE_THUMBNAIL_FULL_HD = 0x010002
+ const val TYPE_PANORAMA = 0x020001
+ const val TYPE_DISPARITY = 0x020002
+ const val TYPE_MULTI_ANGLE = 0x020003
+ const val TYPE_UNDEFINED = 0x000000
+
+ fun getMimeType(format: Int): String? {
+ return when (format) {
+ 0 -> MimeTypes.JPEG
+ else -> null
+ }
+ }
+ }
+}
diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/metadata/metadataextractor/mpf/MpEntryDirectory.kt b/android/app/src/main/kotlin/deckers/thibault/aves/metadata/metadataextractor/mpf/MpEntryDirectory.kt
new file mode 100644
index 000000000..7dba5520f
--- /dev/null
+++ b/android/app/src/main/kotlin/deckers/thibault/aves/metadata/metadataextractor/mpf/MpEntryDirectory.kt
@@ -0,0 +1,64 @@
+package deckers.thibault.aves.metadata.metadataextractor.mpf
+
+import com.drew.metadata.Directory
+import com.drew.metadata.TagDescriptor
+
+class MpEntryDirectory(val id: Int, val entry: MpEntry) : Directory() {
+ private val descriptor = MpEntryDescriptor(this)
+
+ init {
+ setDescriptor(descriptor)
+ }
+
+ fun describe(): Map {
+ return HashMap().apply {
+ put("Flags", descriptor.getFlagsDescription(entry.flags))
+ put("Format", descriptor.getFormatDescription(entry.format))
+ put("Type", descriptor.getTypeDescription(entry.type))
+ put("Size", "${entry.size} bytes")
+ put("Offset", "${entry.dataOffset} bytes")
+ put("Dependent Image 1 Entry Number", "${entry.dep1}")
+ put("Dependent Image 2 Entry Number", "${entry.dep2}")
+ }
+ }
+
+ override fun getName(): String {
+ return "MPF Image #$id"
+ }
+
+ override fun getTagNameMap(): HashMap {
+ return _tagNameMap
+ }
+
+ companion object {
+ private val _tagNameMap = HashMap()
+ }
+}
+
+class MpEntryDescriptor(directory: MpEntryDirectory?) : TagDescriptor(directory) {
+ fun getFlagsDescription(flags: Int): String {
+ val flagStrings = ArrayList().apply {
+ if (flags and MpEntry.FLAG_REPRESENTATIVE != 0) add("representative image")
+ if (flags and MpEntry.FLAG_DEPENDENT_CHILD != 0) add("dependent child image")
+ if (flags and MpEntry.FLAG_DEPENDENT_PARENT != 0) add("dependent parent image")
+ }
+ return if (flagStrings.isEmpty()) "none" else flagStrings.joinToString(", ")
+ }
+
+ fun getFormatDescription(format: Int): String {
+ return MpEntry.getMimeType(format) ?: "Unknown ($format)"
+ }
+
+ fun getTypeDescription(type: Int): String {
+ return when (type) {
+ MpEntry.TYPE_PRIMARY -> "Baseline MP Primary Image"
+ MpEntry.TYPE_THUMBNAIL_VGA -> "Large Thumbnail (VGA equivalent)"
+ MpEntry.TYPE_THUMBNAIL_FULL_HD -> "Large Thumbnail (full HD equivalent)"
+ MpEntry.TYPE_PANORAMA -> "Multi-frame Panorama"
+ MpEntry.TYPE_DISPARITY -> "Multi-frame Disparity"
+ MpEntry.TYPE_MULTI_ANGLE -> "Multi-angle"
+ MpEntry.TYPE_UNDEFINED -> "Undefined"
+ else -> "Unknown ($type)"
+ }
+ }
+}
diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/metadata/metadataextractor/mpf/MpfDirectory.kt b/android/app/src/main/kotlin/deckers/thibault/aves/metadata/metadataextractor/mpf/MpfDirectory.kt
new file mode 100644
index 000000000..53904b56f
--- /dev/null
+++ b/android/app/src/main/kotlin/deckers/thibault/aves/metadata/metadataextractor/mpf/MpfDirectory.kt
@@ -0,0 +1,38 @@
+package deckers.thibault.aves.metadata.metadataextractor.mpf
+
+import com.drew.metadata.Directory
+import com.drew.metadata.TagDescriptor
+
+class MpfDirectory : Directory() {
+ init {
+ setDescriptor(MpfDescriptor(this))
+ }
+
+ override fun getName(): String {
+ return "MPF"
+ }
+
+ override fun getTagNameMap(): HashMap {
+ return _tagNameMap
+ }
+
+ fun getNumberOfImages() = getInt(TAG_NUMBER_OF_IMAGES)
+
+ companion object {
+ const val TAG_MPF_VERSION = 0xb000
+ const val TAG_NUMBER_OF_IMAGES = 0xb001
+ const val TAG_MP_ENTRY = 0xb002
+ private const val TAG_IMAGE_UID_LIST = 0xb003
+ private const val TAG_TOTAL_FRAMES = 0xb004
+
+ private val _tagNameMap = HashMap().apply {
+ put(TAG_MPF_VERSION, "MPF Version")
+ put(TAG_NUMBER_OF_IMAGES, "Number Of Images")
+ put(TAG_MP_ENTRY, "MP Entry")
+ put(TAG_IMAGE_UID_LIST, "Image UID List")
+ put(TAG_TOTAL_FRAMES, "Total Frames")
+ }
+ }
+}
+
+class MpfDescriptor(directory: MpfDirectory?) : TagDescriptor(directory)
\ No newline at end of file
diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/metadata/metadataextractor/mpf/MpfReader.kt b/android/app/src/main/kotlin/deckers/thibault/aves/metadata/metadataextractor/mpf/MpfReader.kt
new file mode 100644
index 000000000..423ff56d4
--- /dev/null
+++ b/android/app/src/main/kotlin/deckers/thibault/aves/metadata/metadataextractor/mpf/MpfReader.kt
@@ -0,0 +1,95 @@
+package deckers.thibault.aves.metadata.metadataextractor.mpf
+
+import android.util.Log
+import com.drew.imaging.jpeg.JpegSegmentMetadataReader
+import com.drew.imaging.jpeg.JpegSegmentType
+import com.drew.lang.ByteArrayReader
+import com.drew.lang.RandomAccessReader
+import com.drew.metadata.Metadata
+import com.drew.metadata.MetadataReader
+import deckers.thibault.aves.utils.LogUtils
+
+class MpfReader : JpegSegmentMetadataReader, MetadataReader {
+ override fun getSegmentTypes(): Iterable {
+ return listOf(JpegSegmentType.APP2)
+ }
+
+ override fun readJpegSegments(segments: Iterable, metadata: Metadata, segmentType: JpegSegmentType) {
+ for (segmentBytes in segments) {
+ // Skip segments not starting with the required header
+ if (segmentBytes.size >= PREAMBLE.length && PREAMBLE == String(segmentBytes, 0, PREAMBLE.length)) {
+ extract(ByteArrayReader(segmentBytes), metadata)
+ }
+ }
+ }
+
+ override fun extract(reader: RandomAccessReader, metadata: Metadata) {
+ val directory = MpfDirectory()
+ metadata.addDirectory(directory)
+
+ val baseOffset = 4
+
+ // MP Format Identifier (4Byte)
+ // MP header
+ // - MP Endian (4Byte)
+ val byteOrderIdentifier = reader.getInt16(baseOffset)
+ if (byteOrderIdentifier.toInt() == 0x4d4d) { // "MM"
+ reader.isMotorolaByteOrder = true
+ } else if (byteOrderIdentifier.toInt() == 0x4949) { // "II"
+ reader.isMotorolaByteOrder = false
+ }
+ // - Offset to First IFD (4Byte)
+ val firstIfdOffset = reader.getInt32(baseOffset + 4)
+
+ // [in primary image only] MP Index IFD:
+ // - Count (2Byte)
+ var offset = baseOffset + firstIfdOffset
+ val tagCount = reader.getInt16(offset)
+ offset += 2
+ // - MP Index Fields (Overall Structure Info.)
+ var imageCount = 0
+ for (tag in 0.. directory.setString(tagId, reader.getString(offset + 8, 4, Charsets.US_ASCII))
+ MpfDirectory.TAG_NUMBER_OF_IMAGES -> {
+ imageCount = reader.getInt32(offset + 8)
+ directory.setInt(tagId, imageCount)
+ }
+
+ MpfDirectory.TAG_MP_ENTRY -> {
+ var mpEntryOffset = baseOffset + reader.getInt32(offset + 8)
+ for (index in 0.. Log.d(LOG_TAG, "unknown tag=$tagId")
+ }
+ offset += 12
+ }
+
+ // - Offset of Next IFD (4Byte)
+ // Value (MP Index IFD)
+
+ // [in primary & other images] MP Attributes IFD:
+ // - Count (2Byte)
+ // - MP Attribute Fields (Details of Specific Image Usage)
+ // - Offset of Next IFD
+ // Value (MP Attribute IFD)
+ }
+
+ companion object {
+ private val LOG_TAG = LogUtils.createTag()
+ private const val PREAMBLE = "MPF"
+ }
+}
diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/model/provider/AvesEmbeddedMediaProvider.kt b/android/app/src/main/kotlin/deckers/thibault/aves/model/provider/AvesEmbeddedMediaProvider.kt
new file mode 100644
index 000000000..49f0a8895
--- /dev/null
+++ b/android/app/src/main/kotlin/deckers/thibault/aves/model/provider/AvesEmbeddedMediaProvider.kt
@@ -0,0 +1,18 @@
+package deckers.thibault.aves.model.provider
+
+import android.content.ContentResolver
+import android.content.Context
+import android.net.Uri
+import java.util.Locale
+
+class AvesEmbeddedMediaProvider : UnknownContentProvider() {
+ override val reliableProviderMimeType: Boolean
+ get() = true
+
+ companion object {
+ fun provides(context: Context, uri: Uri): Boolean {
+ if (uri.scheme?.lowercase(Locale.ROOT) != ContentResolver.SCHEME_CONTENT) return false
+ return uri.authority == "${context.applicationContext.packageName}.file_provider"
+ }
+ }
+}
\ No newline at end of file
diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/model/provider/ImageProvider.kt b/android/app/src/main/kotlin/deckers/thibault/aves/model/provider/ImageProvider.kt
index 8abdc5648..766c3b936 100644
--- a/android/app/src/main/kotlin/deckers/thibault/aves/model/provider/ImageProvider.kt
+++ b/android/app/src/main/kotlin/deckers/thibault/aves/model/provider/ImageProvider.kt
@@ -19,25 +19,36 @@ import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.bumptech.glide.request.FutureTarget
import com.bumptech.glide.request.RequestOptions
import com.commonsware.cwac.document.DocumentFileCompat
-import deckers.thibault.aves.decoder.MultiTrackImage
+import deckers.thibault.aves.decoder.MultiPageImage
import deckers.thibault.aves.decoder.SvgImage
import deckers.thibault.aves.decoder.TiffImage
-import deckers.thibault.aves.metadata.*
+import deckers.thibault.aves.metadata.ExifInterfaceHelper
import deckers.thibault.aves.metadata.ExifInterfaceHelper.getSafeDateMillis
import deckers.thibault.aves.metadata.Metadata.TYPE_EXIF
import deckers.thibault.aves.metadata.Metadata.TYPE_IPTC
import deckers.thibault.aves.metadata.Metadata.TYPE_MP4
import deckers.thibault.aves.metadata.Metadata.TYPE_XMP
+import deckers.thibault.aves.metadata.Mp4ParserHelper
import deckers.thibault.aves.metadata.Mp4ParserHelper.updateLocation
import deckers.thibault.aves.metadata.Mp4ParserHelper.updateRotation
import deckers.thibault.aves.metadata.Mp4ParserHelper.updateXmp
+import deckers.thibault.aves.metadata.MultiPage
+import deckers.thibault.aves.metadata.PixyMetaHelper
import deckers.thibault.aves.metadata.PixyMetaHelper.extendedXmpDocString
import deckers.thibault.aves.metadata.PixyMetaHelper.xmpDocString
+import deckers.thibault.aves.metadata.XMP
import deckers.thibault.aves.metadata.metadataextractor.Helper
-import deckers.thibault.aves.model.*
-import deckers.thibault.aves.utils.*
+import deckers.thibault.aves.model.AvesEntry
+import deckers.thibault.aves.model.ExifOrientationOp
+import deckers.thibault.aves.model.FieldMap
+import deckers.thibault.aves.model.NameConflictStrategy
+import deckers.thibault.aves.model.SourceEntry
+import deckers.thibault.aves.utils.BitmapUtils
+import deckers.thibault.aves.utils.BmpWriter
import deckers.thibault.aves.utils.FileUtils.transferFrom
import deckers.thibault.aves.utils.FileUtils.transferTo
+import deckers.thibault.aves.utils.LogUtils
+import deckers.thibault.aves.utils.MimeTypes
import deckers.thibault.aves.utils.MimeTypes.canEditExif
import deckers.thibault.aves.utils.MimeTypes.canEditIptc
import deckers.thibault.aves.utils.MimeTypes.canEditXmp
@@ -46,13 +57,19 @@ import deckers.thibault.aves.utils.MimeTypes.canReadWithPixyMeta
import deckers.thibault.aves.utils.MimeTypes.canRemoveMetadata
import deckers.thibault.aves.utils.MimeTypes.extensionFor
import deckers.thibault.aves.utils.MimeTypes.isVideo
+import deckers.thibault.aves.utils.StorageUtils
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import pixy.meta.meta.Metadata
import pixy.meta.meta.MetadataType
-import java.io.*
+import java.io.ByteArrayInputStream
+import java.io.File
+import java.io.FileOutputStream
+import java.io.IOException
+import java.io.OutputStream
import java.nio.channels.Channels
-import java.util.*
+import java.util.Date
+import java.util.TimeZone
import kotlin.math.absoluteValue
abstract class ImageProvider {
@@ -291,8 +308,8 @@ abstract class ImageProvider {
targetHeightPx = sourceEntry.height * targetHeightPx / 100
}
- val model: Any = if (MimeTypes.isHeic(sourceMimeType) && pageId != null) {
- MultiTrackImage(activity, sourceUri, pageId)
+ val model: Any = if (pageId != null && MultiPageImage.isSupported(sourceMimeType)) {
+ MultiPageImage(activity, sourceUri, sourceMimeType, pageId)
} else if (sourceMimeType == MimeTypes.TIFF) {
TiffImage(activity, sourceUri, pageId)
} else if (sourceMimeType == MimeTypes.SVG) {
diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/model/provider/ImageProviderFactory.kt b/android/app/src/main/kotlin/deckers/thibault/aves/model/provider/ImageProviderFactory.kt
index 63d0afbde..180720652 100644
--- a/android/app/src/main/kotlin/deckers/thibault/aves/model/provider/ImageProviderFactory.kt
+++ b/android/app/src/main/kotlin/deckers/thibault/aves/model/provider/ImageProviderFactory.kt
@@ -1,20 +1,24 @@
package deckers.thibault.aves.model.provider
import android.content.ContentResolver
+import android.content.Context
import android.net.Uri
import deckers.thibault.aves.utils.StorageUtils
-import java.util.*
+import java.util.Locale
object ImageProviderFactory {
- fun getProvider(uri: Uri): ImageProvider? {
+ fun getProvider(context: Context, uri: Uri): ImageProvider? {
return when (uri.scheme?.lowercase(Locale.ROOT)) {
ContentResolver.SCHEME_CONTENT -> {
if (StorageUtils.isMediaStoreContentUri(uri)) {
MediaStoreImageProvider()
+ } else if (AvesEmbeddedMediaProvider.provides(context, uri)) {
+ AvesEmbeddedMediaProvider()
} else {
- ContentImageProvider()
+ UnknownContentProvider()
}
}
+
ContentResolver.SCHEME_FILE -> FileImageProvider()
else -> null
}
diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/model/provider/ContentImageProvider.kt b/android/app/src/main/kotlin/deckers/thibault/aves/model/provider/UnknownContentProvider.kt
similarity index 62%
rename from android/app/src/main/kotlin/deckers/thibault/aves/model/provider/ContentImageProvider.kt
rename to android/app/src/main/kotlin/deckers/thibault/aves/model/provider/UnknownContentProvider.kt
index ef2e87410..8fc4e6db0 100644
--- a/android/app/src/main/kotlin/deckers/thibault/aves/model/provider/ContentImageProvider.kt
+++ b/android/app/src/main/kotlin/deckers/thibault/aves/model/provider/UnknownContentProvider.kt
@@ -13,31 +13,35 @@ import deckers.thibault.aves.utils.LogUtils
import deckers.thibault.aves.utils.MimeTypes
import deckers.thibault.aves.utils.StorageUtils
-internal class ContentImageProvider : ImageProvider() {
+open class UnknownContentProvider : ImageProvider() {
+ open val reliableProviderMimeType: Boolean
+ get() = false
+
override fun fetchSingle(context: Context, uri: Uri, sourceMimeType: String?, callback: ImageOpCallback) {
- // source MIME type may be incorrect, so we get a second opinion if possible
- var extractorMimeType: String? = null
- try {
- val safeUri = Uri.fromFile(Metadata.createPreviewFile(context, uri))
- StorageUtils.openInputStream(context, safeUri)?.use { input ->
- // `metadata-extractor` is the most reliable, except for `tiff` (false positives, false negatives)
- // cf https://github.com/drewnoakes/metadata-extractor/issues/296
- Helper.readMimeType(input)?.takeIf { it != MimeTypes.TIFF }?.let {
- extractorMimeType = it
- if (extractorMimeType != sourceMimeType) {
- Log.d(LOG_TAG, "source MIME type is $sourceMimeType but extracted MIME type is $extractorMimeType for uri=$uri")
+ var mimeType = sourceMimeType
+ if (sourceMimeType == null || !reliableProviderMimeType) {
+ // source MIME type may be incorrect, so we get a second opinion if possible
+ try {
+ val safeUri = Uri.fromFile(Metadata.createPreviewFile(context, uri))
+ StorageUtils.openInputStream(context, safeUri)?.use { input ->
+ // `metadata-extractor` is the most reliable, except for `tiff` (false positives, false negatives)
+ // cf https://github.com/drewnoakes/metadata-extractor/issues/296
+ Helper.readMimeType(input)?.takeIf { it != MimeTypes.TIFF }?.let {
+ if (it != sourceMimeType) {
+ Log.d(LOG_TAG, "source MIME type is $sourceMimeType but extracted MIME type is $it for uri=$uri")
+ mimeType = it
+ }
}
}
+ } catch (e: Exception) {
+ Log.w(LOG_TAG, "failed to get MIME type by metadata-extractor for uri=$uri", e)
+ } catch (e: NoClassDefFoundError) {
+ Log.w(LOG_TAG, "failed to get MIME type by metadata-extractor for uri=$uri", e)
+ } catch (e: AssertionError) {
+ Log.w(LOG_TAG, "failed to get MIME type by metadata-extractor for uri=$uri", e)
}
- } catch (e: Exception) {
- Log.w(LOG_TAG, "failed to get MIME type by metadata-extractor for uri=$uri", e)
- } catch (e: NoClassDefFoundError) {
- Log.w(LOG_TAG, "failed to get MIME type by metadata-extractor for uri=$uri", e)
- } catch (e: AssertionError) {
- Log.w(LOG_TAG, "failed to get MIME type by metadata-extractor for uri=$uri", e)
}
- val mimeType = extractorMimeType ?: sourceMimeType
val fields: FieldMap = hashMapOf(
"origin" to SourceEntry.ORIGIN_UNKNOWN_CONTENT,
"uri" to uri.toString(),
@@ -75,6 +79,6 @@ internal class ContentImageProvider : ImageProvider() {
}
companion object {
- private val LOG_TAG = LogUtils.createTag()
+ private val LOG_TAG = LogUtils.createTag()
}
}
\ No newline at end of file
diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/utils/MimeTypes.kt b/android/app/src/main/kotlin/deckers/thibault/aves/utils/MimeTypes.kt
index 31d0e9986..d68d851b1 100644
--- a/android/app/src/main/kotlin/deckers/thibault/aves/utils/MimeTypes.kt
+++ b/android/app/src/main/kotlin/deckers/thibault/aves/utils/MimeTypes.kt
@@ -82,9 +82,10 @@ object MimeTypes {
else -> false
}
- // as of Flutter v1.22.0, with additional custom handling for SVG
- fun canDecodeWithFlutter(mimeType: String, rotationDegrees: Int?, isFlipped: Boolean?) = when (mimeType) {
- JPEG, GIF, WEBP, BMP, WBMP, ICO, SVG -> true
+ // as of Flutter v3.16.4, with additional custom handling for SVG
+ fun canDecodeWithFlutter(mimeType: String, pageId: Int?, rotationDegrees: Int?, isFlipped: Boolean?) = when (mimeType) {
+ GIF, WEBP, BMP, WBMP, ICO, SVG -> true
+ JPEG -> (pageId ?: 0) == 0
PNG -> (rotationDegrees ?: 0) == 0 && !(isFlipped ?: false)
else -> false
}
diff --git a/android/app/src/main/res/values-ar/strings.xml b/android/app/src/main/res/values-ar/strings.xml
index 0d6515695..dd308de11 100644
--- a/android/app/src/main/res/values-ar/strings.xml
+++ b/android/app/src/main/res/values-ar/strings.xml
@@ -8,5 +8,5 @@
يتم فحص الوسائط
إيقاف
الوضع الآمن
- أيفيس
+ Aves
\ No newline at end of file
diff --git a/android/app/src/main/res/values-tr/strings.xml b/android/app/src/main/res/values-tr/strings.xml
index e516cc30b..85fa22f09 100644
--- a/android/app/src/main/res/values-tr/strings.xml
+++ b/android/app/src/main/res/values-tr/strings.xml
@@ -8,4 +8,5 @@
Medya tarama
Medya taranıyor
Durdur
+ Güvenli mod
\ No newline at end of file
diff --git a/fastlane/metadata/android/ar/full_description.txt b/fastlane/metadata/android/ar/full_description.txt
index 167ed3b35..74df1a08d 100644
--- a/fastlane/metadata/android/ar/full_description.txt
+++ b/fastlane/metadata/android/ar/full_description.txt
@@ -1,5 +1,5 @@
أيفيس يمكنه التعامل مع جميع أنواع الصور ومقاطع الفيديو ، بما في ذلك ملفات JPEG و MP4 النموذجية ، ولكن أيضًا أشياء أكثر غرابة مثل ملفات TIFF و SVG و AVI القديمة متعددة الصفحات والمزيد! يقوم بمسح مجموعة الوسائط الخاصة بك لتحديد الصور المتحركة, الإستعراضات (المعروف أيضًا باسم الصور البانورامية), 360 درجة مقاطع الفيديو, إلى جانب GeoTIFF الملفات.
-Navigation and search is an important part of Aves. The goal is for users to easily flow from albums to photos to tags to maps, etc.
+الملاحة والبحث جزء مهم من Avesالهدف هو أن يكون بإمكان المستخدمين التنقل بسهولة من الألبومات إلى الصور إلى الوسوم إلى الخرائط، وما إلى ذلك..
-Aves integrates with Android (from KitKat to Android 13, including Android TV) with features such as widgets, app shortcuts, screen saver and global search handling. It also works as a media viewer and picker.
\ No newline at end of file
+Avesتتكامل مع نظام Android (من KitKat إلى Android 14، بما في ذلك Android TV) مع ميزات مثلs الودجتس, اختصارات التطبيق, حافظة الشاشة والبحث العالمي التعامل معه. كما أنه يعمل كـ عارض واختار لوسائط (ملفات الوسائط).
diff --git a/fastlane/metadata/android/ar/images/featureGraphic.png b/fastlane/metadata/android/ar/images/featureGraphic.png
new file mode 100644
index 000000000..7204bd0d6
Binary files /dev/null and b/fastlane/metadata/android/ar/images/featureGraphic.png differ
diff --git a/fastlane/metadata/android/ar/images/phoneScreenshots/1.png b/fastlane/metadata/android/ar/images/phoneScreenshots/1.png
new file mode 100644
index 000000000..c53c38202
Binary files /dev/null and b/fastlane/metadata/android/ar/images/phoneScreenshots/1.png differ
diff --git a/fastlane/metadata/android/ar/images/phoneScreenshots/2.png b/fastlane/metadata/android/ar/images/phoneScreenshots/2.png
new file mode 100644
index 000000000..b18c82d1e
Binary files /dev/null and b/fastlane/metadata/android/ar/images/phoneScreenshots/2.png differ
diff --git a/fastlane/metadata/android/ar/images/phoneScreenshots/3.png b/fastlane/metadata/android/ar/images/phoneScreenshots/3.png
new file mode 100644
index 000000000..50a8c7a8d
Binary files /dev/null and b/fastlane/metadata/android/ar/images/phoneScreenshots/3.png differ
diff --git a/fastlane/metadata/android/ar/images/phoneScreenshots/4.png b/fastlane/metadata/android/ar/images/phoneScreenshots/4.png
new file mode 100644
index 000000000..9cb4a4ed2
Binary files /dev/null and b/fastlane/metadata/android/ar/images/phoneScreenshots/4.png differ
diff --git a/fastlane/metadata/android/ar/images/phoneScreenshots/5.png b/fastlane/metadata/android/ar/images/phoneScreenshots/5.png
new file mode 100644
index 000000000..bf90202cd
Binary files /dev/null and b/fastlane/metadata/android/ar/images/phoneScreenshots/5.png differ
diff --git a/fastlane/metadata/android/ar/images/phoneScreenshots/6.png b/fastlane/metadata/android/ar/images/phoneScreenshots/6.png
new file mode 100644
index 000000000..e46abd530
Binary files /dev/null and b/fastlane/metadata/android/ar/images/phoneScreenshots/6.png differ
diff --git a/fastlane/metadata/android/ar/images/phoneScreenshots/7.png b/fastlane/metadata/android/ar/images/phoneScreenshots/7.png
new file mode 100644
index 000000000..07d4603b9
Binary files /dev/null and b/fastlane/metadata/android/ar/images/phoneScreenshots/7.png differ
diff --git a/fastlane/metadata/android/ar/short_description.txt b/fastlane/metadata/android/ar/short_description.txt
index 3cbcb03a4..24ef32619 100644
--- a/fastlane/metadata/android/ar/short_description.txt
+++ b/fastlane/metadata/android/ar/short_description.txt
@@ -1 +1 @@
-المعرض ومستكشف البيانات الوصفية
\ No newline at end of file
+مستعرض الصور والبيانات
\ No newline at end of file
diff --git a/fastlane/metadata/android/be/full_description.txt b/fastlane/metadata/android/be/full_description.txt
index 9f6558c1a..9be4265ce 100644
--- a/fastlane/metadata/android/be/full_description.txt
+++ b/fastlane/metadata/android/be/full_description.txt
@@ -2,4 +2,4 @@
Навігацыя і пошук з'яўляюцца важнай часткай Aves. Мэта складаецца ў тым, каб карыстальнікі лёгка пераходзілі ад альбомаў да фатаграфій да тэгаў да карт і г.д.
-Aves інтэгруецца з Android (ад KitKat да Android 13, уключаючы Android TV) з такімі функцыямі, як віджэты, ярлыкі праграм, застаўка і апрацоўка глабальнага пошуку. Ён таксама працуе як сродак прагляду і выбару мультымедыя.
\ No newline at end of file
+Aves інтэгруецца з Android (ад KitKat да Android 14, уключаючы Android TV) з такімі функцыямі, як віджэты, ярлыкі праграм, застаўка і апрацоўка глабальнага пошуку. Ён таксама працуе як сродак прагляду і выбару мультымедыя.
diff --git a/fastlane/metadata/android/be/images/featureGraphic.png b/fastlane/metadata/android/be/images/featureGraphic.png
new file mode 100644
index 000000000..c1455009b
Binary files /dev/null and b/fastlane/metadata/android/be/images/featureGraphic.png differ
diff --git a/fastlane/metadata/android/be/images/phoneScreenshots/1.png b/fastlane/metadata/android/be/images/phoneScreenshots/1.png
new file mode 100644
index 000000000..6b176ae33
Binary files /dev/null and b/fastlane/metadata/android/be/images/phoneScreenshots/1.png differ
diff --git a/fastlane/metadata/android/be/images/phoneScreenshots/2.png b/fastlane/metadata/android/be/images/phoneScreenshots/2.png
new file mode 100644
index 000000000..d22c0a2c9
Binary files /dev/null and b/fastlane/metadata/android/be/images/phoneScreenshots/2.png differ
diff --git a/fastlane/metadata/android/be/images/phoneScreenshots/3.png b/fastlane/metadata/android/be/images/phoneScreenshots/3.png
new file mode 100644
index 000000000..7ebc7d837
Binary files /dev/null and b/fastlane/metadata/android/be/images/phoneScreenshots/3.png differ
diff --git a/fastlane/metadata/android/be/images/phoneScreenshots/4.png b/fastlane/metadata/android/be/images/phoneScreenshots/4.png
new file mode 100644
index 000000000..cfa4a9727
Binary files /dev/null and b/fastlane/metadata/android/be/images/phoneScreenshots/4.png differ
diff --git a/fastlane/metadata/android/be/images/phoneScreenshots/5.png b/fastlane/metadata/android/be/images/phoneScreenshots/5.png
new file mode 100644
index 000000000..fc8b1c9bb
Binary files /dev/null and b/fastlane/metadata/android/be/images/phoneScreenshots/5.png differ
diff --git a/fastlane/metadata/android/be/images/phoneScreenshots/6.png b/fastlane/metadata/android/be/images/phoneScreenshots/6.png
new file mode 100644
index 000000000..0567e896e
Binary files /dev/null and b/fastlane/metadata/android/be/images/phoneScreenshots/6.png differ
diff --git a/fastlane/metadata/android/be/images/phoneScreenshots/7.png b/fastlane/metadata/android/be/images/phoneScreenshots/7.png
new file mode 100644
index 000000000..e440673f5
Binary files /dev/null and b/fastlane/metadata/android/be/images/phoneScreenshots/7.png differ
diff --git a/fastlane/metadata/android/bn/full_description.txt b/fastlane/metadata/android/bn/full_description.txt
index 47d36a004..bae3cb8be 100644
--- a/fastlane/metadata/android/bn/full_description.txt
+++ b/fastlane/metadata/android/bn/full_description.txt
@@ -2,4 +2,4 @@
নেভিগেশন এবং সার্চ আভেস এর একটি গুরুত্বপূর্ণ অংশ। লক্ষ্য হল ইউসার যাতে সহজেই অ্যালবাম, ফটো, ট্যাগ, ম্যাপ ইত্যাদিতে স্থানান্তর করতে পারে।
-উইজেট, অ্যাপ শর্টকাট, স্ক্রিন সেভারের এবং গ্লোবাল সার্চ এর মতো বৈশিষ্ট্য সহ, আভেস অ্যান্ড্রয়েড এর সাথে সংহত হতে পারে (কিট ক্যাট থেকে অ্যান্ড্রয়েড ১৩, অ্যান্ড্রয়েড টিভি সহ)। এটি একটি মিডিয়া উপস্থাপক এবং বাছাইকারী হিসেবেও কাজ করে।
\ No newline at end of file
+উইজেট, অ্যাপ শর্টকাট, স্ক্রিন সেভারের এবং গ্লোবাল সার্চ এর মতো বৈশিষ্ট্য সহ, আভেস অ্যান্ড্রয়েড এর সাথে সংহত হতে পারে (কিট ক্যাট থেকে অ্যান্ড্রয়েড ১৩, অ্যান্ড্রয়েড টিভি সহ)। এটি একটি মিডিয়া উপস্থাপক এবং বাছাইকারী হিসেবেও কাজ করে।
diff --git a/fastlane/metadata/android/ckb/full_description.txt b/fastlane/metadata/android/ckb/full_description.txt
index 6c92748f8..6b96ec3ea 100644
--- a/fastlane/metadata/android/ckb/full_description.txt
+++ b/fastlane/metadata/android/ckb/full_description.txt
@@ -2,4 +2,4 @@
Navigation and search is an important part of Aves. The goal is for users to easily flow from albums to photos to tags to maps, etc.
-Aves integrates with Android (from KitKat to Android 13, including Android TV) with features such as widgets, app shortcuts, screen saver and global search handling. It also works as a media viewer and picker.
\ No newline at end of file
+Aves integrates with Android (from KitKat to Android 14, including Android TV) with features such as widgets, app shortcuts, screen saver and global search handling. It also works as a media viewer and picker.
diff --git a/fastlane/metadata/android/cs/full_description.txt b/fastlane/metadata/android/cs/full_description.txt
index 2ca7137cc..63000d41a 100644
--- a/fastlane/metadata/android/cs/full_description.txt
+++ b/fastlane/metadata/android/cs/full_description.txt
@@ -2,4 +2,4 @@
Navigace a vyhledávání jsou důležitou součástí aplikace Aves. Cílem je, aby uživatelé jednoduše přecházeli z alb k fotografiím, albům, mapám, atd.
-Aves podporuje Android (od verze KitKat po Android 13, včetně Android TV) s funkcemi jako jsou widgety, zkratky aplikací, spořič displeje a globální vyhledávání. Rovněž jej lze použít pro prohlížení a výběr médií.
\ No newline at end of file
+Aves podporuje Android (od verze KitKat po Android 14, včetně Android TV) s funkcemi jako jsou widgety, zkratky aplikací, spořič displeje a globální vyhledávání. Rovněž jej lze použít pro prohlížení a výběr médií.
diff --git a/fastlane/metadata/android/de/full_description.txt b/fastlane/metadata/android/de/full_description.txt
index 7cfc6826c..3b78e40f8 100644
--- a/fastlane/metadata/android/de/full_description.txt
+++ b/fastlane/metadata/android/de/full_description.txt
@@ -2,4 +2,4 @@
Navigation und Suche ist ein wichtiger Bestandteil von Aves. Das Ziel besteht darin, dass Benutzer problemlos von Alben zu Fotos zu Tags zu Karten usw. wechseln können.
-Aves lässt sich mit Android (von API 19 bis 33, d. h. von KitKat bis Android 13) mit Funktionen wie App-Verknüpfungen und globaler Suche integrieren. Es funktioniert auch als Medienbetrachter und -auswahl.
\ No newline at end of file
+Aves lässt sich mit Android (von API 19 bis 34, d. h. von KitKat bis Android 14) mit Funktionen wie App-Verknüpfungen und globaler Suche integrieren. Es funktioniert auch als Medienbetrachter und -auswahl.
diff --git a/fastlane/metadata/android/el/full_description.txt b/fastlane/metadata/android/el/full_description.txt
index c183af4c3..c7ee2b244 100644
--- a/fastlane/metadata/android/el/full_description.txt
+++ b/fastlane/metadata/android/el/full_description.txt
@@ -2,4 +2,4 @@
Η πλοήγηση και η αναζήτηση αποτελούν σημαντικό μέρος της εφαρμογής Aves. Ο στόχος της εφαρμογής είναι να παρέχει στους χρήστες εύκολη και γρήγορη πρόσβαση στα άλμπουμ, σε φωτογραφίες, ετικέτες, χάρτες κ.λπ.
-Η εφαρμογή Aves εγκαθίσταται στο λογισμικό Android (συμβατότητα από API 19 έως 33, δηλαδή από KitKat έως Android 13) με δυνατότητες όπως γραφικά στοιχεία, συντομεύσεις, προφύλαξη οθόνης και global search. Μπορεί επίσης να χρησιμοποιηθεί ως εφαρμογή προβολής και επιλογής πολυμέσων.
\ No newline at end of file
+Η εφαρμογή Aves εγκαθίσταται στο λογισμικό Android (συμβατότητα από API 19 έως 34, δηλαδή από KitKat έως Android 14) με δυνατότητες όπως γραφικά στοιχεία, συντομεύσεις, προφύλαξη οθόνης και global search. Μπορεί επίσης να χρησιμοποιηθεί ως εφαρμογή προβολής και επιλογής πολυμέσων.
diff --git a/fastlane/metadata/android/en-US/changelogs/110.txt b/fastlane/metadata/android/en-US/changelogs/110.txt
new file mode 100644
index 000000000..69b5f63e7
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/110.txt
@@ -0,0 +1,4 @@
+In v1.10.1:
+- JPEG MPF support
+- enjoy the app in Arabic & Belarusian
+Full changelog available on GitHub
\ No newline at end of file
diff --git a/fastlane/metadata/android/en-US/changelogs/11001.txt b/fastlane/metadata/android/en-US/changelogs/11001.txt
new file mode 100644
index 000000000..69b5f63e7
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/11001.txt
@@ -0,0 +1,4 @@
+In v1.10.1:
+- JPEG MPF support
+- enjoy the app in Arabic & Belarusian
+Full changelog available on GitHub
\ No newline at end of file
diff --git a/fastlane/metadata/android/en-US/full_description.txt b/fastlane/metadata/android/en-US/full_description.txt
index 6c92748f8..6b96ec3ea 100644
--- a/fastlane/metadata/android/en-US/full_description.txt
+++ b/fastlane/metadata/android/en-US/full_description.txt
@@ -2,4 +2,4 @@
Navigation and search is an important part of Aves. The goal is for users to easily flow from albums to photos to tags to maps, etc.
-Aves integrates with Android (from KitKat to Android 13, including Android TV) with features such as widgets, app shortcuts, screen saver and global search handling. It also works as a media viewer and picker.
\ No newline at end of file
+Aves integrates with Android (from KitKat to Android 14, including Android TV) with features such as widgets, app shortcuts, screen saver and global search handling. It also works as a media viewer and picker.
diff --git a/fastlane/metadata/android/es-MX/full_description.txt b/fastlane/metadata/android/es-MX/full_description.txt
index 01ef58d76..9d58d9cfb 100644
--- a/fastlane/metadata/android/es-MX/full_description.txt
+++ b/fastlane/metadata/android/es-MX/full_description.txt
@@ -2,4 +2,4 @@
La navegación y búsqueda son las partes más importantes de Aves. Su propósito es que los usuarios puedan fácilmente ir de álbumes a fotos, etiquetas, mapas, etc.
-Aves se integra con Android (desde KitKat hasta Android 13, incluido Android TV) con funciones como complementos, accesos directos a aplicaciones, protector de pantalla y búsqueda global. También funciona como un visor y selector de medios.
\ No newline at end of file
+Aves se integra con Android (desde KitKat hasta Android 14, incluido Android TV) con funciones como complementos, accesos directos a aplicaciones, protector de pantalla y búsqueda global. También funciona como un visor y selector de medios.
diff --git a/fastlane/metadata/android/eu/full_description.txt b/fastlane/metadata/android/eu/full_description.txt
index c64149f18..63af644c6 100644
--- a/fastlane/metadata/android/eu/full_description.txt
+++ b/fastlane/metadata/android/eu/full_description.txt
@@ -2,4 +2,4 @@
Nabigazioa eta bilaketa Aves aplikazioaren zati garrantzitsu bat da. Helburua, erabiltzaileek albumetatik argazkietara, etiketetara, mapetara, etab. modu errazean mugi ahal izatea da.
-Aves Androidera (KitKatetik Android 13ra, Android TV barne) egiten da ezaugarri ugarirekin: widgetak, aplikazioko lasterbideak, pantaila-babeslea eta bilaketa globala. Baita ere, media-bisore edo -hautagailu bezala erabil daiteke.
\ No newline at end of file
+Aves Androidera (KitKatetik Android 14ra, Android TV barne) egiten da ezaugarri ugarirekin: widgetak, aplikazioko lasterbideak, pantaila-babeslea eta bilaketa globala. Baita ere, media-bisore edo -hautagailu bezala erabil daiteke.
diff --git a/fastlane/metadata/android/fa/full_description.txt b/fastlane/metadata/android/fa/full_description.txt
index 6c92748f8..6b96ec3ea 100644
--- a/fastlane/metadata/android/fa/full_description.txt
+++ b/fastlane/metadata/android/fa/full_description.txt
@@ -2,4 +2,4 @@
Navigation and search is an important part of Aves. The goal is for users to easily flow from albums to photos to tags to maps, etc.
-Aves integrates with Android (from KitKat to Android 13, including Android TV) with features such as widgets, app shortcuts, screen saver and global search handling. It also works as a media viewer and picker.
\ No newline at end of file
+Aves integrates with Android (from KitKat to Android 14, including Android TV) with features such as widgets, app shortcuts, screen saver and global search handling. It also works as a media viewer and picker.
diff --git a/fastlane/metadata/android/fi/full_description.txt b/fastlane/metadata/android/fi/full_description.txt
index 6c92748f8..6b96ec3ea 100644
--- a/fastlane/metadata/android/fi/full_description.txt
+++ b/fastlane/metadata/android/fi/full_description.txt
@@ -2,4 +2,4 @@
Navigation and search is an important part of Aves. The goal is for users to easily flow from albums to photos to tags to maps, etc.
-Aves integrates with Android (from KitKat to Android 13, including Android TV) with features such as widgets, app shortcuts, screen saver and global search handling. It also works as a media viewer and picker.
\ No newline at end of file
+Aves integrates with Android (from KitKat to Android 14, including Android TV) with features such as widgets, app shortcuts, screen saver and global search handling. It also works as a media viewer and picker.
diff --git a/fastlane/metadata/android/fr/full_description.txt b/fastlane/metadata/android/fr/full_description.txt
index 0c83cfb83..9358d7cf1 100644
--- a/fastlane/metadata/android/fr/full_description.txt
+++ b/fastlane/metadata/android/fr/full_description.txt
@@ -2,4 +2,4 @@
La navigation et la recherche sont une partie importante d’Aves. Le but est que les utilisateurs puissent passer facilement des albums aux photos, des photos aux tags, des tags aux cartes, etc.
-Aves s’intègre avec Android (de KitKat à Android 13, y compris Android TV) avec des fonctionnalités telles que les widgets, les raccourcis d’application, économiseur d’écran et la recherche globale. Il est également possible de l’utiliser comme visionneuse et sélecteur de médias.
\ No newline at end of file
+Aves s’intègre avec Android (de KitKat à Android 14, y compris Android TV) avec des fonctionnalités telles que les widgets, les raccourcis d’application, économiseur d’écran et la recherche globale. Il est également possible de l’utiliser comme visionneuse et sélecteur de médias.
diff --git a/fastlane/metadata/android/gl/full_description.txt b/fastlane/metadata/android/gl/full_description.txt
index 548d3fe17..6e3b9f2cf 100644
--- a/fastlane/metadata/android/gl/full_description.txt
+++ b/fastlane/metadata/android/gl/full_description.txt
@@ -2,4 +2,4 @@
A navegación e busca é unha parte importante de Aves. O obxectivo é que os usuarios poidan fluír facilmente de álbums a fotos, a etiquetas a mapas, etc.
-Aves intégrase con Android (desde KitKat ata Android 13, incluíndo Android TV) con funcións como complementos, atallos de aplicacións, salvapantallas e busca global. Tamén funciona como visor e selector de medios.
\ No newline at end of file
+Aves intégrase con Android (desde KitKat ata Android 14, incluíndo Android TV) con funcións como complementos, atallos de aplicacións, salvapantallas e busca global. Tamén funciona como visor e selector de medios.
diff --git a/fastlane/metadata/android/he/full_description.txt b/fastlane/metadata/android/he/full_description.txt
index 6c92748f8..6b96ec3ea 100644
--- a/fastlane/metadata/android/he/full_description.txt
+++ b/fastlane/metadata/android/he/full_description.txt
@@ -2,4 +2,4 @@
Navigation and search is an important part of Aves. The goal is for users to easily flow from albums to photos to tags to maps, etc.
-Aves integrates with Android (from KitKat to Android 13, including Android TV) with features such as widgets, app shortcuts, screen saver and global search handling. It also works as a media viewer and picker.
\ No newline at end of file
+Aves integrates with Android (from KitKat to Android 14, including Android TV) with features such as widgets, app shortcuts, screen saver and global search handling. It also works as a media viewer and picker.
diff --git a/fastlane/metadata/android/hi/full_description.txt b/fastlane/metadata/android/hi/full_description.txt
index 6c92748f8..6b96ec3ea 100644
--- a/fastlane/metadata/android/hi/full_description.txt
+++ b/fastlane/metadata/android/hi/full_description.txt
@@ -2,4 +2,4 @@
Navigation and search is an important part of Aves. The goal is for users to easily flow from albums to photos to tags to maps, etc.
-Aves integrates with Android (from KitKat to Android 13, including Android TV) with features such as widgets, app shortcuts, screen saver and global search handling. It also works as a media viewer and picker.
\ No newline at end of file
+Aves integrates with Android (from KitKat to Android 14, including Android TV) with features such as widgets, app shortcuts, screen saver and global search handling. It also works as a media viewer and picker.
diff --git a/fastlane/metadata/android/hu/full_description.txt b/fastlane/metadata/android/hu/full_description.txt
index 65ec60bf4..614f6266e 100644
--- a/fastlane/metadata/android/hu/full_description.txt
+++ b/fastlane/metadata/android/hu/full_description.txt
@@ -2,4 +2,4 @@ Az Aves mindenféle képet és videót képes kezelni, beleértve a tipik
A navigáció és a keresés fontos része az Aves-nek. A cél, hogy a felhasználók egyszerűen tudjanak váltani az albumokról a fotókra, címkézni vagy helyadatokkal ellátni az elemeket, stb.
-Az Aves beépül az Android-ba (a KitKat-tól az Android 13-ig, beleértve az Android TV-t) olyan funkciókkal, mint a widgetek, alkalmazás parancsikonok, képernyővédő és globális keresés kezelése. Média fájlok megnyitására és kezelésére is használható.
\ No newline at end of file
+Az Aves beépül az Android-ba (a KitKat-tól az Android 14-ig, beleértve az Android TV-t) olyan funkciókkal, mint a widgetek, alkalmazás parancsikonok, képernyővédő és globális keresés kezelése. Média fájlok megnyitására és kezelésére is használható.
diff --git a/fastlane/metadata/android/id/full_description.txt b/fastlane/metadata/android/id/full_description.txt
index 3c18c062f..c0d9d1c9a 100644
--- a/fastlane/metadata/android/id/full_description.txt
+++ b/fastlane/metadata/android/id/full_description.txt
@@ -2,4 +2,4 @@
Navigasi dan pencarian merupakan bagian penting dari Aves. Tujuannya adalah agar pengguna dengan mudah mengalir dari album ke foto ke tag ke peta, dll.
-Aves mengintegrasi dengan Android (dari Kitkat ke Android 13) dengan fitur-fitur seperti pintasan aplikasi, jalan pintas aplikasi, screen saver dan pencarian global penanganan. Ini juga berfungsi sebagai penampil dan pemilih media.
\ No newline at end of file
+Aves mengintegrasi dengan Android (dari Kitkat ke Android 14) dengan fitur-fitur seperti pintasan aplikasi, jalan pintas aplikasi, screen saver dan pencarian global penanganan. Ini juga berfungsi sebagai penampil dan pemilih media.
diff --git a/fastlane/metadata/android/is/full_description.txt b/fastlane/metadata/android/is/full_description.txt
index 6c92748f8..6b96ec3ea 100644
--- a/fastlane/metadata/android/is/full_description.txt
+++ b/fastlane/metadata/android/is/full_description.txt
@@ -2,4 +2,4 @@
Navigation and search is an important part of Aves. The goal is for users to easily flow from albums to photos to tags to maps, etc.
-Aves integrates with Android (from KitKat to Android 13, including Android TV) with features such as widgets, app shortcuts, screen saver and global search handling. It also works as a media viewer and picker.
\ No newline at end of file
+Aves integrates with Android (from KitKat to Android 14, including Android TV) with features such as widgets, app shortcuts, screen saver and global search handling. It also works as a media viewer and picker.
diff --git a/fastlane/metadata/android/it/full_description.txt b/fastlane/metadata/android/it/full_description.txt
index 463c23554..0b1afa53f 100644
--- a/fastlane/metadata/android/it/full_description.txt
+++ b/fastlane/metadata/android/it/full_description.txt
@@ -2,4 +2,4 @@
Navigazione e ricerca sono una parte importante di Aves. L'obiettivo è che gli utenti passino facilmente dagli album alle foto, ai tag, alle mappe, ecc.
-Aves si integra con Android (da KitKat ad Android 13, anche Android TV) con funzionalità come widget, scorciatoie app, salvaschermo e gestione della ricerca globale. Funziona anche come visualizzazione e raccolta di media.
\ No newline at end of file
+Aves si integra con Android (da KitKat ad Android 14, anche Android TV) con funzionalità come widget, scorciatoie app, salvaschermo e gestione della ricerca globale. Funziona anche come visualizzazione e raccolta di media.
diff --git a/fastlane/metadata/android/ja/full_description.txt b/fastlane/metadata/android/ja/full_description.txt
index 996e794a5..bd93f6622 100644
--- a/fastlane/metadata/android/ja/full_description.txt
+++ b/fastlane/metadata/android/ja/full_description.txt
@@ -2,4 +2,4 @@
ナビゲーションと検索は、Avesの重要な部分です。アルバムから写真、タグ、地図などへ簡単に移動できます。
-Avesは、アプリショートカットやグローバル検索などの機能を、Android(API 19から33まで、つまりAndroid 4.4から13 Lまで)と統合しています。また、メディアビューワーやメディアピッカーとしても機能します。
\ No newline at end of file
+Avesは、アプリショートカットやグローバル検索などの機能を、Android(API 19から34まで、つまりAndroid 4.4から14 Lまで)と統合しています。また、メディアビューワーやメディアピッカーとしても機能します。
diff --git a/fastlane/metadata/android/kn/full_description.txt b/fastlane/metadata/android/kn/full_description.txt
index 6c92748f8..6b96ec3ea 100644
--- a/fastlane/metadata/android/kn/full_description.txt
+++ b/fastlane/metadata/android/kn/full_description.txt
@@ -2,4 +2,4 @@
Navigation and search is an important part of Aves. The goal is for users to easily flow from albums to photos to tags to maps, etc.
-Aves integrates with Android (from KitKat to Android 13, including Android TV) with features such as widgets, app shortcuts, screen saver and global search handling. It also works as a media viewer and picker.
\ No newline at end of file
+Aves integrates with Android (from KitKat to Android 14, including Android TV) with features such as widgets, app shortcuts, screen saver and global search handling. It also works as a media viewer and picker.
diff --git a/fastlane/metadata/android/ko/full_description.txt b/fastlane/metadata/android/ko/full_description.txt
index 6c92748f8..6b96ec3ea 100644
--- a/fastlane/metadata/android/ko/full_description.txt
+++ b/fastlane/metadata/android/ko/full_description.txt
@@ -2,4 +2,4 @@
Navigation and search is an important part of Aves. The goal is for users to easily flow from albums to photos to tags to maps, etc.
-Aves integrates with Android (from KitKat to Android 13, including Android TV) with features such as widgets, app shortcuts, screen saver and global search handling. It also works as a media viewer and picker.
\ No newline at end of file
+Aves integrates with Android (from KitKat to Android 14, including Android TV) with features such as widgets, app shortcuts, screen saver and global search handling. It also works as a media viewer and picker.
diff --git a/fastlane/metadata/android/lt/full_description.txt b/fastlane/metadata/android/lt/full_description.txt
index db97f4f98..246bda3c0 100644
--- a/fastlane/metadata/android/lt/full_description.txt
+++ b/fastlane/metadata/android/lt/full_description.txt
@@ -2,4 +2,4 @@
Naršymas ir paieška yra svarbi „Aves” dalis. Tikslas yra, kad vartotojai galėtų lengvai pereiti nuo albumų prie nuotraukų, žymų, žemėlapių ir kt.
-„Aves” integruojasi su „Android” (nuo 19 iki 33 API, t. y. nuo „KitKat” iki 13 versijos „Android”) su tokiomis funkcijomis kaip valdiklių, programėlių nuorodų , ekrano užsklandų ir globalios paieškos palaikymu. Ji taip pat veikia kaip medijos peržiūros priemonė ir rinkiklis.
\ No newline at end of file
+„Aves” integruojasi su „Android” (nuo 19 iki 34 API, t. y. nuo „KitKat” iki 14 versijos „Android”) su tokiomis funkcijomis kaip valdiklių, programėlių nuorodų , ekrano užsklandų ir globalios paieškos palaikymu. Ji taip pat veikia kaip medijos peržiūros priemonė ir rinkiklis.
diff --git a/fastlane/metadata/android/ml/full_description.txt b/fastlane/metadata/android/ml/full_description.txt
index 6c92748f8..6b96ec3ea 100644
--- a/fastlane/metadata/android/ml/full_description.txt
+++ b/fastlane/metadata/android/ml/full_description.txt
@@ -2,4 +2,4 @@
Navigation and search is an important part of Aves. The goal is for users to easily flow from albums to photos to tags to maps, etc.
-Aves integrates with Android (from KitKat to Android 13, including Android TV) with features such as widgets, app shortcuts, screen saver and global search handling. It also works as a media viewer and picker.
\ No newline at end of file
+Aves integrates with Android (from KitKat to Android 14, including Android TV) with features such as widgets, app shortcuts, screen saver and global search handling. It also works as a media viewer and picker.
diff --git a/fastlane/metadata/android/my/full_description.txt b/fastlane/metadata/android/my/full_description.txt
index ff89ddf0b..44d1a23cf 100644
--- a/fastlane/metadata/android/my/full_description.txt
+++ b/fastlane/metadata/android/my/full_description.txt
@@ -2,4 +2,4 @@
အလွယ်တကူ ရှာဖွေကြည့်ရှုနိုင်တာက Aves ရဲ့ အဓိကကျတဲ့အစိတ်အပိုင်းတစ်ခုဖြစ်ပါတယ်။ အသုံးပြုသူတွေကို အယ်လ်ဘမ်တွေကနေ ပုံတွေ၊ ပုံတွေကနေ tag တွေ၊ tag တွေကနေ မြေပုံတွေ၊ အစရှိသဖြင့် အလွယ်လေးကူးပြောင်းနိုင်စေဖို့က Aves ရဲ့ ပန်းတိုင်ဖြစ်ပါတယ်။
-Aves ဟာ Android (KitKat ကနေ Android 13 အထိ၊ Android တီဗီအပါအဝင်) ဖြင့်ပေါင်းစပ်ပြီး ဝစ်ဂျက်တွေ၊ အက်ပ်ဖြတ်လမ်းတိုတွေ၊ screen saver တွေနဲ့ နေရာအနှံ့ရှာဖွေမှုတွေကိုပါ ကိုင်တွယ်နိုင်ပါတယ်။ ဒါ့အပြင် မီဒီယာကြည့်ဖို့၊ မီဒီယာရွေးချယ်ဖို့အတွက်လည်း သုံးလို့ရပါသေးတယ်။
\ No newline at end of file
+Aves ဟာ Android (KitKat ကနေ Android 14 အထိ၊ Android တီဗီအပါအဝင်) ဖြင့်ပေါင်းစပ်ပြီး ဝစ်ဂျက်တွေ၊ အက်ပ်ဖြတ်လမ်းတိုတွေ၊ screen saver တွေနဲ့ နေရာအနှံ့ရှာဖွေမှုတွေကိုပါ ကိုင်တွယ်နိုင်ပါတယ်။ ဒါ့အပြင် မီဒီယာကြည့်ဖို့၊ မီဒီယာရွေးချယ်ဖို့အတွက်လည်း သုံးလို့ရပါသေးတယ်။
diff --git a/fastlane/metadata/android/nb-NO/full_description.txt b/fastlane/metadata/android/nb-NO/full_description.txt
index b2259273d..9f4e596b0 100644
--- a/fastlane/metadata/android/nb-NO/full_description.txt
+++ b/fastlane/metadata/android/nb-NO/full_description.txt
@@ -2,4 +2,4 @@
Navigasjon og søk er en viktig del av Aves. Målet er at brukere enkelt skal kunne ta seg fra album, til bilder, til etiketter, til kart, osv.
-Aves integrerer seg med Android (fra API 19 til 33, altså fra KitKat til Android 13) med funksjoner som f.eks. miniprogrammer, programsnarveier, skjermsparer og søk i hele programmet. Det fungerer også som mediaviser og utvelger.
\ No newline at end of file
+Aves integrerer seg med Android (fra API 19 til 34, altså fra KitKat til Android 14) med funksjoner som f.eks. miniprogrammer, programsnarveier, skjermsparer og søk i hele programmet. Det fungerer også som mediaviser og utvelger.
diff --git a/fastlane/metadata/android/nl/full_description.txt b/fastlane/metadata/android/nl/full_description.txt
index 8d13866ce..11f348f36 100644
--- a/fastlane/metadata/android/nl/full_description.txt
+++ b/fastlane/metadata/android/nl/full_description.txt
@@ -2,4 +2,4 @@
Navigatie en zoeken is een belangrijk onderdeel van Aves. Het doel is dat gebruikers gemakkelijk van albums naar foto's naar tags naar kaarten enz. kunnen gaan.
-Aves integrates with Android (from KitKat to Android 13, including Android TV) with features such as widgets, app shortcuts, screen saver and global search handling. It also works as a media viewer and picker.
\ No newline at end of file
+Aves integrates with Android (from KitKat to Android 14, including Android TV) with features such as widgets, app shortcuts, screen saver and global search handling. It also works as a media viewer and picker.
diff --git a/fastlane/metadata/android/nn/full_description.txt b/fastlane/metadata/android/nn/full_description.txt
index ed514a8df..0ecaa08de 100644
--- a/fastlane/metadata/android/nn/full_description.txt
+++ b/fastlane/metadata/android/nn/full_description.txt
@@ -2,4 +2,4 @@
Navigering og søk har mykje å sei i Aves. Målet er at ein skal lett kunne gå ifrå album, til bilete, til merkelappar, til kart, osv.
-Aves integrates with Android (from KitKat to Android 13, including Android TV) with features such as widgets, app shortcuts, screen saver and global search handling. It also works as a media viewer and picker.
\ No newline at end of file
+Aves integrates with Android (from KitKat to Android 14, including Android TV) with features such as widgets, app shortcuts, screen saver and global search handling. It also works as a media viewer and picker.
diff --git a/fastlane/metadata/android/or/full_description.txt b/fastlane/metadata/android/or/full_description.txt
index 6c92748f8..6b96ec3ea 100644
--- a/fastlane/metadata/android/or/full_description.txt
+++ b/fastlane/metadata/android/or/full_description.txt
@@ -2,4 +2,4 @@
Navigation and search is an important part of Aves. The goal is for users to easily flow from albums to photos to tags to maps, etc.
-Aves integrates with Android (from KitKat to Android 13, including Android TV) with features such as widgets, app shortcuts, screen saver and global search handling. It also works as a media viewer and picker.
\ No newline at end of file
+Aves integrates with Android (from KitKat to Android 14, including Android TV) with features such as widgets, app shortcuts, screen saver and global search handling. It also works as a media viewer and picker.
diff --git a/fastlane/metadata/android/pl/full_description.txt b/fastlane/metadata/android/pl/full_description.txt
index c10a1a6c6..e0f0b7f36 100644
--- a/fastlane/metadata/android/pl/full_description.txt
+++ b/fastlane/metadata/android/pl/full_description.txt
@@ -2,4 +2,4 @@
Nawigacja i wyszukiwanie jest ważną częścią Aves. Celem jest aby użytkownicy mogli łatwo przechodzić od albumów do zdjęć, tagów, map itd.
-Aves integruje się z Androidem (od API 19 do 33, czyli od KitKata do Androida 13) z funkcjami takimi jak widżety, skróty do aplikacji, wygaszacz ekranu i obsługa globalnego wyszukiwania. Działa również jako przeglądarka i selektor mediów.
\ No newline at end of file
+Aves integruje się z Androidem (od API 19 do 34, czyli od KitKata do Androida 14) z funkcjami takimi jak widżety, skróty do aplikacji, wygaszacz ekranu i obsługa globalnego wyszukiwania. Działa również jako przeglądarka i selektor mediów.
diff --git a/fastlane/metadata/android/pt-BR/full_description.txt b/fastlane/metadata/android/pt-BR/full_description.txt
index 9cae013fe..a0550b001 100644
--- a/fastlane/metadata/android/pt-BR/full_description.txt
+++ b/fastlane/metadata/android/pt-BR/full_description.txt
@@ -2,4 +2,4 @@
Navegação e pesquisa é uma parte importante do Aves. O objetivo é que os usuários fluam facilmente de álbuns para fotos, etiquetas, mapas, etc.
-Aves integra com Android (de KitKat até Android 13, incluindo TVs Android) com recursos como widgets, atalhos de apps, protetor de tela e pesquisa global. Também funciona como um visualizador e selecionador de mídia.
\ No newline at end of file
+Aves integra com Android (de KitKat até Android 14, incluindo TVs Android) com recursos como widgets, atalhos de apps, protetor de tela e pesquisa global. Também funciona como um visualizador e selecionador de mídia.
diff --git a/fastlane/metadata/android/ro/full_description.txt b/fastlane/metadata/android/ro/full_description.txt
index 3914872df..e76ce6d7c 100644
--- a/fastlane/metadata/android/ro/full_description.txt
+++ b/fastlane/metadata/android/ro/full_description.txt
@@ -2,4 +2,4 @@
Navigația și căutarea sunt o parte importantă a Aves. Scopul este ca utilizatorii să treacă cu ușurință de la albume la fotografii la etichete la hărți etc.
-Aves se integrează cu Android (începând de la API 19 la 33, adică de la KitKat la Android 13) cu funcții precum widget-uri, comenzi rapide pentru aplicații, protector de ecran și gestionarea căutării globale. De asemenea, funcționează ca vizionator și selector de conținut media.
\ No newline at end of file
+Aves se integrează cu Android (începând de la API 19 la 34, adică de la KitKat la Android 14) cu funcții precum widget-uri, comenzi rapide pentru aplicații, protector de ecran și gestionarea căutării globale. De asemenea, funcționează ca vizionator și selector de conținut media.
diff --git a/fastlane/metadata/android/ru/full_description.txt b/fastlane/metadata/android/ru/full_description.txt
index 158e533fd..d09a7d4de 100644
--- a/fastlane/metadata/android/ru/full_description.txt
+++ b/fastlane/metadata/android/ru/full_description.txt
@@ -2,4 +2,4 @@
Навигация и поиск важные части Aves. Пользователи могут легко переходить от альбомов к фотографиям, тэгам, картам и т.д.
-Aves интегрируется с Android (от KitKat до Android 13, включая Android TV) предлагая такие возможности как виджеты, пользовательские ярлыки, скринсейвер и поддержку глобального поиска. Он так же работает как диалоговое окно для просмотра и выбора медиа.
\ No newline at end of file
+Aves интегрируется с Android (от KitKat до Android 14, включая Android TV) предлагая такие возможности как виджеты, пользовательские ярлыки, скринсейвер и поддержку глобального поиска. Он так же работает как диалоговое окно для просмотра и выбора медиа.
diff --git a/fastlane/metadata/android/sk/full_description.txt b/fastlane/metadata/android/sk/full_description.txt
index 74557d170..1e9788de0 100644
--- a/fastlane/metadata/android/sk/full_description.txt
+++ b/fastlane/metadata/android/sk/full_description.txt
@@ -2,4 +2,4 @@
Navigácia a vyhľadávanie je dôležitou súčasťou aplikácie Aves. Jej cieľom je poskytnúť užívateľom jednoduchý prechod z albumov, do fotiek, tagov, máp, atď.
-Aves je schopný pracovať s Android (od KitKat do Android 13, včetne Android TV) a ponúka rozšírenia ako miniaplikácie (widgety), skratky aplikácie, šetrič obrazovky a globálne vyhľadávanie. Rovnako poskytuje prehľadávnie médií.
\ No newline at end of file
+Aves je schopný pracovať s Android (od KitKat do Android 14, včetne Android TV) a ponúka rozšírenia ako miniaplikácie (widgety), skratky aplikácie, šetrič obrazovky a globálne vyhľadávanie. Rovnako poskytuje prehľadávnie médií.
diff --git a/fastlane/metadata/android/sl/full_description.txt b/fastlane/metadata/android/sl/full_description.txt
index 6c92748f8..6b96ec3ea 100644
--- a/fastlane/metadata/android/sl/full_description.txt
+++ b/fastlane/metadata/android/sl/full_description.txt
@@ -2,4 +2,4 @@
Navigation and search is an important part of Aves. The goal is for users to easily flow from albums to photos to tags to maps, etc.
-Aves integrates with Android (from KitKat to Android 13, including Android TV) with features such as widgets, app shortcuts, screen saver and global search handling. It also works as a media viewer and picker.
\ No newline at end of file
+Aves integrates with Android (from KitKat to Android 14, including Android TV) with features such as widgets, app shortcuts, screen saver and global search handling. It also works as a media viewer and picker.
diff --git a/fastlane/metadata/android/th/full_description.txt b/fastlane/metadata/android/th/full_description.txt
index 6c92748f8..6b96ec3ea 100644
--- a/fastlane/metadata/android/th/full_description.txt
+++ b/fastlane/metadata/android/th/full_description.txt
@@ -2,4 +2,4 @@
Navigation and search is an important part of Aves. The goal is for users to easily flow from albums to photos to tags to maps, etc.
-Aves integrates with Android (from KitKat to Android 13, including Android TV) with features such as widgets, app shortcuts, screen saver and global search handling. It also works as a media viewer and picker.
\ No newline at end of file
+Aves integrates with Android (from KitKat to Android 14, including Android TV) with features such as widgets, app shortcuts, screen saver and global search handling. It also works as a media viewer and picker.
diff --git a/fastlane/metadata/android/tr/full_description.txt b/fastlane/metadata/android/tr/full_description.txt
index c966a3094..96fd599be 100644
--- a/fastlane/metadata/android/tr/full_description.txt
+++ b/fastlane/metadata/android/tr/full_description.txt
@@ -2,4 +2,4 @@
Gezinme ve arama Aves'in önemli bir parçasıdır. Amaç, kullanıcıların albümlerden fotoğraflara, etiketlerden haritalara vb. kolayca geçmesini sağlamaktır.
-Aves, uygulama kısayolları ve global arama işleme gibi özelliklerle Android (API 19'dan 33'ye, yani KitKat'tan Android 13'ye kadar) ile entegre olur. Ayrıca bir medya görüntüleyici ve alıcı olarak da çalışır.
\ No newline at end of file
+Aves, uygulama kısayolları ve global arama işleme gibi özelliklerle Android (API 19'dan 34'ye, yani KitKat'tan Android 14'ye kadar) ile entegre olur. Ayrıca bir medya görüntüleyici ve alıcı olarak da çalışır.
diff --git a/fastlane/metadata/android/uk/full_description.txt b/fastlane/metadata/android/uk/full_description.txt
index 760891c90..cc81f9cd5 100644
--- a/fastlane/metadata/android/uk/full_description.txt
+++ b/fastlane/metadata/android/uk/full_description.txt
@@ -2,4 +2,4 @@
Навігація та пошук є важливою частиною Aves. Мета полягає в тому, щоб користувачі легко переходили від альбомів до фотографій, від тегів до карт тощо.
-Aves інтегрується з Android (від KitKat до Android 13, включаючи Android TV) пропонуючи такі можливості як віджети, ярлики додатка, заставка екрану та работа з глобальним пошуком. Він також працює як переглядач і засоб вибору медіа.
\ No newline at end of file
+Aves інтегрується з Android (від KitKat до Android 14, включаючи Android TV) пропонуючи такі можливості як віджети, ярлики додатка, заставка екрану та работа з глобальним пошуком. Він також працює як переглядач і засоб вибору медіа.
diff --git a/fastlane/metadata/android/vi/full_description.txt b/fastlane/metadata/android/vi/full_description.txt
index f952f3b18..fa415ff0c 100644
--- a/fastlane/metadata/android/vi/full_description.txt
+++ b/fastlane/metadata/android/vi/full_description.txt
@@ -2,4 +2,4 @@
Điều hướng và tìm kiếm là một phần quan trọng của Aves. Mục tiêu là để người dùng dễ dàng chuyển từ album sang ảnh sang thẻ sang bản đồ, v.v.
-Aves tương thích với Android (từ KitKat đến Android 13, bao gồm cả Android TV) với các tính năng như widget, phím tắt ứng dụng, trình bảo vệ màn hình và xử lý tìm kiếm toàn hệ thống. Nó cũng hoạt động như một trình xem và lựa chọn phương tiện.
\ No newline at end of file
+Aves tương thích với Android (từ KitKat đến Android 14, bao gồm cả Android TV) với các tính năng như widget, phím tắt ứng dụng, trình bảo vệ màn hình và xử lý tìm kiếm toàn hệ thống. Nó cũng hoạt động như một trình xem và lựa chọn phương tiện.
diff --git a/fastlane/metadata/android/vi/images/feature_graphics.png b/fastlane/metadata/android/vi/images/featureGraphic.png
similarity index 100%
rename from fastlane/metadata/android/vi/images/feature_graphics.png
rename to fastlane/metadata/android/vi/images/featureGraphic.png
diff --git a/fastlane/metadata/android/zh-CN/full_description.txt b/fastlane/metadata/android/zh-CN/full_description.txt
index b8352fc7e..429d20c02 100644
--- a/fastlane/metadata/android/zh-CN/full_description.txt
+++ b/fastlane/metadata/android/zh-CN/full_description.txt
@@ -2,4 +2,4 @@
导航与搜索是 Aves 的核心功能之一,旨在帮助用户在相册、照片、标签、地图等之间轻松切换。
-Aves 与 Android(API 19-33,即从 KitKat 到 Android 13)集成,具有快捷方式和全局搜索等功能。它还可用作媒体查看器和选择器。
\ No newline at end of file
+Aves 与 Android(API 19-34,即从 KitKat 到 Android 14)集成,具有快捷方式和全局搜索等功能。它还可用作媒体查看器和选择器。
diff --git a/fastlane/metadata/android/zh-Hant/full_description.txt b/fastlane/metadata/android/zh-Hant/full_description.txt
index 102982150..96c231562 100644
--- a/fastlane/metadata/android/zh-Hant/full_description.txt
+++ b/fastlane/metadata/android/zh-Hant/full_description.txt
@@ -2,4 +2,4 @@
瀏覽和搜尋 是 Aves重要的一部份. 目的是為了讓使用者能夠輕易的從相簿, 相片, 標籤, 地圖, 等等之間順暢切換.
-Aves 與 Android (從 KitKat 到 Android 13, 包括 Android TV) 整合, 具有特色像是 小工具, app 捷徑, 螢幕保護程式 和 全域搜尋 等功能. 還可以當成 媒體檢視和選擇器.
\ No newline at end of file
+Aves 與 Android (從 KitKat 到 Android 14, 包括 Android TV) 整合, 具有特色像是 小工具, app 捷徑, 螢幕保護程式 和 全域搜尋 等功能. 還可以當成 媒體檢視和選擇器.
diff --git a/lib/l10n/app_ar.arb b/lib/l10n/app_ar.arb
index 73b65e109..12836dbde 100644
--- a/lib/l10n/app_ar.arb
+++ b/lib/l10n/app_ar.arb
@@ -27,7 +27,7 @@
"@doNotAskAgain": {},
"welcomeTermsToggle": "أوافق على الشروط",
"@welcomeTermsToggle": {},
- "doubleBackExitMessage": "اضغط على \"رجوع\" مرة أخرى للخروج.",
+ "doubleBackExitMessage": "اضغط على «رجوع» مرة أخرى للخروج.",
"@doubleBackExitMessage": {},
"hideButtonLabel": "إخفاء",
"@hideButtonLabel": {},
@@ -39,7 +39,7 @@
"@changeTooltip": {},
"actionRemove": "إزالة",
"@actionRemove": {},
- "appName": "أيفيس",
+ "appName": "Aves",
"@appName": {},
"welcomeOptional": "اختياري",
"@welcomeOptional": {},
@@ -53,7 +53,7 @@
"@previousTooltip": {},
"welcomeMessage": "مرحبا بكم في أيفيس",
"@welcomeMessage": {},
- "applyButtonLabel": "تطبيق",
+ "applyButtonLabel": "تقديم",
"@applyButtonLabel": {},
"nextButtonLabel": "التالي",
"@nextButtonLabel": {},
@@ -70,5 +70,1453 @@
"tagEditorPageAddTagTooltip": "إضافة علامة",
"@tagEditorPageAddTagTooltip": {},
"albumScreenRecordings": "تسجيل الشاشة",
- "@albumScreenRecordings": {}
+ "@albumScreenRecordings": {},
+ "chipActionSetCover": "تعيين كغلاف",
+ "@chipActionSetCover": {},
+ "saveCopyButtonLabel": "حفظ نسخة",
+ "@saveCopyButtonLabel": {},
+ "chipActionFilterOut": "تصفية أو استبعاد",
+ "@chipActionFilterOut": {},
+ "chipActionHide": "يخفي",
+ "@chipActionHide": {},
+ "sourceStateCataloguing": "تصنيف",
+ "@sourceStateCataloguing": {},
+ "chipActionDelete": "يمسح",
+ "@chipActionDelete": {},
+ "sourceStateLoading": "تحميل",
+ "@sourceStateLoading": {},
+ "sourceStateLocatingCountries": "تحديد مواقع الدول",
+ "@sourceStateLocatingCountries": {},
+ "chipActionFilterIn": "تصفية أو اختيار",
+ "@chipActionFilterIn": {},
+ "chipActionPin": "تثبيت في الأعلى",
+ "@chipActionPin": {},
+ "chipActionRename": "إعادة تسمية",
+ "@chipActionRename": {},
+ "chipActionGoToPlacePage": "عرض في الأماكن",
+ "@chipActionGoToPlacePage": {},
+ "chipActionGoToAlbumPage": "عرض في الألبومات",
+ "@chipActionGoToAlbumPage": {},
+ "chipActionLock": "قَفل",
+ "@chipActionLock": {},
+ "pickTooltip": "اختيار",
+ "@pickTooltip": {},
+ "chipActionGoToCountryPage": "عرض في الدول",
+ "@chipActionGoToCountryPage": {},
+ "applyTooltip": "يتقدم",
+ "@applyTooltip": {},
+ "chipActionUnpin": "إلغاء تثبيت من الأعلى",
+ "@chipActionUnpin": {},
+ "chipActionGoToTagPage": "عرض في الوسوم",
+ "@chipActionGoToTagPage": {},
+ "sourceStateLocatingPlaces": "تحديد المواقع",
+ "@sourceStateLocatingPlaces": {},
+ "aboutCreditsWorldAtlas2": "بموجب ترخيص ISC.",
+ "@aboutCreditsWorldAtlas2": {},
+ "binEntriesConfirmationDialogMessage": "{count, plural, =1{هل تريد نقل هذا العنصر إلى سلة المحذوفات؟} other{حرك هذه {count}العناصر إلى سلة المحذوفات؟}}",
+ "@binEntriesConfirmationDialogMessage": {
+ "placeholders": {
+ "count": {}
+ }
+ },
+ "settingsNavigationDrawerAddAlbum": "إضافة ألبوم",
+ "@settingsNavigationDrawerAddAlbum": {},
+ "settingsPrivacySectionTitle": "خصوصية",
+ "@settingsPrivacySectionTitle": {},
+ "settingsEnableBinSubtitle": "الاحتفاظ بالعناصر المحذوفة لمدة 30 يومًا",
+ "@settingsEnableBinSubtitle": {},
+ "viewerInfoPageTitle": "معلومات",
+ "@viewerInfoPageTitle": {},
+ "mapAttributionStamen": "بيانات الخريطة © [OpenStreetMap](https://www.openstreetmap.org/copyright) المساهمين • البلاط بواسطة [Stamen Design](https://stamen.com), [CC BY 3.0](https://creativecommons.org/licenses/by/3.0)",
+ "@mapAttributionStamen": {},
+ "widgetOpenPageViewer": "افتح العارض",
+ "@widgetOpenPageViewer": {},
+ "setCoverDialogLatest": "أحدث عنصر",
+ "@setCoverDialogLatest": {},
+ "settingsThumbnailShowRating": "عرض التقييم",
+ "@settingsThumbnailShowRating": {},
+ "editEntryRatingDialogTitle": "تقييم",
+ "@editEntryRatingDialogTitle": {},
+ "entryInfoActionExportMetadata": "تصدير البيانات الوصفية",
+ "@entryInfoActionExportMetadata": {},
+ "aboutDataUsageMisc": "منوعات",
+ "@aboutDataUsageMisc": {},
+ "editorActionTransform": "تحول",
+ "@editorActionTransform": {},
+ "collectionExportFailureFeedback": "{count, plural, =1{فشل تصدير صفحة واحدة} other{فشل التصدير {count} pages}}",
+ "@collectionExportFailureFeedback": {
+ "placeholders": {
+ "count": {}
+ }
+ },
+ "vaultDialogLockModeWhenScreenOff": "القفل عند إيقاف تشغيل الشاشة",
+ "@vaultDialogLockModeWhenScreenOff": {},
+ "videoResumeDialogMessage": "هل ترغب في استئناف التشغيل في {time}؟",
+ "@videoResumeDialogMessage": {
+ "placeholders": {
+ "time": {
+ "type": "String",
+ "example": "13:37"
+ }
+ }
+ },
+ "albumVideoCaptures": "الفيديوهات الملتقطة",
+ "@albumVideoCaptures": {},
+ "wallpaperUseScrollEffect": "استخدم تأثير التمرير على الشاشة الرئيسية",
+ "@wallpaperUseScrollEffect": {},
+ "coordinateDms": "{coordinate} {direction}",
+ "@coordinateDms": {
+ "placeholders": {
+ "coordinate": {
+ "type": "String",
+ "example": "38° 41′ 47.72″"
+ },
+ "direction": {
+ "type": "String",
+ "example": "S"
+ }
+ }
+ },
+ "editEntryDateDialogSetCustom": "تحديد تاريخ مخصص",
+ "@editEntryDateDialogSetCustom": {},
+ "mapStyleGoogleTerrain": "خرائط جوجل (التضاريس)",
+ "@mapStyleGoogleTerrain": {},
+ "statsTopTagsSectionTitle": "أهم العلامات",
+ "@statsTopTagsSectionTitle": {},
+ "settingsSubtitleThemeTextAlignmentDialogTitle": "مُحاذاة النص",
+ "@settingsSubtitleThemeTextAlignmentDialogTitle": {},
+ "settingsSearchEmpty": "لا يوجد إعداد مطابق",
+ "@settingsSearchEmpty": {},
+ "removeEntryMetadataDialogMore": "أكثر",
+ "@removeEntryMetadataDialogMore": {},
+ "viewerActionLock": "قفل المعاينة",
+ "@viewerActionLock": {},
+ "pinDialogConfirm": "تأكيد الرمز السري",
+ "@pinDialogConfirm": {},
+ "settingsViewerSlideshowPageTitle": "عرض الشرائح",
+ "@settingsViewerSlideshowPageTitle": {},
+ "tooManyItemsErrorDialogMessage": "حاول مرة أخرى باستخدام عدد أقل من العناصر.",
+ "@tooManyItemsErrorDialogMessage": {},
+ "collectionActionEdit": "تحرير",
+ "@collectionActionEdit": {},
+ "viewerInfoSearchSuggestionResolution": "دقة",
+ "@viewerInfoSearchSuggestionResolution": {},
+ "viewerTransitionSlide": "الإنزلاق",
+ "@viewerTransitionSlide": {},
+ "sortOrderLargestFirst": "الأكبر أولاً",
+ "@sortOrderLargestFirst": {},
+ "viewerTransitionParallax": "تأثير الشبكية",
+ "@viewerTransitionParallax": {},
+ "settingsViewerSectionTitle": "عارض",
+ "@settingsViewerSectionTitle": {},
+ "mapStyleStamenWatercolor": "ستايمن بالألوان المائية",
+ "@mapStyleStamenWatercolor": {},
+ "editEntryDateDialogSourceFileModifiedDate": "تاريخ تعديل الملف",
+ "@editEntryDateDialogSourceFileModifiedDate": {},
+ "editorTransformRotate": "تدوير",
+ "@editorTransformRotate": {},
+ "collectionEmptyFavourites": "لا يوجد مفضلة",
+ "@collectionEmptyFavourites": {},
+ "albumTierNew": "جديد",
+ "@albumTierNew": {},
+ "removeEntryMetadataDialogTitle": "ازالة البيانات الوصفية",
+ "@removeEntryMetadataDialogTitle": {},
+ "settingsLanguageTile": "اللغة",
+ "@settingsLanguageTile": {},
+ "drawerCollectionVideos": "الفيديوهات",
+ "@drawerCollectionVideos": {},
+ "videoResumptionModeNever": "أبداً",
+ "@videoResumptionModeNever": {},
+ "countryEmpty": "لا توجد دول",
+ "@countryEmpty": {},
+ "collectionSelectSectionTooltip": "اختر القسم",
+ "@collectionSelectSectionTooltip": {},
+ "settingsAllowInstalledAppAccessSubtitle": "يستخدم لتحسين عرض الألبوم",
+ "@settingsAllowInstalledAppAccessSubtitle": {},
+ "aboutLicensesBanner": "يستخدم هذا التطبيق الحزم والمكتبات مفتوحة المصدر التالية.",
+ "@aboutLicensesBanner": {},
+ "moveUndatedConfirmationDialogSetDate": "حفظ التواريخ",
+ "@moveUndatedConfirmationDialogSetDate": {},
+ "coordinateDmsNorth": "شمال",
+ "@coordinateDmsNorth": {},
+ "dateYesterday": "أمس",
+ "@dateYesterday": {},
+ "viewerInfoLabelDate": "تاريخ",
+ "@viewerInfoLabelDate": {},
+ "nameConflictStrategyReplace": "إستبدال",
+ "@nameConflictStrategyReplace": {},
+ "aboutDataUsageDatabase": "قاعدة البيانات",
+ "@aboutDataUsageDatabase": {},
+ "collectionMoveFailureFeedback": "{count, plural, =1{فشل في نقل عنصر واحد} other{فشل في النقل {count} items}}",
+ "@collectionMoveFailureFeedback": {
+ "placeholders": {
+ "count": {}
+ }
+ },
+ "videoLoopModeAlways": "دائماً",
+ "@videoLoopModeAlways": {},
+ "settingsRemoveAnimationsDialogTitle": "ازالة الرسوم المتحركة",
+ "@settingsRemoveAnimationsDialogTitle": {},
+ "tileLayoutMosaic": "فسيفساء",
+ "@tileLayoutMosaic": {},
+ "settingsSubtitleThemeTextColor": "لون الخط",
+ "@settingsSubtitleThemeTextColor": {},
+ "collectionDeselectSectionTooltip": "قم بإلغاء تحديد القسم",
+ "@collectionDeselectSectionTooltip": {},
+ "settingsKeepScreenOnTile": "إبقاء شاشة قيد التشغيل",
+ "@settingsKeepScreenOnTile": {},
+ "tileLayoutGrid": "شبكة",
+ "@tileLayoutGrid": {},
+ "settingsDisplayUseTvInterface": "واجهة أندرويد TV",
+ "@settingsDisplayUseTvInterface": {},
+ "settingsTimeToTakeActionTile": "حان الوقت لاتخاذ الإجراءات اللازمة",
+ "@settingsTimeToTakeActionTile": {},
+ "aboutCreditsWorldAtlas1": "يستخدم هذا التطبيق ملف TopoJSON من",
+ "@aboutCreditsWorldAtlas1": {},
+ "nameConflictDialogMultipleSourceMessage": "بعض الملفات لها نفس الاسم.",
+ "@nameConflictDialogMultipleSourceMessage": {},
+ "settingsVideoSectionTitle": "فيديو",
+ "@settingsVideoSectionTitle": {},
+ "appExportCovers": "أغلفة",
+ "@appExportCovers": {},
+ "viewerOpenPanoramaButtonLabel": "فتح البانوراما",
+ "@viewerOpenPanoramaButtonLabel": {},
+ "createAlbumButtonLabel": "إنشاء",
+ "@createAlbumButtonLabel": {},
+ "newAlbumDialogStorageLabel": "تخزين:",
+ "@newAlbumDialogStorageLabel": {},
+ "settingsSubtitleThemeBackgroundColor": "لون الخلفية",
+ "@settingsSubtitleThemeBackgroundColor": {},
+ "menuActionSlideshow": "عرض الشرائح",
+ "@menuActionSlideshow": {},
+ "vaultLockTypePassword": "كلمة سر",
+ "@vaultLockTypePassword": {},
+ "settingsThumbnailOverlayTile": "التراكب",
+ "@settingsThumbnailOverlayTile": {},
+ "settingsNavigationDrawerTabPages": "الصفحات",
+ "@settingsNavigationDrawerTabPages": {},
+ "settingsConfirmationDialogTitle": "نوافذ التأكيد الحوار",
+ "@settingsConfirmationDialogTitle": {},
+ "videoStreamSelectionDialogText": "ترجمات",
+ "@videoStreamSelectionDialogText": {},
+ "settingsVideoAutoPlay": "تشغيل تلقائي",
+ "@settingsVideoAutoPlay": {},
+ "settingsVideoEnableHardwareAcceleration": "تسريع الأجهزة",
+ "@settingsVideoEnableHardwareAcceleration": {},
+ "editEntryDateDialogShift": "يحول",
+ "@editEntryDateDialogShift": {},
+ "viewerInfoLabelCoordinates": "الإحداثيات",
+ "@viewerInfoLabelCoordinates": {},
+ "nameConflictDialogSingleSourceMessage": "بعض الملفات الموجودة في مجلد الوجهة لها نفس الاسم.",
+ "@nameConflictDialogSingleSourceMessage": {},
+ "exportEntryDialogFormat": "شكل:",
+ "@exportEntryDialogFormat": {},
+ "widgetOpenPageHome": "إفتح الرئيسية",
+ "@widgetOpenPageHome": {},
+ "mapStyleHuaweiNormal": "خرائط بيتال (هواوي)",
+ "@mapStyleHuaweiNormal": {},
+ "keepScreenOnAlways": "دائما",
+ "@keepScreenOnAlways": {},
+ "appExportSettings": "إعدادات",
+ "@appExportSettings": {},
+ "exportEntryDialogQuality": "جودة",
+ "@exportEntryDialogQuality": {},
+ "searchPlacesSectionTitle": "الأماكن",
+ "@searchPlacesSectionTitle": {},
+ "settingsCollectionSelectionQuickActionEditorBanner": "المس مع الاستمرار لتحريك الأزرار وتحديد الإجراءات التي يتم عرضها عند تحديد العناصر.",
+ "@settingsCollectionSelectionQuickActionEditorBanner": {},
+ "settingsSlideshowShuffle": "تشغيل عشوائي",
+ "@settingsSlideshowShuffle": {},
+ "settingsThumbnailSectionTitle": "الصور المصغرة",
+ "@settingsThumbnailSectionTitle": {},
+ "videoStreamSelectionDialogAudio": "صوت",
+ "@videoStreamSelectionDialogAudio": {},
+ "videoSpeedDialogLabel": "سرعة التشغيل",
+ "@videoSpeedDialogLabel": {},
+ "openMapPageTooltip": "عرض على صفحة الخريطة",
+ "@openMapPageTooltip": {},
+ "videoActionSkip10": "تقدم إلى الأمام لمدة 10 ثوانٍ",
+ "@videoActionSkip10": {},
+ "editEntryLocationDialogSetCustom": "تعيين الموقع المخصص",
+ "@editEntryLocationDialogSetCustom": {},
+ "viewerInfoUnknown": "مَجهول",
+ "@viewerInfoUnknown": {},
+ "displayRefreshRatePreferHighest": "أعلى معدل",
+ "@displayRefreshRatePreferHighest": {},
+ "settingsVideoShowVideos": "عرض الفيديوهات",
+ "@settingsVideoShowVideos": {},
+ "deleteEntriesConfirmationDialogMessage": "{count, plural, =1{هل تريد حذف هذا العنصر؟} other{احذف هذه {count} أغراض؟}}",
+ "@deleteEntriesConfirmationDialogMessage": {
+ "placeholders": {
+ "count": {}
+ }
+ },
+ "settingsViewerShowInformation": "مزيد من المعلومات",
+ "@settingsViewerShowInformation": {},
+ "placeEmpty": "لا توجد أماكن",
+ "@placeEmpty": {},
+ "settingsCollectionQuickActionsTile": "إجراءات سريعة",
+ "@settingsCollectionQuickActionsTile": {},
+ "editEntryDateDialogExtractFromTitle": "استخراج من العنوان",
+ "@editEntryDateDialogExtractFromTitle": {},
+ "settingsViewerOverlayTile": "تراكب",
+ "@settingsViewerOverlayTile": {},
+ "albumTierRegular": "آخرون",
+ "@albumTierRegular": {},
+ "settingsThumbnailShowFavouriteIcon": "إظهار الأيقونة المفضلة",
+ "@settingsThumbnailShowFavouriteIcon": {},
+ "aboutLinkLicense": "رخصة",
+ "@aboutLinkLicense": {},
+ "albumScreenshots": "لقطات الشاشة",
+ "@albumScreenshots": {},
+ "editEntryDateDialogTitle": "التاريخ والوقت",
+ "@editEntryDateDialogTitle": {},
+ "settingsSubtitleThemeTextPositionDialogTitle": "موضع النَص",
+ "@settingsSubtitleThemeTextPositionDialogTitle": {},
+ "viewerInfoLabelOwner": "المالك",
+ "@viewerInfoLabelOwner": {},
+ "editEntryLocationDialogLongitude": "خط الطول",
+ "@editEntryLocationDialogLongitude": {},
+ "setCoverDialogCustom": "مخصص",
+ "@setCoverDialogCustom": {},
+ "searchCountriesSectionTitle": "البلدان",
+ "@searchCountriesSectionTitle": {},
+ "settingsSlideshowIntervalTile": "فاصلة",
+ "@settingsSlideshowIntervalTile": {},
+ "settingsAskEverytime": "اسأل كل مرة",
+ "@settingsAskEverytime": {},
+ "editEntryDateDialogCopyField": "نسخة من تاريخ آخر",
+ "@editEntryDateDialogCopyField": {},
+ "searchTagsSectionTitle": "العلامات",
+ "@searchTagsSectionTitle": {},
+ "displayRefreshRatePreferLowest": "أدنى معدل",
+ "@displayRefreshRatePreferLowest": {},
+ "filterNoAddressLabel": "لا يوجد عنوان",
+ "@filterNoAddressLabel": {},
+ "settingsModificationWarningDialogMessage": "سيتم تعديل الإعدادات الأخرى.",
+ "@settingsModificationWarningDialogMessage": {},
+ "videoStartOverButtonLabel": "ابدأ من جديد",
+ "@videoStartOverButtonLabel": {},
+ "accessibilityAnimationsKeep": "الحفاظ على تأثيرات الشاشة",
+ "@accessibilityAnimationsKeep": {},
+ "settingsCollectionQuickActionEditorPageTitle": "اجراءات سريعة",
+ "@settingsCollectionQuickActionEditorPageTitle": {},
+ "policyPageTitle": "سياسة الخصوصية",
+ "@policyPageTitle": {},
+ "tileLayoutList": "قائمة",
+ "@tileLayoutList": {},
+ "settingsStorageAccessRevokeTooltip": "إبطال",
+ "@settingsStorageAccessRevokeTooltip": {},
+ "settingsSubtitleThemeTile": "ترجمات",
+ "@settingsSubtitleThemeTile": {},
+ "widgetDisplayedItemMostRecent": "الأحدث",
+ "@widgetDisplayedItemMostRecent": {},
+ "videoActionUnmute": "إلغاء كتم الصوت",
+ "@videoActionUnmute": {},
+ "appPickDialogNone": "لاشيء",
+ "@appPickDialogNone": {},
+ "filterMimeImageLabel": "صورة",
+ "@filterMimeImageLabel": {},
+ "settingsVideoGestureVerticalDragBrightnessVolume": "اسحب لأعلى أو لأسفل لضبط مستوى السطوع/الصوت",
+ "@settingsVideoGestureVerticalDragBrightnessVolume": {},
+ "settingsAccessibilitySectionTitle": "إمكانية الوصول",
+ "@settingsAccessibilitySectionTitle": {},
+ "settingsActionExport": "يصدّر",
+ "@settingsActionExport": {},
+ "aboutBugCopyInfoInstruction": "نسخ معلومات النظام",
+ "@aboutBugCopyInfoInstruction": {},
+ "filterNoTagLabel": "بدون علامات",
+ "@filterNoTagLabel": {},
+ "missingSystemFilePickerDialogMessage": "منتقي ملفات النظام مفقود أو معطل. يرجى تمكينه والمحاولة مرة أخرى.",
+ "@missingSystemFilePickerDialogMessage": {},
+ "viewerInfoViewXmlLinkText": "عرض ملف XML",
+ "@viewerInfoViewXmlLinkText": {},
+ "sortOrderOldestFirst": "الأقدم أولا",
+ "@sortOrderOldestFirst": {},
+ "collectionRenameFailureFeedback": "{count, plural, =1{فشلت إعادة تسمية عنصر واحد} other{فشلت إعادة التسمية {count} items}}",
+ "@collectionRenameFailureFeedback": {
+ "placeholders": {
+ "count": {}
+ }
+ },
+ "videoResumptionModeAlways": "دائماً",
+ "@videoResumptionModeAlways": {},
+ "tagEditorDiscardDialogMessage": "هل تريد تجاهل التغييرات؟",
+ "@tagEditorDiscardDialogMessage": {},
+ "collectionEditSuccessFeedback": "{count, plural, =1{تم تحريرعنصر واحد} other{تحرير {count} عناصر}}",
+ "@collectionEditSuccessFeedback": {
+ "placeholders": {
+ "count": {}
+ }
+ },
+ "wallpaperTargetLock": "شاشة القفل",
+ "@wallpaperTargetLock": {},
+ "coverDialogTabApp": "التطبيق",
+ "@coverDialogTabApp": {},
+ "settingsThumbnailShowMotionPhotoIcon": "إظهار أيقونة الصورة المتحركة",
+ "@settingsThumbnailShowMotionPhotoIcon": {},
+ "accessibilityAnimationsRemove": "منع تأثيرات الشاشة",
+ "@accessibilityAnimationsRemove": {},
+ "removeEntryMetadataMotionPhotoXmpWarningDialogMessage": "مطلوب XMP لتشغيل الفيديو داخل الصورة المتحركة.\n\nهل أنت متأكد أنك تريد إزالته؟",
+ "@removeEntryMetadataMotionPhotoXmpWarningDialogMessage": {},
+ "nameConflictStrategyRename": "إعادة تسمية",
+ "@nameConflictStrategyRename": {},
+ "settingsThumbnailShowRawIcon": "إظهار أيقونة الخام",
+ "@settingsThumbnailShowRawIcon": {},
+ "vaultLockTypePattern": "نمط",
+ "@vaultLockTypePattern": {},
+ "tagPageTitle": "العلامات",
+ "@tagPageTitle": {},
+ "collectionEmptyVideos": "لا توجد فيديوهات",
+ "@collectionEmptyVideos": {},
+ "entryActionRemoveFavourite": "إزالة من المفضلة",
+ "@entryActionRemoveFavourite": {},
+ "aboutCreditsSectionTitle": "الاعتمادات",
+ "@aboutCreditsSectionTitle": {},
+ "drawerAlbumPage": "الألبومات",
+ "@drawerAlbumPage": {},
+ "statsTopCountriesSectionTitle": "أهم الدول",
+ "@statsTopCountriesSectionTitle": {},
+ "settingsActionImport": "يستورد",
+ "@settingsActionImport": {},
+ "viewerInfoLabelSize": "مقاس",
+ "@viewerInfoLabelSize": {},
+ "locationPickerUseThisLocationButton": "استخدم هذا الموقع",
+ "@locationPickerUseThisLocationButton": {},
+ "settingsSlideshowFillScreen": "ملء الشاشة",
+ "@settingsSlideshowFillScreen": {},
+ "settingsHiddenFiltersBanner": "لن تظهر الصور ومقاطع الفيديو المطابقة للمرشحات المخفية في مجموعتك.",
+ "@settingsHiddenFiltersBanner": {},
+ "albumTierVaults": "خزائن",
+ "@albumTierVaults": {},
+ "viewerSetWallpaperButtonLabel": "تعيين خلفية",
+ "@viewerSetWallpaperButtonLabel": {},
+ "settingsVideoResumptionModeTile": "استئناف التشغيل",
+ "@settingsVideoResumptionModeTile": {},
+ "collectionGroupNone": "لا تجمع",
+ "@collectionGroupNone": {},
+ "searchRatingSectionTitle": "التقييمات",
+ "@searchRatingSectionTitle": {},
+ "vaultBinUsageDialogMessage": "تستخدم بعض الخزائن سلة المحذوفات.",
+ "@vaultBinUsageDialogMessage": {},
+ "collectionCopyFailureFeedback": "{count, plural, =1{فشل نسخ عنصر واحد} other{فشل النسخ {count} items}}",
+ "@collectionCopyFailureFeedback": {
+ "placeholders": {
+ "count": {}
+ }
+ },
+ "settingsDisabled": "غير مفعل",
+ "@settingsDisabled": {},
+ "settingsVideoGestureDoubleTapTogglePlay": "انقر نقرًا مزدوجًا للتشغيل/الإيقاف",
+ "@settingsVideoGestureDoubleTapTogglePlay": {},
+ "coordinateFormatDecimal": "الدرجات العشرية",
+ "@coordinateFormatDecimal": {},
+ "overlayHistogramLuminance": "الانارة",
+ "@overlayHistogramLuminance": {},
+ "coordinateDmsEast": "شرق",
+ "@coordinateDmsEast": {},
+ "filterAspectRatioLandscapeLabel": "طبيعي",
+ "@filterAspectRatioLandscapeLabel": {},
+ "albumTierApps": "تطبيقات",
+ "@albumTierApps": {},
+ "filterAspectRatioPortraitLabel": "لوحة",
+ "@filterAspectRatioPortraitLabel": {},
+ "settingsWidgetDisplayedItem": "العنصر المعروض",
+ "@settingsWidgetDisplayedItem": {},
+ "aboutBugSaveLogInstruction": "حفظ سجلات التطبيق في ملف",
+ "@aboutBugSaveLogInstruction": {},
+ "settingsActionImportDialogTitle": "يستورد",
+ "@settingsActionImportDialogTitle": {},
+ "filterTypeGeotiffLabel": "GeoTIFF",
+ "@filterTypeGeotiffLabel": {},
+ "entryActionRotateScreen": "تدوير الشاشة",
+ "@entryActionRotateScreen": {},
+ "albumGroupTier": "حسب الطبقة",
+ "@albumGroupTier": {},
+ "aboutBugReportInstruction": "تقرير على GitHub مع السجلات ومعلومات النظام",
+ "@aboutBugReportInstruction": {},
+ "addPathTooltip": "أضف المسار",
+ "@addPathTooltip": {},
+ "videoActionCaptureFrame": "التقاط الإطار",
+ "@videoActionCaptureFrame": {},
+ "patternDialogEnter": "أدخل النمط",
+ "@patternDialogEnter": {},
+ "settingsEnableBin": "استخدم سلة المحذوفات",
+ "@settingsEnableBin": {},
+ "entryActionViewMotionPhotoVideo": "فتح الفيديو",
+ "@entryActionViewMotionPhotoVideo": {},
+ "videoControlsNone": "لا شيء",
+ "@videoControlsNone": {},
+ "otherDirectoryDescription": "دليل «{name}»",
+ "@otherDirectoryDescription": {
+ "placeholders": {
+ "name": {
+ "type": "String",
+ "example": "Pictures",
+ "description": "the name of a specific directory"
+ }
+ }
+ },
+ "viewerTransitionZoomIn": "تكبير",
+ "@viewerTransitionZoomIn": {},
+ "drawerCollectionAll": "كل جمع",
+ "@drawerCollectionAll": {},
+ "collectionMoveSuccessFeedback": "{count, plural, =1{تم نقل عنصر واحد} other{نقل {count} عناصر}}",
+ "@collectionMoveSuccessFeedback": {
+ "placeholders": {
+ "count": {}
+ }
+ },
+ "settingsSubtitleThemeTextAlignmentLeft": "يسار",
+ "@settingsSubtitleThemeTextAlignmentLeft": {},
+ "settingsVideoGestureSideDoubleTapSeek": "انقر نقرًا مزدوجًا على حواف الشاشة للتقدم للأمام/للخلف",
+ "@settingsVideoGestureSideDoubleTapSeek": {},
+ "mapStyleHuaweiTerrain": "خرائط بيتال (التضاريس)",
+ "@mapStyleHuaweiTerrain": {},
+ "sortByItemCount": "حسب عدد العناصر",
+ "@sortByItemCount": {},
+ "sectionUnknown": "مجهول",
+ "@sectionUnknown": {},
+ "dateToday": "اليوم",
+ "@dateToday": {},
+ "filterNoTitleLabel": "بدون عنوان",
+ "@filterNoTitleLabel": {},
+ "videoStreamSelectionDialogNoSelection": "لا توجد مسارات أخرى.",
+ "@videoStreamSelectionDialogNoSelection": {},
+ "searchRecentSectionTitle": "مؤخرًا",
+ "@searchRecentSectionTitle": {},
+ "albumPickPageTitlePick": "اختر الألبوم",
+ "@albumPickPageTitlePick": {},
+ "videoPlaybackMuted": "تشغيل بدون صوت",
+ "@videoPlaybackMuted": {},
+ "settingsSubtitleThemeTextAlignmentRight": "يمين",
+ "@settingsSubtitleThemeTextAlignmentRight": {},
+ "menuActionMap": "خريطة",
+ "@menuActionMap": {},
+ "entryInfoActionRemoveMetadata": "إزالة البيانات الوصفية",
+ "@entryInfoActionRemoveMetadata": {},
+ "collectionActionMove": "الانتقال إلى الألبوم",
+ "@collectionActionMove": {},
+ "searchAlbumsSectionTitle": "الألبومات",
+ "@searchAlbumsSectionTitle": {},
+ "settingsLanguagePageTitle": "اللغة",
+ "@settingsLanguagePageTitle": {},
+ "rootDirectoryDescription": "دليل الجذر",
+ "@rootDirectoryDescription": {},
+ "viewDialogGroupSectionTitle": "مجموعة",
+ "@viewDialogGroupSectionTitle": {},
+ "maxBrightnessAlways": "دائماً",
+ "@maxBrightnessAlways": {},
+ "settingsAllowMediaManagement": "السماح بإدارة الوسائط",
+ "@settingsAllowMediaManagement": {},
+ "aboutDataUsageSectionTitle": "استخدام البيانات",
+ "@aboutDataUsageSectionTitle": {},
+ "durationDialogSeconds": "ثواني",
+ "@durationDialogSeconds": {},
+ "themeBrightnessLight": "مضيء",
+ "@themeBrightnessLight": {},
+ "unitSystemImperial": "النظام الإنشي",
+ "@unitSystemImperial": {},
+ "filterMimeVideoLabel": "فيديو",
+ "@filterMimeVideoLabel": {},
+ "albumEmpty": "لا توجد ألبومات",
+ "@albumEmpty": {},
+ "editEntryLocationDialogChooseOnMap": "اختر على الخريطة",
+ "@editEntryLocationDialogChooseOnMap": {},
+ "settingsCollectionBrowsingQuickActionEditorBanner": "المس مع الاستمرار لتحريك الأزرار وتحديد الإجراءات التي يتم عرضها عند تصفح العناصر.",
+ "@settingsCollectionBrowsingQuickActionEditorBanner": {},
+ "settingsConfirmationBeforeDeleteItems": "اسأل قبل حذف العناصر إلى الأبد",
+ "@settingsConfirmationBeforeDeleteItems": {},
+ "sortByName": "حسب الإسم",
+ "@sortByName": {},
+ "settingsHomeDialogTitle": "الرئيسية",
+ "@settingsHomeDialogTitle": {},
+ "searchDateSectionTitle": "تاريخ",
+ "@searchDateSectionTitle": {},
+ "viewerErrorUnknown": "آسف!",
+ "@viewerErrorUnknown": {},
+ "storageAccessDialogMessage": "يرجى تحديد {directory} لـ «{volume}» في الشاشة التالية لمنح هذا التطبيق حق الوصول إليه.",
+ "@storageAccessDialogMessage": {
+ "placeholders": {
+ "directory": {
+ "type": "String",
+ "description": "the name of a directory, using the output of `rootDirectoryDescription` or `otherDirectoryDescription`"
+ },
+ "volume": {
+ "type": "String",
+ "example": "SD card",
+ "description": "the name of a storage volume"
+ }
+ }
+ },
+ "themeBrightnessDark": "مظلم",
+ "@themeBrightnessDark": {},
+ "entryActionConvertMotionPhotoToStillImage": "تحويل إلى صورة ثابتة",
+ "@entryActionConvertMotionPhotoToStillImage": {},
+ "entryActionCast": "البث",
+ "@entryActionCast": {},
+ "entryInfoActionEditTitleDescription": "تحرير العنوان والوصف",
+ "@entryInfoActionEditTitleDescription": {},
+ "collectionSearchTitlesHintText": "عناوين البحث",
+ "@collectionSearchTitlesHintText": {},
+ "entryInfoActionEditLocation": "تحديد الوجهة",
+ "@entryInfoActionEditLocation": {},
+ "viewerInfoSearchSuggestionDate": "التَاريخ والوقت",
+ "@viewerInfoSearchSuggestionDate": {},
+ "videoPlaybackWithSound": "تشغيل بالصوت",
+ "@videoPlaybackWithSound": {},
+ "viewerInfoLabelTitle": "عنوان",
+ "@viewerInfoLabelTitle": {},
+ "searchCollectionFieldHint": "البحث في المجموعة",
+ "@searchCollectionFieldHint": {},
+ "viewerActionUnlock": "إلغاء قفل المعاينة",
+ "@viewerActionUnlock": {},
+ "settingsDoubleBackExit": "اضغط على «رجوع» مرتين للخروج",
+ "@settingsDoubleBackExit": {},
+ "entryActionShare": "مشاركة",
+ "@entryActionShare": {},
+ "drawerCollectionSphericalVideos": "فيديوهات 360 درجة",
+ "@drawerCollectionSphericalVideos": {},
+ "moveUndatedConfirmationDialogMessage": "هل تريد حفظ تواريخ العناصر قبل المتابعة؟",
+ "@moveUndatedConfirmationDialogMessage": {},
+ "collectionEditFailureFeedback": "{count, plural, =1{فشل تحرير عنصر واحد} other{فشل التحرير {count} items}}",
+ "@collectionEditFailureFeedback": {
+ "placeholders": {
+ "count": {}
+ }
+ },
+ "videoActionPause": "إيقاف مؤقت",
+ "@videoActionPause": {},
+ "noMatchingAppDialogMessage": "لا توجد تطبيقات يمكنها التعامل مع هذا.",
+ "@noMatchingAppDialogMessage": {},
+ "settingsThumbnailOverlayPageTitle": "التراكب",
+ "@settingsThumbnailOverlayPageTitle": {},
+ "settingsViewerShowInformationSubtitle": "إظهار العنوان والتاريخ والموقع وما إلى ذلك.",
+ "@settingsViewerShowInformationSubtitle": {},
+ "searchMetadataSectionTitle": "البيانات الوصفية",
+ "@searchMetadataSectionTitle": {},
+ "widgetOpenPageCollection": "فتح المجموعة",
+ "@widgetOpenPageCollection": {},
+ "settingsWidgetOpenPage": "عند النقر على الويدجت",
+ "@settingsWidgetOpenPage": {},
+ "settingsShowBottomNavigationBar": "إظهار شريط التنقل السفلي",
+ "@settingsShowBottomNavigationBar": {},
+ "renameProcessorName": "اسم",
+ "@renameProcessorName": {},
+ "viewerInfoSearchFieldLabel": "البحث في البيانات الوصفية",
+ "@viewerInfoSearchFieldLabel": {},
+ "viewerInfoLabelDescription": "وصف",
+ "@viewerInfoLabelDescription": {},
+ "nameConflictStrategySkip": "تخطي",
+ "@nameConflictStrategySkip": {},
+ "addShortcutButtonLabel": "إضافة",
+ "@addShortcutButtonLabel": {},
+ "exportEntryDialogHeight": "ارتفاع",
+ "@exportEntryDialogHeight": {},
+ "collectionActionEmptyBin": "سلة فارغة",
+ "@collectionActionEmptyBin": {},
+ "settingsSlideshowRepeat": "تكرار",
+ "@settingsSlideshowRepeat": {},
+ "settingsViewerQuickActionEditorPageTitle": "اجراءات سريعة",
+ "@settingsViewerQuickActionEditorPageTitle": {},
+ "sortOrderAtoZ": "من الألف إلى الياء",
+ "@sortOrderAtoZ": {},
+ "settingsVideoPageTitle": "اعدادات الفيديو",
+ "@settingsVideoPageTitle": {},
+ "setCoverDialogAuto": "آلي",
+ "@setCoverDialogAuto": {},
+ "tagEditorPageNewTagFieldLabel": "علامة جديدة",
+ "@tagEditorPageNewTagFieldLabel": {},
+ "exportEntryDialogWidth": "عرض",
+ "@exportEntryDialogWidth": {},
+ "newAlbumDialogTitle": "البوم جديد",
+ "@newAlbumDialogTitle": {},
+ "collectionRenameSuccessFeedback": "{count, plural, =1{تمت إعادة تسمية عنصر واحد} other{أعادة تسمية {count} عناصر}}",
+ "@collectionRenameSuccessFeedback": {
+ "placeholders": {
+ "count": {}
+ }
+ },
+ "videoStreamSelectionDialogTrack": "مسار",
+ "@videoStreamSelectionDialogTrack": {},
+ "settingsViewerUseCutout": "استخدام منطقة القص",
+ "@settingsViewerUseCutout": {},
+ "tagEditorPageTitle": "تحريرالعلامات",
+ "@tagEditorPageTitle": {},
+ "settingsWidgetShowOutline": "الخطوط العريضة",
+ "@settingsWidgetShowOutline": {},
+ "settingsHomeTile": "الرئيسية",
+ "@settingsHomeTile": {},
+ "entryActionOpenMap": "عرض في تطبيق الخرائط",
+ "@entryActionOpenMap": {},
+ "hideFilterConfirmationDialogMessage": "سيتم إخفاء الصور ومقاطع الفيديو المطابقة من مجموعتك. ويمكنك إظهارها مرة أخرى من إعدادات «الخصوصية».\n\nهل أنت متأكد أنك تريد إخفاءهم؟",
+ "@hideFilterConfirmationDialogMessage": {},
+ "settingsViewerGestureSideTapNext": "اضغط على حواف الشاشة لإظهار العنصر السابق/التالي",
+ "@settingsViewerGestureSideTapNext": {},
+ "collectionGroupDay": "حسب اليوم",
+ "@collectionGroupDay": {},
+ "collectionGroupAlbum": "حسب الألبوم",
+ "@collectionGroupAlbum": {},
+ "newFilterBanner": "الجديد",
+ "@newFilterBanner": {},
+ "drawerCollectionFavourites": "المفضلة",
+ "@drawerCollectionFavourites": {},
+ "filterTypeRawLabel": "خام",
+ "@filterTypeRawLabel": {},
+ "videoControlsPlaySeek": "تشغيل وتقدم للأمام/ للخلف",
+ "@videoControlsPlaySeek": {},
+ "settingsSubtitleThemeTextAlignmentCenter": "وسط",
+ "@settingsSubtitleThemeTextAlignmentCenter": {},
+ "keepScreenOnVideoPlayback": "أثناء تشغيل الفيديو",
+ "@keepScreenOnVideoPlayback": {},
+ "vaultLockTypePin": "رمز سري",
+ "@vaultLockTypePin": {},
+ "settingsSubtitleThemeTextAlignmentTile": "محاذاة النص",
+ "@settingsSubtitleThemeTextAlignmentTile": {},
+ "editorTransformCrop": "قص",
+ "@editorTransformCrop": {},
+ "aboutLicensesFlutterPackagesSectionTitle": "حزم إضافية",
+ "@aboutLicensesFlutterPackagesSectionTitle": {},
+ "settingsCollectionQuickActionTabSelecting": "إختيار",
+ "@settingsCollectionQuickActionTabSelecting": {},
+ "focalLength": "{length} mm",
+ "@focalLength": {
+ "placeholders": {
+ "length": {
+ "type": "String",
+ "example": "5.4"
+ }
+ }
+ },
+ "filterTaggedLabel": "الموسومة",
+ "@filterTaggedLabel": {},
+ "statePageTitle": "الولايات",
+ "@statePageTitle": {},
+ "drawerTagPage": "العلامات",
+ "@drawerTagPage": {},
+ "newAlbumDialogNameLabelAlreadyExistsHelper": "الدليل موجود بالفعل",
+ "@newAlbumDialogNameLabelAlreadyExistsHelper": {},
+ "patternDialogConfirm": "تأكيد النمط",
+ "@patternDialogConfirm": {},
+ "restrictedAccessDialogMessage": "لا يُسمح لهذا التطبيق بتعديل الملفات في {directory} لـ «{volume}»\n\nالرجاء استخدام مدير الملفات أو تطبيق المعرض المثبت مسبقًا لنقل العناصر إلى دليل آخر.",
+ "@restrictedAccessDialogMessage": {
+ "placeholders": {
+ "directory": {
+ "type": "String",
+ "description": "the name of a directory, using the output of `rootDirectoryDescription` or `otherDirectoryDescription`"
+ },
+ "volume": {
+ "type": "String",
+ "example": "SD card",
+ "description": "the name of a storage volume"
+ }
+ }
+ },
+ "durationDialogMinutes": "دقائق",
+ "@durationDialogMinutes": {},
+ "settingsAllowErrorReporting": "السماح بالإبلاغ عن الأخطاء المجهولة",
+ "@settingsAllowErrorReporting": {},
+ "settingsVideoLoopModeTile": "وضع التكرار",
+ "@settingsVideoLoopModeTile": {},
+ "unsupportedTypeDialogMessage": "{count, plural, =1{هذه العملية غير مدعومة للعناصر من النوع التالي: {types}.} other{هذه العملية غير معتمدة لعناصر الأنواع التالية: {types}.}}",
+ "@unsupportedTypeDialogMessage": {
+ "placeholders": {
+ "count": {},
+ "types": {
+ "type": "String",
+ "example": "GIF, TIFF, MP4",
+ "description": "a list of unsupported types"
+ }
+ }
+ },
+ "settingsScreenSaverPageTitle": "شاشة التوقف",
+ "@settingsScreenSaverPageTitle": {},
+ "settingsNavigationDrawerEditorPageTitle": "قائمة التنقل",
+ "@settingsNavigationDrawerEditorPageTitle": {},
+ "settingsConfirmationBeforeMoveUndatedItems": "اسأل قبل نقل العناصر غير المؤرخة",
+ "@settingsConfirmationBeforeMoveUndatedItems": {},
+ "albumPageTitle": "الألبومات",
+ "@albumPageTitle": {},
+ "editEntryLocationDialogTitle": "موقع",
+ "@editEntryLocationDialogTitle": {},
+ "statsWithGps": "{count, plural, =1{1 عنصر مع الموقع} other{{count} العناصر مع الموقع}}",
+ "@statsWithGps": {
+ "placeholders": {
+ "count": {}
+ }
+ },
+ "settingsVideoResumptionModeDialogTitle": "إستئناف التشغيل",
+ "@settingsVideoResumptionModeDialogTitle": {},
+ "albumTierPinned": "مثبت",
+ "@albumTierPinned": {},
+ "mapStyleDialogTitle": "نمط الخريطة",
+ "@mapStyleDialogTitle": {},
+ "entryActionRotateCCW": "تدوير باتجاه عقارب الساعة",
+ "@entryActionRotateCCW": {},
+ "settingsVideoBackgroundMode": "وضع الخلفية",
+ "@settingsVideoBackgroundMode": {},
+ "chipActionCreateVault": "إنشاء خزنة",
+ "@chipActionCreateVault": {},
+ "albumPickPageTitleCopy": "نسخ إلى ألبوم",
+ "@albumPickPageTitleCopy": {},
+ "collectionActionCopy": "نسخ إلى الألبوم",
+ "@collectionActionCopy": {},
+ "entryActionPrint": "طباعة",
+ "@entryActionPrint": {},
+ "settingsAllowInstalledAppAccess": "السماح بالوصول إلى مخزون التطبيق",
+ "@settingsAllowInstalledAppAccess": {},
+ "entryActionShowGeoTiffOnMap": "عرض كتراكب على الخريطة",
+ "@entryActionShowGeoTiffOnMap": {},
+ "viewDialogReverseSortOrder": "عكس ترتيب الفرز",
+ "@viewDialogReverseSortOrder": {},
+ "menuActionConfigureView": "رؤية",
+ "@menuActionConfigureView": {},
+ "aboutLicensesDartPackagesSectionTitle": "حزم البرمجة",
+ "@aboutLicensesDartPackagesSectionTitle": {},
+ "drawerCollectionMotionPhotos": "صور متحركة",
+ "@drawerCollectionMotionPhotos": {},
+ "settingsDefault": "افتراضي",
+ "@settingsDefault": {},
+ "settingsHiddenItemsTabFilters": "المرشحات المخفية",
+ "@settingsHiddenItemsTabFilters": {},
+ "settingsSlideshowAnimatedZoomEffect": "تأثير التكبير المتحرك",
+ "@settingsSlideshowAnimatedZoomEffect": {},
+ "viewerActionSettings": "الإعدادات",
+ "@viewerActionSettings": {},
+ "placePageTitle": "أماكن",
+ "@placePageTitle": {},
+ "filterOnThisDayLabel": "في هذا اليوم",
+ "@filterOnThisDayLabel": {},
+ "columnCount": "{count, plural, =1{1 عمود} other{{count} أعمدة}}{count}",
+ "@columnCount": {
+ "placeholders": {
+ "count": {}
+ }
+ },
+ "viewerTransitionNone": "لا شيء",
+ "@viewerTransitionNone": {},
+ "settingsDisplayRefreshRateModeTile": "عرض معدل التحديث",
+ "@settingsDisplayRefreshRateModeTile": {},
+ "addShortcutDialogLabel": "تسمية الاختصار",
+ "@addShortcutDialogLabel": {},
+ "settingsViewerOverlayPageTitle": "تراكب",
+ "@settingsViewerOverlayPageTitle": {},
+ "tagEmpty": "لا توجد العلامات",
+ "@tagEmpty": {},
+ "pinDialogEnter": "أدخل الرمز السري",
+ "@pinDialogEnter": {},
+ "videoControlsPlayOutside": "فتح في مشغل آخر",
+ "@videoControlsPlayOutside": {},
+ "settingsCoordinateFormatDialogTitle": "تنسيق الاحداثيات",
+ "@settingsCoordinateFormatDialogTitle": {},
+ "authenticateToUnlockVault": "المصادقة لفتح الخزنة",
+ "@authenticateToUnlockVault": {},
+ "collectionActionShowTitleSearch": "إظهار مرشح العنوان",
+ "@collectionActionShowTitleSearch": {},
+ "lengthUnitPercent": "%",
+ "@lengthUnitPercent": {},
+ "settingsNavigationDrawerTabTypes": "أنواع",
+ "@settingsNavigationDrawerTabTypes": {},
+ "menuActionSelectAll": "تحديد الكل",
+ "@menuActionSelectAll": {},
+ "settingsHiddenItemsTile": "العناصر المخفية",
+ "@settingsHiddenItemsTile": {},
+ "maxBrightnessNever": "أبداً",
+ "@maxBrightnessNever": {},
+ "aboutDataUsageCache": "التخزين المؤقت",
+ "@aboutDataUsageCache": {},
+ "settingsConfirmationTile": "نوافذ التأكيد",
+ "@settingsConfirmationTile": {},
+ "coordinateDmsSouth": "جنوب",
+ "@coordinateDmsSouth": {},
+ "settingsThumbnailShowVideoDuration": "عرض مدة الفيديو",
+ "@settingsThumbnailShowVideoDuration": {},
+ "passwordDialogConfirm": "تأكيد كلمة السر",
+ "@passwordDialogConfirm": {},
+ "videoActionReplay10": "تقدم الخلفي لمدة 10 ثوانٍ",
+ "@videoActionReplay10": {},
+ "settingsCollectionBurstPatternsNone": "لا شيء",
+ "@settingsCollectionBurstPatternsNone": {},
+ "albumMimeTypeMixed": "مختلط",
+ "@albumMimeTypeMixed": {},
+ "settingsViewerQuickActionEditorAvailableButtonsSectionTitle": "الأزرار المتاحة",
+ "@settingsViewerQuickActionEditorAvailableButtonsSectionTitle": {},
+ "itemCount": "{count, plural, =1{1 عنصر} other{{count} عناصر}}",
+ "@itemCount": {
+ "placeholders": {
+ "count": {}
+ }
+ },
+ "widgetTapUpdateWidget": "تحديث الويدجت",
+ "@widgetTapUpdateWidget": {},
+ "settingsViewerShowDescription": "إظهار الوصف",
+ "@settingsViewerShowDescription": {},
+ "viewerTransitionFade": "تلاشي",
+ "@viewerTransitionFade": {},
+ "chipActionConfigureVault": "تكوين الخزنة",
+ "@chipActionConfigureVault": {},
+ "cropAspectRatioFree": "حر",
+ "@cropAspectRatioFree": {},
+ "aboutLinkPolicy": "سياسة الخصوصية",
+ "@aboutLinkPolicy": {},
+ "filterTypeSphericalVideoLabel": "فيديو 360 درجة",
+ "@filterTypeSphericalVideoLabel": {},
+ "slideshowActionShowInCollection": "عرض في المجموعة",
+ "@slideshowActionShowInCollection": {},
+ "notEnoughSpaceDialogMessage": "تحتاج هذه العملية إلى {neededSize} من المساحة الحرة على «{volume}» لإكمالها، ولكن لم يتبق سوى {freeSize}.",
+ "@notEnoughSpaceDialogMessage": {
+ "placeholders": {
+ "neededSize": {
+ "type": "String",
+ "example": "314 MB"
+ },
+ "freeSize": {
+ "type": "String",
+ "example": "123 MB"
+ },
+ "volume": {
+ "type": "String",
+ "example": "SD card",
+ "description": "the name of a storage volume"
+ }
+ }
+ },
+ "filterNoRatingLabel": "غير مصنف",
+ "@filterNoRatingLabel": {},
+ "settingsUnitSystemTile": "الوحدات",
+ "@settingsUnitSystemTile": {},
+ "entryActionOpen": "فتح باستخدام",
+ "@entryActionOpen": {},
+ "settingsCoordinateFormatTile": "تنسيق الإحداثيات",
+ "@settingsCoordinateFormatTile": {},
+ "newVaultWarningDialogMessage": "العناصر الموجودة في الخزائن متاحة فقط لهذا التطبيق وليس للتطبيقات الأخرى.\n\nإذا قمت بإلغاء تثبيت هذا التطبيق، أو قمت بمسح بيانات هذا التطبيق، فسوف تفقد كل هذه العناصر.",
+ "@newVaultWarningDialogMessage": {},
+ "settingsViewerQuickActionEditorBanner": "المس مع الاستمرار لتحريك الأزرار وتحديد الإجراءات التي سيتم عرضها في العارض.",
+ "@settingsViewerQuickActionEditorBanner": {},
+ "themeBrightnessBlack": "أسود",
+ "@themeBrightnessBlack": {},
+ "filterNoLocationLabel": "غير محدد",
+ "@filterNoLocationLabel": {},
+ "mapZoomInTooltip": "تكبير",
+ "@mapZoomInTooltip": {},
+ "viewerInfoOpenLinkText": "فتح",
+ "@viewerInfoOpenLinkText": {},
+ "storageVolumeDescriptionFallbackNonPrimary": "بطاقة الذاكرة",
+ "@storageVolumeDescriptionFallbackNonPrimary": {},
+ "renameEntrySetPagePatternFieldLabel": "نمط التسمية",
+ "@renameEntrySetPagePatternFieldLabel": {},
+ "renameAlbumDialogLabel": "إسم جديد",
+ "@renameAlbumDialogLabel": {},
+ "videoActionPlay": "تشغيل",
+ "@videoActionPlay": {},
+ "settingsDisablingBinWarningDialogMessage": "سيتم حذف العناصر الموجودة في سلة المحذوفات إلى الأبد.",
+ "@settingsDisablingBinWarningDialogMessage": {},
+ "entryActionSetAs": "تعيين كـ",
+ "@entryActionSetAs": {},
+ "sortOrderLowestFirst": "الأدنى أولاً",
+ "@sortOrderLowestFirst": {},
+ "albumGroupNone": "لا تجمع",
+ "@albumGroupNone": {},
+ "statsTopStatesSectionTitle": "أهم الولايات",
+ "@statsTopStatesSectionTitle": {},
+ "settingsViewerQuickActionEditorDisplayedButtonsSectionTitle": "الأزرار المعروضة",
+ "@settingsViewerQuickActionEditorDisplayedButtonsSectionTitle": {},
+ "settingsVideoPlaybackPageTitle": "التشغيل",
+ "@settingsVideoPlaybackPageTitle": {},
+ "filterLocatedLabel": "متواجد",
+ "@filterLocatedLabel": {},
+ "videoPlaybackSkip": "تخطي",
+ "@videoPlaybackSkip": {},
+ "mapStyleTooltip": "حدد نمط الخريطة",
+ "@mapStyleTooltip": {},
+ "countryPageTitle": "دول",
+ "@countryPageTitle": {},
+ "albumGroupType": "حسب النوع",
+ "@albumGroupType": {},
+ "entryActionInfo": "معلومات",
+ "@entryActionInfo": {},
+ "viewerErrorDoesNotExist": "الملف لم يعد موجودا.",
+ "@viewerErrorDoesNotExist": {},
+ "albumCamera": "الكاميرا",
+ "@albumCamera": {},
+ "videoControlsPlay": "تشغيل",
+ "@videoControlsPlay": {},
+ "settingsNavigationSectionTitle": "التنقل",
+ "@settingsNavigationSectionTitle": {},
+ "settingsDisplayRefreshRateModeDialogTitle": "معدل التحديث",
+ "@settingsDisplayRefreshRateModeDialogTitle": {},
+ "viewerInfoLabelUri": "URI",
+ "@viewerInfoLabelUri": {},
+ "entryActionViewSource": "عرض المصدر",
+ "@entryActionViewSource": {},
+ "entryActionShareVideoOnly": "مشاركة الفيديوهات فقط",
+ "@entryActionShareVideoOnly": {},
+ "filterTypePanoramaLabel": "بانوراما",
+ "@filterTypePanoramaLabel": {},
+ "coordinateFormatDms": "نظام إدارة الوجهة",
+ "@coordinateFormatDms": {},
+ "passwordDialogEnter": "أدخل كلمة السر",
+ "@passwordDialogEnter": {},
+ "mapZoomOutTooltip": "تصغير",
+ "@mapZoomOutTooltip": {},
+ "entryInfoActionEditTags": "تعديل العلامات",
+ "@entryInfoActionEditTags": {},
+ "collectionActionHideTitleSearch": "إخفاء مرشح العنوان",
+ "@collectionActionHideTitleSearch": {},
+ "mapAttributionOsmHot": "بيانات الخريطة © [OpenStreetMap](https://www.openstreetmap.org/copyright) المساهمين • البلاط بواسطة [HOT](https://www.hotosm.org/) • استضافة بواسطة [OSM France](https://openstreetmap.fr/)",
+ "@mapAttributionOsmHot": {},
+ "settingsNavigationDrawerTile": "قائمة تنقل",
+ "@settingsNavigationDrawerTile": {},
+ "drawerCollectionAnimated": "متحرك",
+ "@drawerCollectionAnimated": {},
+ "renameAlbumDialogLabelAlreadyExistsHelper": "الدليل موجود بالفعل",
+ "@renameAlbumDialogLabelAlreadyExistsHelper": {},
+ "settingsHiddenItemsPageTitle": "العناصر المَخفية",
+ "@settingsHiddenItemsPageTitle": {},
+ "keepScreenOnViewerOnly": "صفحة المشاهدة فقط",
+ "@keepScreenOnViewerOnly": {},
+ "durationDialogHours": "ساعات",
+ "@durationDialogHours": {},
+ "settingsHiddenPathsBanner": "لن تظهر الصور ومقاطع الفيديو الموجودة في هذه المجلدات، أو أي من مجلداتها الفرعية في مجموعتك.",
+ "@settingsHiddenPathsBanner": {},
+ "settingsKeepScreenOnDialogTitle": "ابقاء الشَاشة قيد التشغيل",
+ "@settingsKeepScreenOnDialogTitle": {},
+ "wallpaperTargetHome": "الشاشة الرئيسية",
+ "@wallpaperTargetHome": {},
+ "settingsViewerShowOverlayOnOpening": "عرض عند الفتح",
+ "@settingsViewerShowOverlayOnOpening": {},
+ "settingsAccessibilityShowPinchGestureAlternatives": "عرض بدائل إيماءات اللمس المتعدد",
+ "@settingsAccessibilityShowPinchGestureAlternatives": {},
+ "videoActionSelectStreams": "اختيار المسارات",
+ "@videoActionSelectStreams": {},
+ "settingsViewerShowShootingDetails": "عرض تفاصيل التصوير",
+ "@settingsViewerShowShootingDetails": {},
+ "settingsConfirmationAfterMoveToBinItems": "إظهار الرسالة بعد نقل العناصر إلى سلة المحذوفات",
+ "@settingsConfirmationAfterMoveToBinItems": {},
+ "widgetDisplayedItemRandom": "عشوائي",
+ "@widgetDisplayedItemRandom": {},
+ "settingsLanguageSectionTitle": "اللغة والتنسيقات",
+ "@settingsLanguageSectionTitle": {},
+ "drawerPlacePage": "الأماكن",
+ "@drawerPlacePage": {},
+ "menuActionSelect": "تحديد",
+ "@menuActionSelect": {},
+ "drawerCollectionPanoramas": "لقطات بانورامية",
+ "@drawerCollectionPanoramas": {},
+ "renameEntrySetPagePreviewSectionTitle": "معاينة",
+ "@renameEntrySetPagePreviewSectionTitle": {},
+ "filterBinLabel": "سلة المَحذوفات",
+ "@filterBinLabel": {},
+ "settingsDisplaySectionTitle": "عَرض",
+ "@settingsDisplaySectionTitle": {},
+ "settingsConfirmationVaultDataLoss": "إظهار تحذير فقدان بيانات المخزن",
+ "@settingsConfirmationVaultDataLoss": {},
+ "settingsSlideshowTransitionTile": "انتقال",
+ "@settingsSlideshowTransitionTile": {},
+ "settingsPageTitle": "إعدادات",
+ "@settingsPageTitle": {},
+ "subtitlePositionTop": "أعلى",
+ "@subtitlePositionTop": {},
+ "menuActionSelectNone": "لا تحدد شيء",
+ "@menuActionSelectNone": {},
+ "entryActionConvert": "تحويل",
+ "@entryActionConvert": {},
+ "aboutDataUsageClearCache": "مسح ذاكرة التخزين المؤقت",
+ "@aboutDataUsageClearCache": {},
+ "settingsSearchFieldLabel": "إعدادات البحث",
+ "@settingsSearchFieldLabel": {},
+ "appExportFavourites": "المفضلة",
+ "@appExportFavourites": {},
+ "collectionEmptyImages": "لا توجد صور",
+ "@collectionEmptyImages": {},
+ "settingsViewerMaximumBrightness": "أقصى سطوع",
+ "@settingsViewerMaximumBrightness": {},
+ "albumPickPageTitleExport": "تصدير إلى الألبوم",
+ "@albumPickPageTitleExport": {},
+ "settingsThumbnailShowTagIcon": "إظهار رمز العلامة",
+ "@settingsThumbnailShowTagIcon": {},
+ "settingsStorageAccessEmpty": "عدم منح الوصول",
+ "@settingsStorageAccessEmpty": {},
+ "settingsRemoveAnimationsTile": "إزالة الرسوم المتحركة",
+ "@settingsRemoveAnimationsTile": {},
+ "settingsStorageAccessBanner": "تتطلب بعض الدلائل منح وصول صريح لتعديل الملفات الموجودة فيها. يمكنك هنا مراجعة الدلائل التي منحتها حق الوصول إليها مسبقًا.",
+ "@settingsStorageAccessBanner": {},
+ "authenticateToConfigureVault": "قم بالمصادقة لتكوين المخزن",
+ "@authenticateToConfigureVault": {},
+ "settingsActionExportDialogTitle": "يصدّر",
+ "@settingsActionExportDialogTitle": {},
+ "genericDangerWarningDialogMessage": "هل أنت متأكد؟",
+ "@genericDangerWarningDialogMessage": {},
+ "lengthUnitPixel": "بكسل",
+ "@lengthUnitPixel": {},
+ "vaultDialogLockTypeLabel": "نوع القفل",
+ "@vaultDialogLockTypeLabel": {},
+ "aboutDataUsageExternal": "خارجي",
+ "@aboutDataUsageExternal": {},
+ "collectionSelectPageTitle": "اختيار العناصر",
+ "@collectionSelectPageTitle": {},
+ "entryInfoActionEditDate": "تعديل التاريخ والوقت",
+ "@entryInfoActionEditDate": {},
+ "editEntryLocationDialogLatitude": "خط العرض",
+ "@editEntryLocationDialogLatitude": {},
+ "slideshowActionResume": "استئناف",
+ "@slideshowActionResume": {},
+ "cropAspectRatioSquare": "مربع",
+ "@cropAspectRatioSquare": {},
+ "collectionActionRescan": "إعادة المسح",
+ "@collectionActionRescan": {},
+ "collectionCopySuccessFeedback": "{count, plural, =1{تم نسخ عنصر واحد} other{نسخ {count} أغراض}}",
+ "@collectionCopySuccessFeedback": {
+ "placeholders": {
+ "count": {}
+ }
+ },
+ "settingsNavigationDrawerBanner": "إلمس مع الاستمرار لنقل عناصر القائمة وإعادة ترتيبها.",
+ "@settingsNavigationDrawerBanner": {},
+ "settingsWidgetPageTitle": "إطار الصورة",
+ "@settingsWidgetPageTitle": {},
+ "viewDialogSortSectionTitle": "نوع",
+ "@viewDialogSortSectionTitle": {},
+ "collectionPageTitle": "مجموعة بيانات",
+ "@collectionPageTitle": {},
+ "unitSystemMetric": "النظام المتري",
+ "@unitSystemMetric": {},
+ "overlayHistogramNone": "لا شيء",
+ "@overlayHistogramNone": {},
+ "chipActionShowCountryStates": "عرض الولايات",
+ "@chipActionShowCountryStates": {},
+ "filterRecentlyAddedLabel": "أضيف مؤخرا",
+ "@filterRecentlyAddedLabel": {},
+ "editEntryDialogTargetFieldsHeader": "الحقول المراد تعديلها",
+ "@editEntryDialogTargetFieldsHeader": {},
+ "storageVolumeDescriptionFallbackPrimary": "التخزين الداخلي",
+ "@storageVolumeDescriptionFallbackPrimary": {},
+ "collectionActionAddShortcut": "إضافة اختصار",
+ "@collectionActionAddShortcut": {},
+ "settingsViewerShowMinimap": "إظهار الخريطة المصغرة",
+ "@settingsViewerShowMinimap": {},
+ "settingsCollectionBurstPatternsTile": "أنماط الانفجار",
+ "@settingsCollectionBurstPatternsTile": {},
+ "viewerInfoLabelPath": "الطريق",
+ "@viewerInfoLabelPath": {},
+ "albumGroupVolume": "حسب حجم التخزين",
+ "@albumGroupVolume": {},
+ "collectionGroupMonth": "حسب الشهر",
+ "@collectionGroupMonth": {},
+ "viewerInfoLabelResolution": "دقة",
+ "@viewerInfoLabelResolution": {},
+ "renameProcessorCounter": "عداد",
+ "@renameProcessorCounter": {},
+ "settingsImageBackground": "خلفية الصورة",
+ "@settingsImageBackground": {},
+ "newAlbumDialogNameLabel": "اسم الألبوم",
+ "@newAlbumDialogNameLabel": {},
+ "cropAspectRatioOriginal": "الأصل",
+ "@cropAspectRatioOriginal": {},
+ "sortByDate": "حسب التاريخ",
+ "@sortByDate": {},
+ "statsTopAlbumsSectionTitle": "أهم الألبومات",
+ "@statsTopAlbumsSectionTitle": {},
+ "configureVaultDialogTitle": "تكوين قبو",
+ "@configureVaultDialogTitle": {},
+ "entryActionRename": "إعادة تسمية",
+ "@entryActionRename": {},
+ "viewerInfoLabelDuration": "المدة",
+ "@viewerInfoLabelDuration": {},
+ "sortOrderZtoA": "من الياء إلى الألف",
+ "@sortOrderZtoA": {},
+ "keepScreenOnNever": "أبداً",
+ "@keepScreenOnNever": {},
+ "statsPageTitle": "احصائيات",
+ "@statsPageTitle": {},
+ "viewerInfoSearchSuggestionDimensions": "أبعاد",
+ "@viewerInfoSearchSuggestionDimensions": {},
+ "mapStyleOsmHot": "خرائط OSM",
+ "@mapStyleOsmHot": {},
+ "drawerAboutButton": "حول",
+ "@drawerAboutButton": {},
+ "aboutTranslatorsSectionTitle": "المترجمين",
+ "@aboutTranslatorsSectionTitle": {},
+ "statsTopPlacesSectionTitle": "أهم المواقع",
+ "@statsTopPlacesSectionTitle": {},
+ "videoStreamSelectionDialogOff": "ايقاف",
+ "@videoStreamSelectionDialogOff": {},
+ "settingsVideoLoopModeDialogTitle": "وضع التَكرار",
+ "@settingsVideoLoopModeDialogTitle": {},
+ "drawerCollectionImages": "الصور",
+ "@drawerCollectionImages": {},
+ "sortOrderSmallestFirst": "الأصغر أولاً",
+ "@sortOrderSmallestFirst": {},
+ "timeSeconds": "{seconds, plural, =1{1 ثانية} other{{seconds} ثواني}}",
+ "@timeSeconds": {
+ "placeholders": {
+ "seconds": {}
+ }
+ },
+ "sortBySize": "حسب الحجم",
+ "@sortBySize": {},
+ "viewerInfoSearchSuggestionDescription": "وصف",
+ "@viewerInfoSearchSuggestionDescription": {},
+ "settingsViewerShowOverlayThumbnails": "عرض الصور المصغرة",
+ "@settingsViewerShowOverlayThumbnails": {},
+ "collectionPickPageTitle": "اختيار",
+ "@collectionPickPageTitle": {},
+ "settingsVideoControlsPageTitle": "ضوابط",
+ "@settingsVideoControlsPageTitle": {},
+ "aboutBugReportButton": "تقرير",
+ "@aboutBugReportButton": {},
+ "collectionEmptyGrantAccessButtonLabel": "منح الوصول",
+ "@collectionEmptyGrantAccessButtonLabel": {},
+ "filterTypeMotionPhotoLabel": "الصور المتحركة",
+ "@filterTypeMotionPhotoLabel": {},
+ "mapStyleGoogleNormal": "خرائط جوجل",
+ "@mapStyleGoogleNormal": {},
+ "videoStreamSelectionDialogVideo": "فيديو",
+ "@videoStreamSelectionDialogVideo": {},
+ "viewDialogLayoutSectionTitle": "تخطيط",
+ "@viewDialogLayoutSectionTitle": {},
+ "searchStatesSectionTitle": "الولايات",
+ "@searchStatesSectionTitle": {},
+ "filterTypeAnimatedLabel": "متحرك",
+ "@filterTypeAnimatedLabel": {},
+ "videoLoopModeNever": "أبداً",
+ "@videoLoopModeNever": {},
+ "settingsUnitSystemDialogTitle": "الوحدات",
+ "@settingsUnitSystemDialogTitle": {},
+ "videoActionSetSpeed": "سرعة التشغيل",
+ "@videoActionSetSpeed": {},
+ "dateThisMonth": "هذا الشهر",
+ "@dateThisMonth": {},
+ "renameEntrySetPageTitle": "إعادة تسمية",
+ "@renameEntrySetPageTitle": {},
+ "settingsConfirmationBeforeMoveToBinItems": "اسأل قبل نقل العناصر إلى سلة المحذوفات",
+ "@settingsConfirmationBeforeMoveToBinItems": {},
+ "settingsSlideshowVideoPlaybackTile": "تشغيل الفيديو",
+ "@settingsSlideshowVideoPlaybackTile": {},
+ "settingsHiddenFiltersEmpty": "لا يوجد مرشحات مخفية",
+ "@settingsHiddenFiltersEmpty": {},
+ "aboutPageTitle": "حول",
+ "@aboutPageTitle": {},
+ "sortByRating": "حسب التصنيف",
+ "@sortByRating": {},
+ "stateEmpty": "لا توجد ولايات",
+ "@stateEmpty": {},
+ "viewerInfoSearchEmpty": "لا توجد مفاتيح مطابقة",
+ "@viewerInfoSearchEmpty": {},
+ "filterFavouriteLabel": "مفضل",
+ "@filterFavouriteLabel": {},
+ "drawerCountryPage": "البلدان",
+ "@drawerCountryPage": {},
+ "aboutBugSectionTitle": "تقرير الأخطاء",
+ "@aboutBugSectionTitle": {},
+ "filterRatingRejectedLabel": "مرفوض",
+ "@filterRatingRejectedLabel": {},
+ "settingsThumbnailShowLocationIcon": "إظهار رمز الموقع",
+ "@settingsThumbnailShowLocationIcon": {},
+ "editEntryDialogCopyFromItem": "نسخ من عنصر آخر",
+ "@editEntryDialogCopyFromItem": {},
+ "settingsStorageAccessPageTitle": "الوصُول إلى التخزين",
+ "@settingsStorageAccessPageTitle": {},
+ "genericFailureFeedback": "فشل",
+ "@genericFailureFeedback": {},
+ "aboutDataUsageData": "بيانات",
+ "@aboutDataUsageData": {},
+ "settingsThemeEnableDynamicColor": "اللون الديناميكي",
+ "@settingsThemeEnableDynamicColor": {},
+ "viewerInfoOpenEmbeddedFailureFeedback": "فشل في استخراج البيانات المضمنة",
+ "@viewerInfoOpenEmbeddedFailureFeedback": {},
+ "aboutDataUsageInternal": "داخلي",
+ "@aboutDataUsageInternal": {},
+ "albumDownload": "التحميل",
+ "@albumDownload": {},
+ "coverDialogTabColor": "اللون",
+ "@coverDialogTabColor": {},
+ "coordinateDmsWest": "غرب",
+ "@coordinateDmsWest": {},
+ "genericSuccessFeedback": "إنتهى!",
+ "@genericSuccessFeedback": {},
+ "videoActionMute": "كتم الصوت",
+ "@videoActionMute": {},
+ "renameEntryDialogLabel": "اسم جديد",
+ "@renameEntryDialogLabel": {},
+ "renameEntrySetPageInsertTooltip": "أدخل الحقل",
+ "@renameEntrySetPageInsertTooltip": {},
+ "aboutLicensesShowAllButtonLabel": "عرض كافة التراخيص",
+ "@aboutLicensesShowAllButtonLabel": {},
+ "settingsSubtitleThemeBackgroundOpacity": "عتامة الخلفية",
+ "@settingsSubtitleThemeBackgroundOpacity": {},
+ "settingsStorageAccessTile": "الوصول إلى التخزين",
+ "@settingsStorageAccessTile": {},
+ "entryActionDelete": "مسح",
+ "@entryActionDelete": {},
+ "settingsThemeBrightnessTile": "السمَة",
+ "@settingsThemeBrightnessTile": {},
+ "settingsViewerQuickActionEmpty": "لا يوجد أزرار",
+ "@settingsViewerQuickActionEmpty": {},
+ "viewerInfoBackToViewerTooltip": "العودة إلى العارض",
+ "@viewerInfoBackToViewerTooltip": {},
+ "settingsSystemDefault": "الإعداد الافتراضي للنظام",
+ "@settingsSystemDefault": {},
+ "settingsViewerSlideshowTile": "عرض الشرائح",
+ "@settingsViewerSlideshowTile": {},
+ "settingsCollectionTile": "مجمُوعة",
+ "@settingsCollectionTile": {},
+ "entryActionRotateCW": "تدوير في اتجاه عقارب الساعة",
+ "@entryActionRotateCW": {},
+ "settingsSubtitleThemeTextOpacity": "عتامة النص",
+ "@settingsSubtitleThemeTextOpacity": {},
+ "sortOrderNewestFirst": "الأحدث أولاً",
+ "@sortOrderNewestFirst": {},
+ "settingsViewerShowRatingTags": "عرض التصنيف والعلامات",
+ "@settingsViewerShowRatingTags": {},
+ "drawerSettingsButton": "إعدادات",
+ "@drawerSettingsButton": {},
+ "entryActionFlip": "عكس أفقيًا",
+ "@entryActionFlip": {},
+ "drawerCollectionRaws": "الصور الخام",
+ "@drawerCollectionRaws": {},
+ "settingsViewerEnableOverlayBlurEffect": "تأثير الضبابية",
+ "@settingsViewerEnableOverlayBlurEffect": {},
+ "settingsMotionPhotoAutoPlay": "التشغيل التلقائي للصور المتحركة",
+ "@settingsMotionPhotoAutoPlay": {},
+ "overlayHistogramRGB": "RGB",
+ "@overlayHistogramRGB": {},
+ "settingsVideoControlsTile": "ضوابط",
+ "@settingsVideoControlsTile": {},
+ "settingsSlideshowVideoPlaybackDialogTitle": "تَشغيل الفيديو",
+ "@settingsSlideshowVideoPlaybackDialogTitle": {},
+ "settingsSubtitleThemeShowOutline": "إظهار الخطوط العريضة والظل",
+ "@settingsSubtitleThemeShowOutline": {},
+ "settingsNavigationDrawerTabAlbums": "الألبومات",
+ "@settingsNavigationDrawerTabAlbums": {},
+ "subtitlePositionBottom": "أسفل",
+ "@subtitlePositionBottom": {},
+ "castDialogTitle": "أجهزة البث",
+ "@castDialogTitle": {},
+ "timeDays": "{days, plural, =1{1 يوم} other{{days} أيام}}",
+ "@timeDays": {
+ "placeholders": {
+ "days": {}
+ }
+ },
+ "videoResumeButtonLabel": "إستئناف",
+ "@videoResumeButtonLabel": {},
+ "entryActionExport": "تصدير",
+ "@entryActionExport": {},
+ "mapEmptyRegion": "لا توجد صور في هذه المنطقة",
+ "@mapEmptyRegion": {},
+ "settingsVideoEnablePip": "صورة في صورة",
+ "@settingsVideoEnablePip": {},
+ "settingsThemeBrightnessDialogTitle": "السمة",
+ "@settingsThemeBrightnessDialogTitle": {},
+ "aboutLicensesFlutterPluginsSectionTitle": "مكونات إضافية",
+ "@aboutLicensesFlutterPluginsSectionTitle": {},
+ "sortOrderHighestFirst": "الاعلى اولا",
+ "@sortOrderHighestFirst": {},
+ "aboutLicensesAndroidLibrariesSectionTitle": "مكتبات أندرويد",
+ "@aboutLicensesAndroidLibrariesSectionTitle": {},
+ "settingsViewerQuickActionsTile": "إجراءات سريعة",
+ "@settingsViewerQuickActionsTile": {},
+ "entryActionAddFavourite": "إضافة إلى المفضلة",
+ "@entryActionAddFavourite": {},
+ "entryActionEdit": "تحرير",
+ "@entryActionEdit": {},
+ "newVaultDialogTitle": "قبو جديد",
+ "@newVaultDialogTitle": {},
+ "entryInfoActionEditRating": "تحرير التقييم",
+ "@entryInfoActionEditRating": {},
+ "timeMinutes": "{minutes, plural, =1{1 دقيقة} other{{minutes} دقائق}}",
+ "@timeMinutes": {
+ "placeholders": {
+ "minutes": {}
+ }
+ },
+ "albumTierSpecial": "شائع",
+ "@albumTierSpecial": {},
+ "settingsSubtitleThemePageTitle": "ترجمات",
+ "@settingsSubtitleThemePageTitle": {},
+ "settingsSubtitleThemeTextPositionTile": "موضع النص",
+ "@settingsSubtitleThemeTextPositionTile": {},
+ "entryActionRestore": "استعادة",
+ "@entryActionRestore": {},
+ "entryActionCopyToClipboard": "نسخ إلى الحافظة",
+ "@entryActionCopyToClipboard": {},
+ "viewerInfoLabelAddress": "العنوان",
+ "@viewerInfoLabelAddress": {},
+ "settingsVideoBackgroundModeDialogTitle": "وضع الخلـفية",
+ "@settingsVideoBackgroundModeDialogTitle": {},
+ "binPageTitle": "سلة المحذوفات",
+ "@binPageTitle": {},
+ "tagPlaceholderState": "ولاية",
+ "@tagPlaceholderState": {},
+ "sortByAlbumFileName": "حسب الألبوم واسم الملف",
+ "@sortByAlbumFileName": {},
+ "deleteMultiAlbumConfirmationDialogMessage": "{count, plural, =1{هل تريد حذف هذه الألبومات والعنصر الموجود فيها؟} other{احذف هذه الألبومات و {count} العناصر فيها؟}}",
+ "@deleteMultiAlbumConfirmationDialogMessage": {
+ "placeholders": {
+ "count": {}
+ }
+ },
+ "settingsSubtitleThemeTextSize": "حجم الخط",
+ "@settingsSubtitleThemeTextSize": {},
+ "aboutLicensesSectionTitle": "تراخيص مفتوحة المصدر",
+ "@aboutLicensesSectionTitle": {},
+ "menuActionStats": "احصائيات",
+ "@menuActionStats": {},
+ "settingsCollectionQuickActionTabBrowsing": "التصفح",
+ "@settingsCollectionQuickActionTabBrowsing": {},
+ "chipActionCreateAlbum": "إنشاء ألبوم",
+ "@chipActionCreateAlbum": {},
+ "videoLoopModeShortOnly": "فيديوهات قصيرة فقط",
+ "@videoLoopModeShortOnly": {},
+ "deleteSingleAlbumConfirmationDialogMessage": "{count, plural, =1{هل تريد حذف هذا الألبوم والعنصر الموجود فيه؟} other{احذف هذا الألبوم و {count} العناصر فيه؟}}",
+ "@deleteSingleAlbumConfirmationDialogMessage": {
+ "placeholders": {
+ "count": {}
+ }
+ },
+ "settingsThemeColorHighlights": "تحديد الألوان",
+ "@settingsThemeColorHighlights": {},
+ "appPickDialogTitle": "اختر التطبيق",
+ "@appPickDialogTitle": {},
+ "settingsHiddenItemsTabPaths": "المسارات المخفية",
+ "@settingsHiddenItemsTabPaths": {},
+ "viewerInfoSearchSuggestionRights": "حقوق",
+ "@viewerInfoSearchSuggestionRights": {},
+ "mapPointNorthUpTooltip": "نقطة الشمال لأعلى",
+ "@mapPointNorthUpTooltip": {},
+ "entryInfoActionRemoveLocation": "إزالة الموقع",
+ "@entryInfoActionRemoveLocation": {},
+ "collectionDeleteFailureFeedback": "{count, plural, =1{فشل حذف عنصر واحد} other{فشل الحذف {count} items}}",
+ "@collectionDeleteFailureFeedback": {
+ "placeholders": {
+ "count": {}
+ }
+ },
+ "entryActionShareImageOnly": "مشاركة الصورة فقط",
+ "@entryActionShareImageOnly": {},
+ "settingsVideoButtonsTile": "أزرار",
+ "@settingsVideoButtonsTile": {},
+ "settingsSubtitleThemeSample": "هذه عينة.",
+ "@settingsSubtitleThemeSample": {},
+ "albumPickPageTitleMove": "انتقل إلى الألبوم",
+ "@albumPickPageTitleMove": {},
+ "settingsSaveSearchHistory": "حفظ سجل البحث",
+ "@settingsSaveSearchHistory": {},
+ "settingsViewerShowHistogram": "إظهار الرسم البياني",
+ "@settingsViewerShowHistogram": {},
+ "aboutBugCopyInfoButton": "نسخ",
+ "@aboutBugCopyInfoButton": {},
+ "mapStyleGoogleHybrid": "خرائط جوجل (الهجينة)",
+ "@mapStyleGoogleHybrid": {},
+ "wallpaperTargetHomeLock": "الشاشة الرئيسية وشاشة القفل",
+ "@wallpaperTargetHomeLock": {},
+ "coverDialogTabCover": "غلاف",
+ "@coverDialogTabCover": {},
+ "settingsVideoPlaybackTile": "التشغيل",
+ "@settingsVideoPlaybackTile": {},
+ "filterNoDateLabel": "غير مؤرخ",
+ "@filterNoDateLabel": {},
+ "exportEntryDialogWriteMetadata": "كتابة البيانات الوصفية",
+ "@exportEntryDialogWriteMetadata": {}
}
diff --git a/lib/l10n/app_be.arb b/lib/l10n/app_be.arb
index 04857893c..2d919b3fd 100644
--- a/lib/l10n/app_be.arb
+++ b/lib/l10n/app_be.arb
@@ -166,30 +166,6 @@
"@slideshowActionResume": {},
"viewerActionUnlock": "Разблакіроўка прагляду",
"@viewerActionUnlock": {},
- "columnCount": "{count, plural, =1{1 column} other{{count} columns}}",
- "@columnCount": {
- "placeholders": {
- "count": {}
- }
- },
- "timeSeconds": "{seconds, plural, =1{1 second} other{{seconds} seconds}}",
- "@timeSeconds": {
- "placeholders": {
- "seconds": {}
- }
- },
- "timeMinutes": "{minutes, plural, =1{1 minute} other{{minutes} minutes}}",
- "@timeMinutes": {
- "placeholders": {
- "minutes": {}
- }
- },
- "timeDays": "{days, plural, =1{1 day} other{{days} days}}",
- "@timeDays": {
- "placeholders": {
- "days": {}
- }
- },
"entryActionExport": "Экспарт",
"@entryActionExport": {},
"entryActionInfo": "Інфармацыя",
@@ -236,7 +212,7 @@
"@cropAspectRatioOriginal": {},
"cropAspectRatioSquare": "Квадратнае",
"@cropAspectRatioSquare": {},
- "coordinateDmsNorth": "Поўнач",
+ "coordinateDmsNorth": "Пн",
"@coordinateDmsNorth": {},
"filterAspectRatioPortraitLabel": "Партрэтныя",
"@filterAspectRatioPortraitLabel": {},
@@ -295,7 +271,7 @@
"@filterNoDateLabel": {},
"filterNoAddressLabel": "Без адрасу",
"@filterNoAddressLabel": {},
- "filterLocatedLabel": "Месцазнаходжанне",
+ "filterLocatedLabel": "Размешчаны",
"@filterLocatedLabel": {},
"filterNoLocationLabel": "Без месцазнаходжання",
"@filterNoLocationLabel": {},
@@ -325,11 +301,11 @@
"@albumTierVaults": {},
"albumTierSpecial": "Стандартныя",
"@albumTierSpecial": {},
- "coordinateDmsSouth": "Поўдзень",
+ "coordinateDmsSouth": "Пд",
"@coordinateDmsSouth": {},
- "coordinateDmsEast": "Усход",
+ "coordinateDmsEast": "У",
"@coordinateDmsEast": {},
- "coordinateDmsWest": "Захад",
+ "coordinateDmsWest": "З",
"@coordinateDmsWest": {},
"displayRefreshRatePreferHighest": "Найвышэйшая частата",
"@displayRefreshRatePreferHighest": {},
@@ -415,7 +391,7 @@
"@storageVolumeDescriptionFallbackNonPrimary": {},
"rootDirectoryDescription": "каранёвы каталог",
"@rootDirectoryDescription": {},
- "otherDirectoryDescription": "Каталог “{name}”",
+ "otherDirectoryDescription": "Каталог «{name}»",
"@otherDirectoryDescription": {
"placeholders": {
"name": {
@@ -439,7 +415,7 @@
}
}
},
- "notEnoughSpaceDialogMessage": "Для завяршэння гэтай аперацыі патрабуецца {neededSize} вольнага месца на “{volume}”, але засталося толькі {freeSize}.",
+ "notEnoughSpaceDialogMessage": "Для завяршэння гэтай аперацыі патрабуецца {neededSize} вольнага месца на «{volume}», але засталося толькі {freeSize}.",
"@notEnoughSpaceDialogMessage": {
"placeholders": {
"neededSize": {
@@ -830,5 +806,717 @@
"settingsThemeColorHighlights": "Каляровыя акцэнты",
"@settingsThemeColorHighlights": {},
"exportEntryDialogWriteMetadata": "Запісаць метададзеныя",
- "@exportEntryDialogWriteMetadata": {}
+ "@exportEntryDialogWriteMetadata": {},
+ "aboutCreditsWorldAtlas2": "пад ліцэнзіяй ISC.",
+ "@aboutCreditsWorldAtlas2": {},
+ "settingsPrivacySectionTitle": "Канфідэнцыяльнасць",
+ "@settingsPrivacySectionTitle": {},
+ "albumScreenRecordings": "Запісы экрана",
+ "@albumScreenRecordings": {},
+ "editEntryRatingDialogTitle": "Рэйтынг",
+ "@editEntryRatingDialogTitle": {},
+ "aboutDataUsageMisc": "Розныя",
+ "@aboutDataUsageMisc": {},
+ "albumVideoCaptures": "Відэазапісы",
+ "@albumVideoCaptures": {},
+ "editEntryDateDialogSetCustom": "Усталяваць карыстацкую дату",
+ "@editEntryDateDialogSetCustom": {},
+ "settingsSearchEmpty": "Няма адпаведнай налады",
+ "@settingsSearchEmpty": {},
+ "removeEntryMetadataDialogMore": "Больш",
+ "@removeEntryMetadataDialogMore": {},
+ "tooManyItemsErrorDialogMessage": "Паўтарыце спробу з меншай колькасцю элементаў.",
+ "@tooManyItemsErrorDialogMessage": {},
+ "collectionActionEdit": "Рэдагаваць",
+ "@collectionActionEdit": {},
+ "sortOrderLargestFirst": "Спачатку вялікія",
+ "@sortOrderLargestFirst": {},
+ "editEntryDateDialogSourceFileModifiedDate": "Дата змены файла",
+ "@editEntryDateDialogSourceFileModifiedDate": {},
+ "collectionEmptyFavourites": "Няма абраных",
+ "@collectionEmptyFavourites": {},
+ "removeEntryMetadataDialogTitle": "Выдаленне метададзеных",
+ "@removeEntryMetadataDialogTitle": {},
+ "drawerCollectionVideos": "Відэа",
+ "@drawerCollectionVideos": {},
+ "countryEmpty": "Няма краін",
+ "@countryEmpty": {},
+ "collectionSelectSectionTooltip": "Выбраць раздзел",
+ "@collectionSelectSectionTooltip": {},
+ "aboutLicensesBanner": "Гэта праграма выкарыстоўвае наступныя пакеты і бібліятэкі з адкрытым зыходным кодам.",
+ "@aboutLicensesBanner": {},
+ "dateYesterday": "Учора",
+ "@dateYesterday": {},
+ "aboutDataUsageDatabase": "База дадзеных",
+ "@aboutDataUsageDatabase": {},
+ "tileLayoutMosaic": "Мазаіка",
+ "@tileLayoutMosaic": {},
+ "collectionDeselectSectionTooltip": "Адмяніць выбар раздзела",
+ "@collectionDeselectSectionTooltip": {},
+ "settingsKeepScreenOnTile": "Трымаць экран уключаным",
+ "@settingsKeepScreenOnTile": {},
+ "tileLayoutGrid": "Сетка",
+ "@tileLayoutGrid": {},
+ "aboutCreditsWorldAtlas1": "Гэта праграма выкарыстоўвае файл TopoJSON з",
+ "@aboutCreditsWorldAtlas1": {},
+ "appExportCovers": "Вокладкі",
+ "@appExportCovers": {},
+ "createAlbumButtonLabel": "СТВАРЫЦЬ",
+ "@createAlbumButtonLabel": {},
+ "menuActionSlideshow": "Слайд-шоў",
+ "@menuActionSlideshow": {},
+ "settingsConfirmationDialogTitle": "Дыялогі пацверджання",
+ "@settingsConfirmationDialogTitle": {},
+ "videoStreamSelectionDialogText": "Субтытры",
+ "@videoStreamSelectionDialogText": {},
+ "editEntryDateDialogShift": "Зрух",
+ "@editEntryDateDialogShift": {},
+ "appExportSettings": "Налады",
+ "@appExportSettings": {},
+ "searchPlacesSectionTitle": "Месцы",
+ "@searchPlacesSectionTitle": {},
+ "videoStreamSelectionDialogAudio": "Аўдыё",
+ "@videoStreamSelectionDialogAudio": {},
+ "videoSpeedDialogLabel": "Хуткасць прайгравання",
+ "@videoSpeedDialogLabel": {},
+ "editEntryLocationDialogSetCustom": "Устанавіць карыстацкае месцазнаходжанне",
+ "@editEntryLocationDialogSetCustom": {},
+ "placeEmpty": "Няма месцаў",
+ "@placeEmpty": {},
+ "editEntryDateDialogExtractFromTitle": "Выняць з загалоўка",
+ "@editEntryDateDialogExtractFromTitle": {},
+ "aboutLinkLicense": "Ліцэнзія",
+ "@aboutLinkLicense": {},
+ "albumScreenshots": "Скрыншоты",
+ "@albumScreenshots": {},
+ "editEntryLocationDialogLongitude": "Даўгата",
+ "@editEntryLocationDialogLongitude": {},
+ "searchCountriesSectionTitle": "Краіны",
+ "@searchCountriesSectionTitle": {},
+ "settingsAskEverytime": "Пытацца кожны раз",
+ "@settingsAskEverytime": {},
+ "editEntryDateDialogCopyField": "Капіяваць з іншай даты",
+ "@editEntryDateDialogCopyField": {},
+ "searchTagsSectionTitle": "Тэгі",
+ "@searchTagsSectionTitle": {},
+ "settingsModificationWarningDialogMessage": "Іншыя налады будуць зменены.",
+ "@settingsModificationWarningDialogMessage": {},
+ "policyPageTitle": "Палітыка канфідэнцыяльнасці",
+ "@policyPageTitle": {},
+ "tileLayoutList": "Спіс",
+ "@tileLayoutList": {},
+ "appPickDialogNone": "Нічога",
+ "@appPickDialogNone": {},
+ "settingsActionExport": "Экспарт",
+ "@settingsActionExport": {},
+ "sortOrderOldestFirst": "Спачатку самы стары",
+ "@sortOrderOldestFirst": {},
+ "coverDialogTabApp": "Праграма",
+ "@coverDialogTabApp": {},
+ "removeEntryMetadataMotionPhotoXmpWarningDialogMessage": "XMP патрабуецца для прайгравання відэа ўнутры фота з рухам.\n\nВы ўпэўнены, што хочаце выдаліць яго?",
+ "@removeEntryMetadataMotionPhotoXmpWarningDialogMessage": {},
+ "tagPageTitle": "Тэгі",
+ "@tagPageTitle": {},
+ "collectionEmptyVideos": "Няма відэа",
+ "@collectionEmptyVideos": {},
+ "aboutCreditsSectionTitle": "Падзякі",
+ "@aboutCreditsSectionTitle": {},
+ "drawerAlbumPage": "Альбомы",
+ "@drawerAlbumPage": {},
+ "settingsActionImport": "Імпарт",
+ "@settingsActionImport": {},
+ "locationPickerUseThisLocationButton": "Выкарыстоўваць гэтае месца",
+ "@locationPickerUseThisLocationButton": {},
+ "collectionGroupNone": "Не групаваць",
+ "@collectionGroupNone": {},
+ "searchRatingSectionTitle": "Рэйтынгі",
+ "@searchRatingSectionTitle": {},
+ "settingsDisabled": "Адключана",
+ "@settingsDisabled": {},
+ "settingsActionImportDialogTitle": "Імпарт",
+ "@settingsActionImportDialogTitle": {},
+ "albumGroupTier": "Па ўзроўні",
+ "@albumGroupTier": {},
+ "drawerCollectionAll": "Уся калекцыя",
+ "@drawerCollectionAll": {},
+ "sortByItemCount": "Па колькасці элементаў",
+ "@sortByItemCount": {},
+ "sectionUnknown": "Невядома",
+ "@sectionUnknown": {},
+ "dateToday": "Сёння",
+ "@dateToday": {},
+ "videoStreamSelectionDialogNoSelection": "Іншых трэкаў няма.",
+ "@videoStreamSelectionDialogNoSelection": {},
+ "searchRecentSectionTitle": "Апошнія",
+ "@searchRecentSectionTitle": {},
+ "albumPickPageTitlePick": "Выбраць Альбом",
+ "@albumPickPageTitlePick": {},
+ "menuActionMap": "Карта",
+ "@menuActionMap": {},
+ "collectionActionMove": "Перамясціць у альбом",
+ "@collectionActionMove": {},
+ "searchAlbumsSectionTitle": "Альбомы",
+ "@searchAlbumsSectionTitle": {},
+ "viewDialogGroupSectionTitle": "Групоўка",
+ "@viewDialogGroupSectionTitle": {},
+ "aboutDataUsageSectionTitle": "Выкарыстанне дадзеных",
+ "@aboutDataUsageSectionTitle": {},
+ "durationDialogSeconds": "Секунды",
+ "@durationDialogSeconds": {},
+ "albumEmpty": "Няма альбомаў",
+ "@albumEmpty": {},
+ "editEntryLocationDialogChooseOnMap": "Выбраць на карце",
+ "@editEntryLocationDialogChooseOnMap": {},
+ "sortByName": "Па назве",
+ "@sortByName": {},
+ "settingsHomeDialogTitle": "Галоўная",
+ "@settingsHomeDialogTitle": {},
+ "searchDateSectionTitle": "Дата",
+ "@searchDateSectionTitle": {},
+ "collectionSearchTitlesHintText": "Пошук загалоўкаў",
+ "@collectionSearchTitlesHintText": {},
+ "searchCollectionFieldHint": "Пошук калекцый",
+ "@searchCollectionFieldHint": {},
+ "settingsDoubleBackExit": "Двойчы націсніце «назад», каб выйсці",
+ "@settingsDoubleBackExit": {},
+ "drawerCollectionSphericalVideos": "360° Відэа",
+ "@drawerCollectionSphericalVideos": {},
+ "searchMetadataSectionTitle": "Метададзеныя",
+ "@searchMetadataSectionTitle": {},
+ "settingsShowBottomNavigationBar": "Паказаць ніжнюю панэль навігацыі",
+ "@settingsShowBottomNavigationBar": {},
+ "collectionActionEmptyBin": "Ачысціць кошык",
+ "@collectionActionEmptyBin": {},
+ "sortOrderAtoZ": "Ад А да Я",
+ "@sortOrderAtoZ": {},
+ "videoStreamSelectionDialogTrack": "Трэк",
+ "@videoStreamSelectionDialogTrack": {},
+ "settingsHomeTile": "Галоўная",
+ "@settingsHomeTile": {},
+ "collectionGroupDay": "Па днях",
+ "@collectionGroupDay": {},
+ "collectionGroupAlbum": "Па альбоме",
+ "@collectionGroupAlbum": {},
+ "newFilterBanner": "новы",
+ "@newFilterBanner": {},
+ "drawerCollectionFavourites": "Абраныя",
+ "@drawerCollectionFavourites": {},
+ "aboutLicensesFlutterPackagesSectionTitle": "Пакеты Flutter",
+ "@aboutLicensesFlutterPackagesSectionTitle": {},
+ "statePageTitle": "Штаты",
+ "@statePageTitle": {},
+ "drawerTagPage": "Тэгі",
+ "@drawerTagPage": {},
+ "durationDialogMinutes": "Хвіліны",
+ "@durationDialogMinutes": {},
+ "albumPageTitle": "Альбомы",
+ "@albumPageTitle": {},
+ "editEntryLocationDialogTitle": "Месцазнаходжанне",
+ "@editEntryLocationDialogTitle": {},
+ "albumPickPageTitleCopy": "Капіюваць у альбом",
+ "@albumPickPageTitleCopy": {},
+ "collectionActionCopy": "Скапіюваць у альбом",
+ "@collectionActionCopy": {},
+ "viewDialogReverseSortOrder": "Адваротны парадак сартавання",
+ "@viewDialogReverseSortOrder": {},
+ "menuActionConfigureView": "Выгляд",
+ "@menuActionConfigureView": {},
+ "aboutLicensesDartPackagesSectionTitle": "Пакеты Dart",
+ "@aboutLicensesDartPackagesSectionTitle": {},
+ "drawerCollectionMotionPhotos": "Фота з рухам",
+ "@drawerCollectionMotionPhotos": {},
+ "settingsDefault": "Па змаўчанні",
+ "@settingsDefault": {},
+ "placePageTitle": "Месцы",
+ "@placePageTitle": {},
+ "tagEmpty": "Няма тэгаў",
+ "@tagEmpty": {},
+ "collectionActionShowTitleSearch": "Паказаць фільтр загалоўка",
+ "@collectionActionShowTitleSearch": {},
+ "menuActionSelectAll": "Выбраць усё",
+ "@menuActionSelectAll": {},
+ "settingsConfirmationTile": "Дыялогі пацверджання",
+ "@settingsConfirmationTile": {},
+ "albumMimeTypeMixed": "Змешаны",
+ "@albumMimeTypeMixed": {},
+ "aboutLinkPolicy": "Палітыка канфідэнцыяльнасці",
+ "@aboutLinkPolicy": {},
+ "sortOrderLowestFirst": "Спачатку з нізкім",
+ "@sortOrderLowestFirst": {},
+ "albumGroupNone": "Не групаваць",
+ "@albumGroupNone": {},
+ "countryPageTitle": "Краіны",
+ "@countryPageTitle": {},
+ "albumGroupType": "Па тыпу",
+ "@albumGroupType": {},
+ "albumCamera": "Камера",
+ "@albumCamera": {},
+ "settingsNavigationSectionTitle": "Навігацыя",
+ "@settingsNavigationSectionTitle": {},
+ "collectionActionHideTitleSearch": "Схаваць фільтр загалоўка",
+ "@collectionActionHideTitleSearch": {},
+ "drawerCollectionAnimated": "Анімацыі",
+ "@drawerCollectionAnimated": {},
+ "durationDialogHours": "Гадзіны",
+ "@durationDialogHours": {},
+ "settingsKeepScreenOnDialogTitle": "Трымаць экран уключаным",
+ "@settingsKeepScreenOnDialogTitle": {},
+ "drawerPlacePage": "Месцы",
+ "@drawerPlacePage": {},
+ "menuActionSelect": "Выбраць",
+ "@menuActionSelect": {},
+ "drawerCollectionPanoramas": "Панарамы",
+ "@drawerCollectionPanoramas": {},
+ "settingsPageTitle": "Налады",
+ "@settingsPageTitle": {},
+ "menuActionSelectNone": "Зняць вылучэнне",
+ "@menuActionSelectNone": {},
+ "settingsSearchFieldLabel": "Пошук налад",
+ "@settingsSearchFieldLabel": {},
+ "appExportFavourites": "Абранае",
+ "@appExportFavourites": {},
+ "collectionEmptyImages": "Няма выяў",
+ "@collectionEmptyImages": {},
+ "albumPickPageTitleExport": "Экспартаваць у альбом",
+ "@albumPickPageTitleExport": {},
+ "settingsActionExportDialogTitle": "Экспарт",
+ "@settingsActionExportDialogTitle": {},
+ "genericDangerWarningDialogMessage": "Вы ўпэўнены?",
+ "@genericDangerWarningDialogMessage": {},
+ "aboutDataUsageExternal": "Знешні",
+ "@aboutDataUsageExternal": {},
+ "collectionSelectPageTitle": "Выбраць элементы",
+ "@collectionSelectPageTitle": {},
+ "editEntryLocationDialogLatitude": "Шырата",
+ "@editEntryLocationDialogLatitude": {},
+ "collectionActionRescan": "Паўторнае сканаванне",
+ "@collectionActionRescan": {},
+ "viewDialogSortSectionTitle": "Сартаваць",
+ "@viewDialogSortSectionTitle": {},
+ "collectionPageTitle": "Калекцыя",
+ "@collectionPageTitle": {},
+ "collectionActionAddShortcut": "Дадаць ярлык",
+ "@collectionActionAddShortcut": {},
+ "albumGroupVolume": "Па аб'ёме захоўвання",
+ "@albumGroupVolume": {},
+ "collectionGroupMonth": "Па месяцу",
+ "@collectionGroupMonth": {},
+ "sortByDate": "Па даце",
+ "@sortByDate": {},
+ "sortOrderZtoA": "Ад Я да А",
+ "@sortOrderZtoA": {},
+ "drawerAboutButton": "Пра нас",
+ "@drawerAboutButton": {},
+ "aboutTranslatorsSectionTitle": "Перакладчыкі",
+ "@aboutTranslatorsSectionTitle": {},
+ "videoStreamSelectionDialogOff": "Адкл.",
+ "@videoStreamSelectionDialogOff": {},
+ "drawerCollectionImages": "Выявы",
+ "@drawerCollectionImages": {},
+ "sortOrderSmallestFirst": "Спачатку маленькі",
+ "@sortOrderSmallestFirst": {},
+ "sortBySize": "Па памеры",
+ "@sortBySize": {},
+ "collectionPickPageTitle": "Выбраць",
+ "@collectionPickPageTitle": {},
+ "collectionEmptyGrantAccessButtonLabel": "Даць доступ",
+ "@collectionEmptyGrantAccessButtonLabel": {},
+ "videoStreamSelectionDialogVideo": "Відэа",
+ "@videoStreamSelectionDialogVideo": {},
+ "viewDialogLayoutSectionTitle": "Макет",
+ "@viewDialogLayoutSectionTitle": {},
+ "searchStatesSectionTitle": "Штаты",
+ "@searchStatesSectionTitle": {},
+ "dateThisMonth": "У гэтым месяцы",
+ "@dateThisMonth": {},
+ "aboutPageTitle": "Пра нас",
+ "@aboutPageTitle": {},
+ "sortByRating": "Па рэйтынгу",
+ "@sortByRating": {},
+ "stateEmpty": "Няма штатаў",
+ "@stateEmpty": {},
+ "drawerCountryPage": "Краіны",
+ "@drawerCountryPage": {},
+ "genericFailureFeedback": "Не атрымалася",
+ "@genericFailureFeedback": {},
+ "aboutDataUsageData": "Дадзеныя",
+ "@aboutDataUsageData": {},
+ "aboutDataUsageInternal": "Унутраны",
+ "@aboutDataUsageInternal": {},
+ "albumDownload": "Загрузкі",
+ "@albumDownload": {},
+ "coverDialogTabColor": "Колер",
+ "@coverDialogTabColor": {},
+ "genericSuccessFeedback": "Гатова!",
+ "@genericSuccessFeedback": {},
+ "aboutLicensesShowAllButtonLabel": "Паказаць усе ліцэнзіі",
+ "@aboutLicensesShowAllButtonLabel": {},
+ "sortOrderNewestFirst": "Спачатку самае новае",
+ "@sortOrderNewestFirst": {},
+ "drawerSettingsButton": "Налады",
+ "@drawerSettingsButton": {},
+ "drawerCollectionRaws": "Raw фатаграфіі",
+ "@drawerCollectionRaws": {},
+ "castDialogTitle": "Прылады трансляцыі",
+ "@castDialogTitle": {},
+ "aboutLicensesFlutterPluginsSectionTitle": "Плагіны Flutter",
+ "@aboutLicensesFlutterPluginsSectionTitle": {},
+ "sortOrderHighestFirst": "Спачатку з высокім",
+ "@sortOrderHighestFirst": {},
+ "aboutLicensesAndroidLibrariesSectionTitle": "Бібліятэкі Android",
+ "@aboutLicensesAndroidLibrariesSectionTitle": {},
+ "binPageTitle": "Кошык",
+ "@binPageTitle": {},
+ "sortByAlbumFileName": "Па назве альбома і файла",
+ "@sortByAlbumFileName": {},
+ "aboutLicensesSectionTitle": "Ліцэнзіі з адкрытым зыходным кодам",
+ "@aboutLicensesSectionTitle": {},
+ "menuActionStats": "Статыстыка",
+ "@menuActionStats": {},
+ "appPickDialogTitle": "Выбраць праграму",
+ "@appPickDialogTitle": {},
+ "albumPickPageTitleMove": "Перамясціць у альбом",
+ "@albumPickPageTitleMove": {},
+ "coverDialogTabCover": "Вокладка",
+ "@coverDialogTabCover": {},
+ "settingsConfirmationBeforeDeleteItems": "Спытаць, перш чым выдаляць элементы назаўжды",
+ "@settingsConfirmationBeforeDeleteItems": {},
+ "settingsConfirmationBeforeMoveUndatedItems": "Спытаць, перш чым перамяшчаць прадметы без даты",
+ "@settingsConfirmationBeforeMoveUndatedItems": {},
+ "settingsConfirmationAfterMoveToBinItems": "Паказваць паведамленне пасля перамяшчэння элементаў у кошык",
+ "@settingsConfirmationAfterMoveToBinItems": {},
+ "settingsConfirmationBeforeMoveToBinItems": "Спытаць, перш чым перамяшчаць элементы ў кошык",
+ "@settingsConfirmationBeforeMoveToBinItems": {},
+ "settingsNavigationDrawerAddAlbum": "Дадаць альбом",
+ "@settingsNavigationDrawerAddAlbum": {},
+ "settingsEnableBinSubtitle": "Захоўвае выдаленыя элементы на працягу 30 дзён",
+ "@settingsEnableBinSubtitle": {},
+ "settingsThumbnailShowRating": "Паказаць рэйтынг",
+ "@settingsThumbnailShowRating": {},
+ "collectionExportFailureFeedback": "{count, plural, =1{Не атрымалася экспартаваць 1 старонку} few{Не атрымалася экспартаваць {count} старонкі} other{Не атрымалася экспартаваць {count} старонак}}",
+ "@collectionExportFailureFeedback": {
+ "placeholders": {
+ "count": {}
+ }
+ },
+ "settingsSubtitleThemeTextAlignmentDialogTitle": "Выраўноўванне тэксту",
+ "@settingsSubtitleThemeTextAlignmentDialogTitle": {},
+ "settingsViewerSlideshowPageTitle": "Слайд-шоў",
+ "@settingsViewerSlideshowPageTitle": {},
+ "settingsViewerSectionTitle": "Прагляднік",
+ "@settingsViewerSectionTitle": {},
+ "settingsAllowInstalledAppAccessSubtitle": "Выкарыстоўваецца для паляпшэння адлюстравання альбомаў",
+ "@settingsAllowInstalledAppAccessSubtitle": {},
+ "collectionMoveFailureFeedback": "{count, plural, =1{Немагчыма перанесці 1 элемент} few{Немагчыма перанесці {count} элементы} other{Немагчыма перанесці {count} элементаў}}",
+ "@collectionMoveFailureFeedback": {
+ "placeholders": {
+ "count": {}
+ }
+ },
+ "settingsSubtitleThemeTextColor": "Колер тэксту",
+ "@settingsSubtitleThemeTextColor": {},
+ "settingsVideoSectionTitle": "Відэа",
+ "@settingsVideoSectionTitle": {},
+ "settingsSubtitleThemeBackgroundColor": "Колер фону",
+ "@settingsSubtitleThemeBackgroundColor": {},
+ "settingsThumbnailOverlayTile": "Навязванне",
+ "@settingsThumbnailOverlayTile": {},
+ "settingsNavigationDrawerTabPages": "Старонкі",
+ "@settingsNavigationDrawerTabPages": {},
+ "settingsVideoAutoPlay": "Аўтапрайграванне",
+ "@settingsVideoAutoPlay": {},
+ "settingsVideoEnableHardwareAcceleration": "Апаратнае паскарэнне",
+ "@settingsVideoEnableHardwareAcceleration": {},
+ "settingsCollectionSelectionQuickActionEditorBanner": "Націсніце і ўтрымлівайце, каб перамясціць кнопкі і выбраць дзеянні, якія будуць адлюстроўвацца пры выбары элементаў.",
+ "@settingsCollectionSelectionQuickActionEditorBanner": {},
+ "settingsSlideshowShuffle": "Ператасаваць",
+ "@settingsSlideshowShuffle": {},
+ "settingsThumbnailSectionTitle": "Мініяцюры",
+ "@settingsThumbnailSectionTitle": {},
+ "settingsVideoShowVideos": "Паказаць відэа",
+ "@settingsVideoShowVideos": {},
+ "settingsViewerShowInformation": "Паказаць інфармацыю",
+ "@settingsViewerShowInformation": {},
+ "settingsCollectionQuickActionsTile": "Хуткія дзеянні",
+ "@settingsCollectionQuickActionsTile": {},
+ "settingsViewerOverlayTile": "Навязванне",
+ "@settingsViewerOverlayTile": {},
+ "settingsThumbnailShowFavouriteIcon": "Паказаць значок абранага",
+ "@settingsThumbnailShowFavouriteIcon": {},
+ "settingsSubtitleThemeTextPositionDialogTitle": "Палажэнне тэксту",
+ "@settingsSubtitleThemeTextPositionDialogTitle": {},
+ "settingsSlideshowIntervalTile": "Інтэрвал",
+ "@settingsSlideshowIntervalTile": {},
+ "settingsCollectionQuickActionEditorPageTitle": "Хуткія дзеянні",
+ "@settingsCollectionQuickActionEditorPageTitle": {},
+ "settingsStorageAccessRevokeTooltip": "Адклікаць",
+ "@settingsStorageAccessRevokeTooltip": {},
+ "settingsSubtitleThemeTile": "Субтытры",
+ "@settingsSubtitleThemeTile": {},
+ "settingsVideoGestureVerticalDragBrightnessVolume": "Правядзіце пальцам уверх ці ўніз, каб наладзіць яркасць/гучнасць",
+ "@settingsVideoGestureVerticalDragBrightnessVolume": {},
+ "settingsAccessibilitySectionTitle": "Спецыяльныя магчымасці",
+ "@settingsAccessibilitySectionTitle": {},
+ "collectionRenameFailureFeedback": "{count, plural, =1{Не атрымалася перайменаваць 1 элемент} few{Не атрымалася перайменаваць {count} элементы} other{Не атрымалася перайменаваць {count} элементаў}}",
+ "@collectionRenameFailureFeedback": {
+ "placeholders": {
+ "count": {}
+ }
+ },
+ "collectionEditSuccessFeedback": "{count, plural, =1{1 элемент адрэдагаваны} few{{count} элементы адрэдагаваны} other{{count} элементаў адрэдагаваны}}",
+ "@collectionEditSuccessFeedback": {
+ "placeholders": {
+ "count": {}
+ }
+ },
+ "settingsThumbnailShowMotionPhotoIcon": "Паказаць значок фота з рухам",
+ "@settingsThumbnailShowMotionPhotoIcon": {},
+ "settingsThumbnailShowRawIcon": "Паказаць значок raw",
+ "@settingsThumbnailShowRawIcon": {},
+ "settingsSlideshowFillScreen": "Запоўніць экран",
+ "@settingsSlideshowFillScreen": {},
+ "settingsHiddenFiltersBanner": "Фота і відэа, якія адпавядаюць схаваным фільтрам, не будуць адлюстроўвацца ў вашай калекцыі.",
+ "@settingsHiddenFiltersBanner": {},
+ "settingsVideoResumptionModeTile": "Працягнуць прайграванне",
+ "@settingsVideoResumptionModeTile": {},
+ "collectionCopyFailureFeedback": "{count, plural, =1{Не атрымалася скапіюваць 1 элемент} few{Не атрымалася скапіюваць {count} элементы} other{Не атрымалася скапіюваць {count} элементаў}}",
+ "@collectionCopyFailureFeedback": {
+ "placeholders": {
+ "count": {}
+ }
+ },
+ "settingsVideoGestureDoubleTapTogglePlay": "Двойчы націсніце, каб прайграць/прыпыніць",
+ "@settingsVideoGestureDoubleTapTogglePlay": {},
+ "addPathTooltip": "Дадаць шлях",
+ "@addPathTooltip": {},
+ "settingsEnableBin": "Выкарыстоўваць кошык",
+ "@settingsEnableBin": {},
+ "collectionMoveSuccessFeedback": "{count, plural, =1{Перамяшчаны 1 элемент} few{Перамяшчаны {count} элементы} other{Перамяшчаны {count} элементаў}}",
+ "@collectionMoveSuccessFeedback": {
+ "placeholders": {
+ "count": {}
+ }
+ },
+ "settingsSubtitleThemeTextAlignmentLeft": "Злева",
+ "@settingsSubtitleThemeTextAlignmentLeft": {},
+ "settingsVideoGestureSideDoubleTapSeek": "Двойчы націсніце на край экрана, каб перайсці назад/наперад",
+ "@settingsVideoGestureSideDoubleTapSeek": {},
+ "settingsSubtitleThemeTextAlignmentRight": "Справа",
+ "@settingsSubtitleThemeTextAlignmentRight": {},
+ "settingsAllowMediaManagement": "Дазволіць кіраванне мультымедыя",
+ "@settingsAllowMediaManagement": {},
+ "settingsCollectionBrowsingQuickActionEditorBanner": "Націсніце і ўтрымлівайце, каб перамясціць кнопкі і выбраць дзеянні, якія будуць адлюстроўвацца пры праглядзе элементаў.",
+ "@settingsCollectionBrowsingQuickActionEditorBanner": {},
+ "collectionEditFailureFeedback": "{count, plural, =1{Немагчыма адрэдагаваць 1 элемент} few{Немагчыма адрэдагаваць {count} элементы} other{Немагчыма адрэдагаваць {count} элементаў}}",
+ "@collectionEditFailureFeedback": {
+ "placeholders": {
+ "count": {}
+ }
+ },
+ "settingsThumbnailOverlayPageTitle": "Навязванне",
+ "@settingsThumbnailOverlayPageTitle": {},
+ "settingsViewerShowInformationSubtitle": "Паказаць назву, дату, месцазнаходжанне і г.д.",
+ "@settingsViewerShowInformationSubtitle": {},
+ "settingsSlideshowRepeat": "Паўтарэнне",
+ "@settingsSlideshowRepeat": {},
+ "settingsViewerQuickActionEditorPageTitle": "Хуткія дзеянні",
+ "@settingsViewerQuickActionEditorPageTitle": {},
+ "settingsVideoPageTitle": "Налады відэа",
+ "@settingsVideoPageTitle": {},
+ "collectionRenameSuccessFeedback": "{count, plural, =1{Перайменаваны 1 элемент} few{Перайменаваны {count} элементы} other{Перайменаваны {count} элементаў}}",
+ "@collectionRenameSuccessFeedback": {
+ "placeholders": {
+ "count": {}
+ }
+ },
+ "settingsViewerUseCutout": "Выкарыстоўваць вобласць выраза",
+ "@settingsViewerUseCutout": {},
+ "settingsViewerGestureSideTapNext": "Дакраніцеся да краёў экрана, каб паказаць папярэдні/наступны элемент",
+ "@settingsViewerGestureSideTapNext": {},
+ "settingsSubtitleThemeTextAlignmentCenter": "Па цэнтры",
+ "@settingsSubtitleThemeTextAlignmentCenter": {},
+ "settingsSubtitleThemeTextAlignmentTile": "Выраўноўванне тэксту",
+ "@settingsSubtitleThemeTextAlignmentTile": {},
+ "settingsCollectionQuickActionTabSelecting": "Выбар",
+ "@settingsCollectionQuickActionTabSelecting": {},
+ "settingsAllowErrorReporting": "Дазволіць ананімнае паведамленне пра памылкі",
+ "@settingsAllowErrorReporting": {},
+ "settingsVideoLoopModeTile": "Цыклічны рэжым",
+ "@settingsVideoLoopModeTile": {},
+ "settingsNavigationDrawerEditorPageTitle": "Меню навігацыі",
+ "@settingsNavigationDrawerEditorPageTitle": {},
+ "statsWithGps": "{count, plural, =1{1 элемент з месцазнаходжаннем} few{{count} элементы з месцазнаходжаннем} other{{count} элементаў з месцазнаходжаннем}}",
+ "@statsWithGps": {
+ "placeholders": {
+ "count": {}
+ }
+ },
+ "settingsVideoResumptionModeDialogTitle": "Працягнуць прайграванне",
+ "@settingsVideoResumptionModeDialogTitle": {},
+ "settingsVideoBackgroundMode": "Фонавы рэжым",
+ "@settingsVideoBackgroundMode": {},
+ "settingsAllowInstalledAppAccess": "Дазволіць доступ да інвентара праграм",
+ "@settingsAllowInstalledAppAccess": {},
+ "settingsHiddenItemsTabFilters": "Схаваныя фільтры",
+ "@settingsHiddenItemsTabFilters": {},
+ "settingsSlideshowAnimatedZoomEffect": "Аніміраваны эфект маштабавання",
+ "@settingsSlideshowAnimatedZoomEffect": {},
+ "settingsViewerOverlayPageTitle": "Навязванне",
+ "@settingsViewerOverlayPageTitle": {},
+ "settingsNavigationDrawerTabTypes": "Тыпы",
+ "@settingsNavigationDrawerTabTypes": {},
+ "settingsHiddenItemsTile": "Схаваныя элементы",
+ "@settingsHiddenItemsTile": {},
+ "settingsThumbnailShowVideoDuration": "Паказаць працягласць відэа",
+ "@settingsThumbnailShowVideoDuration": {},
+ "settingsCollectionBurstPatternsNone": "Без ўспышкі",
+ "@settingsCollectionBurstPatternsNone": {},
+ "settingsViewerQuickActionEditorAvailableButtonsSectionTitle": "Даступныя кнопкі",
+ "@settingsViewerQuickActionEditorAvailableButtonsSectionTitle": {},
+ "settingsViewerShowDescription": "Паказаць апісанне",
+ "@settingsViewerShowDescription": {},
+ "settingsViewerQuickActionEditorBanner": "Націсніце і ўтрымлівайце, каб перамяшчаць кнопкі і выбіраць дзеянні для адлюстравання ў праглядніку.",
+ "@settingsViewerQuickActionEditorBanner": {},
+ "settingsDisablingBinWarningDialogMessage": "Элементы ў кошыку будуць выдалены назаўжды.",
+ "@settingsDisablingBinWarningDialogMessage": {},
+ "settingsViewerQuickActionEditorDisplayedButtonsSectionTitle": "Адлюстраваныя кнопкі",
+ "@settingsViewerQuickActionEditorDisplayedButtonsSectionTitle": {},
+ "settingsVideoPlaybackPageTitle": "Прайграванне",
+ "@settingsVideoPlaybackPageTitle": {},
+ "settingsNavigationDrawerTile": "Меню навігацыі",
+ "@settingsNavigationDrawerTile": {},
+ "settingsHiddenItemsPageTitle": "Схаваныя элементы",
+ "@settingsHiddenItemsPageTitle": {},
+ "settingsHiddenPathsBanner": "Фатаграфіі і відэа ў гэтых папках або ў любой з іх укладзеных папак не будуць адлюстроўвацца ў вашай калекцыі.",
+ "@settingsHiddenPathsBanner": {},
+ "settingsViewerShowOverlayOnOpening": "Паказаць на адкрыцці",
+ "@settingsViewerShowOverlayOnOpening": {},
+ "settingsViewerShowShootingDetails": "Паказаць дэталі здымкі",
+ "@settingsViewerShowShootingDetails": {},
+ "settingsConfirmationVaultDataLoss": "Паказаць папярэджанне аб страце даных сховішча",
+ "@settingsConfirmationVaultDataLoss": {},
+ "settingsSlideshowTransitionTile": "Пераход",
+ "@settingsSlideshowTransitionTile": {},
+ "settingsViewerMaximumBrightness": "Максімальная яркасць",
+ "@settingsViewerMaximumBrightness": {},
+ "settingsThumbnailShowTagIcon": "Паказаць значок тэга",
+ "@settingsThumbnailShowTagIcon": {},
+ "settingsStorageAccessEmpty": "Доступ не прадстаўлены",
+ "@settingsStorageAccessEmpty": {},
+ "settingsRemoveAnimationsTile": "Выдаліць анімацыі",
+ "@settingsRemoveAnimationsTile": {},
+ "settingsStorageAccessBanner": "Некаторыя каталогі патрабуюць відавочнага дазволу на змяненне файлаў у іх. Тут вы можаце прагледзець каталогі, да якіх вы раней далі доступ.",
+ "@settingsStorageAccessBanner": {},
+ "collectionCopySuccessFeedback": "{count, plural, =1{1 элемент скапіяваны} few{{count} элементы скапіявана} other{{count} элементаў скапіявана}}",
+ "@collectionCopySuccessFeedback": {
+ "placeholders": {
+ "count": {}
+ }
+ },
+ "settingsNavigationDrawerBanner": "Націсніце і ўтрымлівайце для перамяшчэння і змены парадку пунктаў меню.",
+ "@settingsNavigationDrawerBanner": {},
+ "settingsViewerShowMinimap": "Паказаць мінікарту",
+ "@settingsViewerShowMinimap": {},
+ "settingsCollectionBurstPatternsTile": "Шаблоны ўспышкі",
+ "@settingsCollectionBurstPatternsTile": {},
+ "settingsImageBackground": "Фон выявы",
+ "@settingsImageBackground": {},
+ "settingsVideoLoopModeDialogTitle": "Цыклічны рэжым",
+ "@settingsVideoLoopModeDialogTitle": {},
+ "settingsViewerShowOverlayThumbnails": "Паказаць мініяцюры",
+ "@settingsViewerShowOverlayThumbnails": {},
+ "settingsVideoControlsPageTitle": "Элементы кіравання",
+ "@settingsVideoControlsPageTitle": {},
+ "settingsSlideshowVideoPlaybackTile": "Прайграванне відэа",
+ "@settingsSlideshowVideoPlaybackTile": {},
+ "settingsHiddenFiltersEmpty": "Няма схаваных фільтраў",
+ "@settingsHiddenFiltersEmpty": {},
+ "settingsThumbnailShowLocationIcon": "Паказаць значок месцазнаходжання",
+ "@settingsThumbnailShowLocationIcon": {},
+ "settingsStorageAccessPageTitle": "Доступ да сховішча",
+ "@settingsStorageAccessPageTitle": {},
+ "settingsSubtitleThemeBackgroundOpacity": "Непразрыстасць фону",
+ "@settingsSubtitleThemeBackgroundOpacity": {},
+ "settingsStorageAccessTile": "Доступ да сховішча",
+ "@settingsStorageAccessTile": {},
+ "settingsViewerQuickActionEmpty": "Няма кнопак",
+ "@settingsViewerQuickActionEmpty": {},
+ "settingsViewerSlideshowTile": "Слайд-шоў",
+ "@settingsViewerSlideshowTile": {},
+ "settingsSubtitleThemeTextOpacity": "Непразрыстасць тэксту",
+ "@settingsSubtitleThemeTextOpacity": {},
+ "settingsViewerShowRatingTags": "Паказаць рэйтынг і тэгі",
+ "@settingsViewerShowRatingTags": {},
+ "settingsViewerEnableOverlayBlurEffect": "Эфект размыцця",
+ "@settingsViewerEnableOverlayBlurEffect": {},
+ "settingsMotionPhotoAutoPlay": "Аўтаматычнае прайграванне фатаграфій з рухам",
+ "@settingsMotionPhotoAutoPlay": {},
+ "settingsVideoControlsTile": "Элементы кіравання",
+ "@settingsVideoControlsTile": {},
+ "settingsSlideshowVideoPlaybackDialogTitle": "Прайграванне відэа",
+ "@settingsSlideshowVideoPlaybackDialogTitle": {},
+ "settingsSubtitleThemeShowOutline": "Паказаць контур і цень",
+ "@settingsSubtitleThemeShowOutline": {},
+ "settingsNavigationDrawerTabAlbums": "Альбомы",
+ "@settingsNavigationDrawerTabAlbums": {},
+ "settingsViewerQuickActionsTile": "Хуткія дзеянні",
+ "@settingsViewerQuickActionsTile": {},
+ "settingsSubtitleThemePageTitle": "Субтытры",
+ "@settingsSubtitleThemePageTitle": {},
+ "settingsSubtitleThemeTextPositionTile": "Палажэнне тэксту",
+ "@settingsSubtitleThemeTextPositionTile": {},
+ "settingsVideoBackgroundModeDialogTitle": "Фонавы рэжым",
+ "@settingsVideoBackgroundModeDialogTitle": {},
+ "deleteMultiAlbumConfirmationDialogMessage": "{count, plural, =1{Выдаліць гэтыя альбомы і элемент у іх?} few{Выдаліць гэтыя альбомы і {count} элементы у іх?} other{Выдаліць гэтыя альбомы і {count} элементаў у іх?}}",
+ "@deleteMultiAlbumConfirmationDialogMessage": {
+ "placeholders": {
+ "count": {}
+ }
+ },
+ "settingsSubtitleThemeTextSize": "Памер тэксту",
+ "@settingsSubtitleThemeTextSize": {},
+ "settingsCollectionQuickActionTabBrowsing": "Прагляд",
+ "@settingsCollectionQuickActionTabBrowsing": {},
+ "settingsHiddenItemsTabPaths": "Схаваныя шляхі",
+ "@settingsHiddenItemsTabPaths": {},
+ "collectionDeleteFailureFeedback": "{count, plural, =1{Не атрымалася выдаліць 1 элемент} few{Не атрымалася выдаліць {count} элементы} other{Не атрымалася выдаліць {count} элементаў}}",
+ "@collectionDeleteFailureFeedback": {
+ "placeholders": {
+ "count": {}
+ }
+ },
+ "settingsVideoButtonsTile": "Кнопкі",
+ "@settingsVideoButtonsTile": {},
+ "settingsSubtitleThemeSample": "Гэта ўзор.",
+ "@settingsSubtitleThemeSample": {},
+ "settingsSaveSearchHistory": "Захаваць гісторыю пошуку",
+ "@settingsSaveSearchHistory": {},
+ "settingsViewerShowHistogram": "Паказаць гістаграму",
+ "@settingsViewerShowHistogram": {},
+ "settingsVideoPlaybackTile": "Прайграванне",
+ "@settingsVideoPlaybackTile": {},
+ "columnCount": "{count, plural, =1{1 слупок} few{{count} слупкі} other{{count} слупкоў}}",
+ "@columnCount": {
+ "placeholders": {
+ "count": {}
+ }
+ },
+ "timeSeconds": "{seconds, plural, =1{1 секунда} few{{seconds} секунды} other{{seconds} секунд}}",
+ "@timeSeconds": {
+ "placeholders": {
+ "seconds": {}
+ }
+ },
+ "timeDays": "{days, plural, =1{1 дзень} few{{days} дні} other{{days} дзён}}",
+ "@timeDays": {
+ "placeholders": {
+ "days": {}
+ }
+ },
+ "timeMinutes": "{minutes, plural, =1{1 хвіліна} few{{minutes} хвіліны} other{{minutes} хвілін}}",
+ "@timeMinutes": {
+ "placeholders": {
+ "minutes": {}
+ }
+ }
}
diff --git a/lib/l10n/app_de.arb b/lib/l10n/app_de.arb
index b8b4be190..4a72170e9 100644
--- a/lib/l10n/app_de.arb
+++ b/lib/l10n/app_de.arb
@@ -1350,5 +1350,9 @@
"overlayHistogramLuminance": "Leuchtdichte",
"@overlayHistogramLuminance": {},
"overlayHistogramRGB": "RGB",
- "@overlayHistogramRGB": {}
+ "@overlayHistogramRGB": {},
+ "aboutDataUsageClearCache": "Cache leeren",
+ "@aboutDataUsageClearCache": {},
+ "settingsViewerShowHistogram": "Histogramm anzeigen",
+ "@settingsViewerShowHistogram": {}
}
diff --git a/lib/l10n/app_it.arb b/lib/l10n/app_it.arb
index a9104a63b..d71aa99b5 100644
--- a/lib/l10n/app_it.arb
+++ b/lib/l10n/app_it.arb
@@ -1354,5 +1354,11 @@
"settingsViewerShowHistogram": "Mostra istogramma",
"@settingsViewerShowHistogram": {},
"overlayHistogramRGB": "RGB",
- "@overlayHistogramRGB": {}
+ "@overlayHistogramRGB": {},
+ "entryActionCast": "Cast",
+ "@entryActionCast": {},
+ "aboutDataUsageClearCache": "Pulisci Cache",
+ "@aboutDataUsageClearCache": {},
+ "castDialogTitle": "Dispositivi per Cast",
+ "@castDialogTitle": {}
}
diff --git a/lib/l10n/app_pt.arb b/lib/l10n/app_pt.arb
index 81fd67d77..0e09ed45b 100644
--- a/lib/l10n/app_pt.arb
+++ b/lib/l10n/app_pt.arb
@@ -1354,5 +1354,7 @@
"overlayHistogramRGB": "RGB",
"@overlayHistogramRGB": {},
"settingsViewerShowHistogram": "Mostrar histograma",
- "@settingsViewerShowHistogram": {}
+ "@settingsViewerShowHistogram": {},
+ "aboutDataUsageClearCache": "Limpar o cache",
+ "@aboutDataUsageClearCache": {}
}
diff --git a/lib/l10n/app_zh.arb b/lib/l10n/app_zh.arb
index 141cf4d61..36ba2b40a 100644
--- a/lib/l10n/app_zh.arb
+++ b/lib/l10n/app_zh.arb
@@ -613,7 +613,7 @@
"@drawerCollectionImages": {},
"drawerCollectionVideos": "视频",
"@drawerCollectionVideos": {},
- "drawerCollectionAnimated": "动画",
+ "drawerCollectionAnimated": "动图",
"@drawerCollectionAnimated": {},
"drawerCollectionMotionPhotos": "动态照片",
"@drawerCollectionMotionPhotos": {},
@@ -1228,5 +1228,137 @@
"overlayHistogramRGB": "RGB",
"@overlayHistogramRGB": {},
"saveCopyButtonLabel": "保存副本",
- "@saveCopyButtonLabel": {}
+ "@saveCopyButtonLabel": {},
+ "aboutDataUsageMisc": "其他",
+ "@aboutDataUsageMisc": {},
+ "vaultDialogLockModeWhenScreenOff": "屏幕关闭时锁定",
+ "@vaultDialogLockModeWhenScreenOff": {},
+ "tooManyItemsErrorDialogMessage": "用较少的项目重试。",
+ "@tooManyItemsErrorDialogMessage": {},
+ "videoResumptionModeNever": "从不",
+ "@videoResumptionModeNever": {},
+ "aboutDataUsageDatabase": "数据库",
+ "@aboutDataUsageDatabase": {},
+ "exportEntryDialogQuality": "画质",
+ "@exportEntryDialogQuality": {},
+ "placeEmpty": "没有地点",
+ "@placeEmpty": {},
+ "settingsAskEverytime": "每次询问",
+ "@settingsAskEverytime": {},
+ "settingsModificationWarningDialogMessage": "其他设置将被修改。",
+ "@settingsModificationWarningDialogMessage": {},
+ "settingsVideoGestureVerticalDragBrightnessVolume": "上下滑动屏幕调整亮度或音量",
+ "@settingsVideoGestureVerticalDragBrightnessVolume": {},
+ "videoResumptionModeAlways": "始终",
+ "@videoResumptionModeAlways": {},
+ "vaultLockTypePattern": "图案",
+ "@vaultLockTypePattern": {},
+ "albumTierVaults": "保险库",
+ "@albumTierVaults": {},
+ "settingsVideoResumptionModeTile": "恢复回放",
+ "@settingsVideoResumptionModeTile": {},
+ "vaultBinUsageDialogMessage": "有些保险库正在使用资源回收站。",
+ "@vaultBinUsageDialogMessage": {},
+ "overlayHistogramLuminance": "亮度",
+ "@overlayHistogramLuminance": {},
+ "patternDialogEnter": "输入图形",
+ "@patternDialogEnter": {},
+ "maxBrightnessAlways": "始终",
+ "@maxBrightnessAlways": {},
+ "aboutDataUsageSectionTitle": "数据使用量",
+ "@aboutDataUsageSectionTitle": {},
+ "entryActionCast": "投屏",
+ "@entryActionCast": {},
+ "vaultLockTypePin": "PIN",
+ "@vaultLockTypePin": {},
+ "editorTransformCrop": "裁剪",
+ "@editorTransformCrop": {},
+ "filterTaggedLabel": "已标记",
+ "@filterTaggedLabel": {},
+ "statePageTitle": "地区",
+ "@statePageTitle": {},
+ "settingsVideoResumptionModeDialogTitle": "恢复回放",
+ "@settingsVideoResumptionModeDialogTitle": {},
+ "settingsVideoBackgroundMode": "后台模式",
+ "@settingsVideoBackgroundMode": {},
+ "chipActionGoToPlacePage": "在地点中显示",
+ "@chipActionGoToPlacePage": {},
+ "placePageTitle": "地点",
+ "@placePageTitle": {},
+ "authenticateToUnlockVault": "验证以解锁保险库",
+ "@authenticateToUnlockVault": {},
+ "lengthUnitPercent": "百分比",
+ "@lengthUnitPercent": {},
+ "maxBrightnessNever": "从不",
+ "@maxBrightnessNever": {},
+ "aboutDataUsageCache": "缓存",
+ "@aboutDataUsageCache": {},
+ "settingsCollectionBurstPatternsNone": "无",
+ "@settingsCollectionBurstPatternsNone": {},
+ "widgetTapUpdateWidget": "更新小工具",
+ "@widgetTapUpdateWidget": {},
+ "settingsViewerShowDescription": "显示描述",
+ "@settingsViewerShowDescription": {},
+ "cropAspectRatioFree": "自由",
+ "@cropAspectRatioFree": {},
+ "newVaultWarningDialogMessage": "保险库中的项目仅供此应用使用,其他应用不可用。\n\n如果您卸载此应用或清除此应用数据,您将丢失所有这些项目。",
+ "@newVaultWarningDialogMessage": {},
+ "settingsDisablingBinWarningDialogMessage": "回收站中的项目将被永久删除。",
+ "@settingsDisablingBinWarningDialogMessage": {},
+ "statsTopStatesSectionTitle": "最多项的地区",
+ "@statsTopStatesSectionTitle": {},
+ "settingsVideoPlaybackPageTitle": "回放",
+ "@settingsVideoPlaybackPageTitle": {},
+ "filterLocatedLabel": "位于",
+ "@filterLocatedLabel": {},
+ "settingsAccessibilityShowPinchGestureAlternatives": "显示触屏手势可选方案",
+ "@settingsAccessibilityShowPinchGestureAlternatives": {},
+ "drawerPlacePage": "地点",
+ "@drawerPlacePage": {},
+ "settingsConfirmationVaultDataLoss": "显示保险库数据丢失警报",
+ "@settingsConfirmationVaultDataLoss": {},
+ "aboutDataUsageClearCache": "清理缓存",
+ "@aboutDataUsageClearCache": {},
+ "authenticateToConfigureVault": "验证以设置保险库",
+ "@authenticateToConfigureVault": {},
+ "lengthUnitPixel": "像素",
+ "@lengthUnitPixel": {},
+ "vaultDialogLockTypeLabel": "锁定类型",
+ "@vaultDialogLockTypeLabel": {},
+ "aboutDataUsageExternal": "外部存储",
+ "@aboutDataUsageExternal": {},
+ "cropAspectRatioSquare": "方形",
+ "@cropAspectRatioSquare": {},
+ "overlayHistogramNone": "无",
+ "@overlayHistogramNone": {},
+ "settingsCollectionBurstPatternsTile": "连拍模式",
+ "@settingsCollectionBurstPatternsTile": {},
+ "cropAspectRatioOriginal": "原始",
+ "@cropAspectRatioOriginal": {},
+ "configureVaultDialogTitle": "设置保险库",
+ "@configureVaultDialogTitle": {},
+ "searchStatesSectionTitle": "地区",
+ "@searchStatesSectionTitle": {},
+ "stateEmpty": "没有地区",
+ "@stateEmpty": {},
+ "aboutDataUsageData": "数据",
+ "@aboutDataUsageData": {},
+ "aboutDataUsageInternal": "内部存储",
+ "@aboutDataUsageInternal": {},
+ "castDialogTitle": "投屏设备",
+ "@castDialogTitle": {},
+ "settingsVideoEnablePip": "画中画",
+ "@settingsVideoEnablePip": {},
+ "newVaultDialogTitle": "新保险库",
+ "@newVaultDialogTitle": {},
+ "settingsVideoBackgroundModeDialogTitle": "后台模式",
+ "@settingsVideoBackgroundModeDialogTitle": {},
+ "tagPlaceholderState": "地区",
+ "@tagPlaceholderState": {},
+ "settingsViewerShowHistogram": "显示直方图",
+ "@settingsViewerShowHistogram": {},
+ "settingsVideoPlaybackTile": "回放",
+ "@settingsVideoPlaybackTile": {},
+ "exportEntryDialogWriteMetadata": "写入元数据",
+ "@exportEntryDialogWriteMetadata": {}
}
diff --git a/lib/model/app/contributors.dart b/lib/model/app/contributors.dart
index 031b6c9a3..9e3c7b812 100644
--- a/lib/model/app/contributors.dart
+++ b/lib/model/app/contributors.dart
@@ -66,10 +66,12 @@ class Contributors {
Contributor('Fqwe1', 'Fqwe1@users.noreply.hosted.weblate.org'),
Contributor('Reza Almanda', 'rezaalmanda27@gmail.com'),
Contributor('Sveinn í Felli', 'sv1@fellsnet.is'),
- // Contributor('SAMIRAH AIL', 'samiratalzahrani@gmail.com'), // Arabic
- // Contributor('Salih Ail', 'rrrfff444@gmail.com'), // Arabic
- // Contributor('nasreddineloukriz', 'nasreddineloukriz@gmail.com'), // Arabic
- // Contributor('Mohamed Zeroug', 'mzeroug19@gmail.com'), // Arabic
+ Contributor('Henning Bunk', 'henningtbunk@gmail.com'),
+ Contributor('SAMIRAH AIL', 'samiratalzahrani@gmail.com'),
+ Contributor('Salih Ail', 'rrrfff444@gmail.com'),
+ Contributor('nasreddineloukriz', 'nasreddineloukriz@gmail.com'),
+ Contributor('Mohamed Zeroug', 'mzeroug19@gmail.com'),
+ Contributor('ssantos', 'ssantos@web.de'),
// Contributor('Alvi Khan', 'aveenalvi@gmail.com'), // Bengali
// Contributor('Htet Oo Hlaing', 'htetoh2006@outlook.com'), // Burmese
// Contributor('Khant', 'khant@users.noreply.hosted.weblate.org'), // Burmese
diff --git a/lib/model/entry/extensions/multipage.dart b/lib/model/entry/extensions/multipage.dart
index 2352b27f0..e613583a6 100644
--- a/lib/model/entry/extensions/multipage.dart
+++ b/lib/model/entry/extensions/multipage.dart
@@ -3,19 +3,17 @@ import 'dart:async';
import 'package:aves/model/entry/entry.dart';
import 'package:aves/model/multipage.dart';
import 'package:aves/ref/bursts.dart';
-import 'package:aves/ref/mime_types.dart';
import 'package:aves/services/common/services.dart';
import 'package:collection/collection.dart';
extension ExtraAvesEntryMultipage on AvesEntry {
- bool get isMultiPage => (catalogMetadata?.isMultiPage ?? false) || isBurst;
+ bool get isMultiPage => isBurst || ((catalogMetadata?.isMultiPage ?? false) && (isMotionPhoto || !isHdr));
bool get isBurst => burstEntries?.isNotEmpty == true;
- // for backward compatibility
- bool get _isMotionPhotoLegacy => isMultiPage && !isBurst && mimeType == MimeTypes.jpeg;
+ bool get isMotionPhoto => catalogMetadata?.isMotionPhoto ?? false;
- bool get isMotionPhoto => (catalogMetadata?.isMotionPhoto ?? false) || _isMotionPhotoLegacy;
+ bool get isHdr => catalogMetadata?.hasHdrGainMap ?? false;
String? getBurstKey(List patterns) {
final key = BurstPatterns.getKeyForName(filenameWithoutExtension, patterns);
diff --git a/lib/model/filters/coordinate.dart b/lib/model/filters/coordinate.dart
index 4a17edb2e..57b7b4ebe 100644
--- a/lib/model/filters/coordinate.dart
+++ b/lib/model/filters/coordinate.dart
@@ -4,12 +4,10 @@ import 'package:aves/model/filters/filters.dart';
import 'package:aves/model/settings/enums/coordinate_format.dart';
import 'package:aves/model/settings/settings.dart';
import 'package:aves/theme/icons.dart';
-import 'package:aves/widgets/common/extensions/build_context.dart';
import 'package:aves_map/aves_map.dart';
import 'package:aves_model/aves_model.dart';
import 'package:flutter/widgets.dart';
import 'package:latlong2/latlong.dart';
-import 'package:provider/provider.dart';
class CoordinateFilter extends CollectionFilter {
static const type = 'coordinate';
@@ -45,24 +43,30 @@ class CoordinateFilter extends CollectionFilter {
@override
EntryFilter get positiveTest => _test;
- String _formatBounds(AppLocalizations l10n, CoordinateFormat format) {
- String s(LatLng latLng) => format.format(
- l10n,
- latLng,
- minuteSecondPadding: minuteSecondPadding,
- dmsSecondDecimals: 0,
- );
- return '${s(ne)}\n${s(sw)}';
- }
+ String _formatBounds(String Function(LatLng latLng) s) => '${s(ne)}\n${s(sw)}';
@override
bool get exclusiveProp => false;
@override
- String get universalLabel => _formatBounds(lookupAppLocalizations(AppLocalizations.supportedLocales.first), CoordinateFormat.decimal);
+ String get universalLabel {
+ return _formatBounds((latLng) => CoordinateFormat.decimal.formatWithoutDirectionality(
+ lookupAppLocalizations(AppLocalizations.supportedLocales.first),
+ latLng,
+ minuteSecondPadding: minuteSecondPadding,
+ dmsSecondDecimals: 0,
+ ));
+ }
@override
- String getLabel(BuildContext context) => _formatBounds(context.l10n, context.read().coordinateFormat);
+ String getLabel(BuildContext context) {
+ return _formatBounds((latLng) => settings.coordinateFormat.format(
+ context,
+ latLng,
+ minuteSecondPadding: minuteSecondPadding,
+ dmsSecondDecimals: 0,
+ ));
+ }
@override
Widget iconBuilder(BuildContext context, double size, {bool showGenericIcon = true}) => Icon(AIcons.geoBounds, size: size);
diff --git a/lib/model/filters/type.dart b/lib/model/filters/type.dart
index a095887dc..9b4e331e1 100644
--- a/lib/model/filters/type.dart
+++ b/lib/model/filters/type.dart
@@ -13,7 +13,8 @@ class TypeFilter extends CollectionFilter {
static const _animated = 'animated'; // subset of `image/gif` and `image/webp`
static const _geotiff = 'geotiff'; // subset of `image/tiff`
- static const _motionPhoto = 'motion_photo'; // subset of `image/jpeg`
+ static const _hdr = 'hdr'; // subset of `image/jpeg`
+ static const _motionPhoto = 'motion_photo'; // subset of images (jpeg, heic)
static const _panorama = 'panorama'; // subset of images
static const _raw = 'raw'; // specific image formats
static const _sphericalVideo = 'spherical_video'; // subset of videos
@@ -24,6 +25,7 @@ class TypeFilter extends CollectionFilter {
static final animated = TypeFilter._private(_animated);
static final geotiff = TypeFilter._private(_geotiff);
+ static final hdr = TypeFilter._private(_hdr);
static final motionPhoto = TypeFilter._private(_motionPhoto);
static final panorama = TypeFilter._private(_panorama);
static final raw = TypeFilter._private(_raw);
@@ -40,6 +42,9 @@ class TypeFilter extends CollectionFilter {
case _geotiff:
_test = (entry) => entry.isGeotiff;
_icon = AIcons.geo;
+ case _hdr:
+ _test = (entry) => entry.isHdr;
+ _icon = AIcons.hdr;
case _motionPhoto:
_test = (entry) => entry.isMotionPhoto;
_icon = AIcons.motionPhoto;
@@ -83,11 +88,12 @@ class TypeFilter extends CollectionFilter {
final l10n = context.l10n;
return switch (itemType) {
_animated => l10n.filterTypeAnimatedLabel,
+ _geotiff => l10n.filterTypeGeotiffLabel,
+ _hdr => 'HDR',
_motionPhoto => l10n.filterTypeMotionPhotoLabel,
_panorama => l10n.filterTypePanoramaLabel,
_raw => l10n.filterTypeRawLabel,
_sphericalVideo => l10n.filterTypeSphericalVideoLabel,
- _geotiff => l10n.filterTypeGeotiffLabel,
_ => itemType,
};
}
diff --git a/lib/model/metadata/catalog.dart b/lib/model/metadata/catalog.dart
index 0d389eae2..157c348aa 100644
--- a/lib/model/metadata/catalog.dart
+++ b/lib/model/metadata/catalog.dart
@@ -4,7 +4,7 @@ import 'package:flutter/foundation.dart';
class CatalogMetadata {
final int id;
final int? dateMillis;
- final bool isAnimated, isGeotiff, is360, isMultiPage, isMotionPhoto;
+ final bool isAnimated, isGeotiff, is360, isMultiPage, isMotionPhoto, hasHdrGainMap;
bool isFlipped;
int? rotationDegrees;
final String? mimeType, xmpSubjects, xmpTitle;
@@ -12,13 +12,16 @@ class CatalogMetadata {
Address? address;
int rating;
+ // less lenient than Flutter's `precisionErrorTolerance` (1e-10)
static const double _precisionErrorTolerance = 1e-9;
+
static const _isAnimatedMask = 1 << 0;
static const _isFlippedMask = 1 << 1;
static const _isGeotiffMask = 1 << 2;
static const _is360Mask = 1 << 3;
static const _isMultiPageMask = 1 << 4;
static const _isMotionPhotoMask = 1 << 5;
+ static const _hasHdrGainMapMask = 1 << 6;
CatalogMetadata({
required this.id,
@@ -30,6 +33,7 @@ class CatalogMetadata {
this.is360 = false,
this.isMultiPage = false,
this.isMotionPhoto = false,
+ this.hasHdrGainMap = false,
this.rotationDegrees,
this.xmpSubjects,
this.xmpTitle,
@@ -71,6 +75,7 @@ class CatalogMetadata {
is360: is360,
isMultiPage: isMultiPage ?? this.isMultiPage,
isMotionPhoto: isMotionPhoto,
+ hasHdrGainMap: hasHdrGainMap,
rotationDegrees: rotationDegrees ?? this.rotationDegrees,
xmpSubjects: xmpSubjects,
xmpTitle: xmpTitle,
@@ -92,6 +97,7 @@ class CatalogMetadata {
is360: flags & _is360Mask != 0,
isMultiPage: flags & _isMultiPageMask != 0,
isMotionPhoto: flags & _isMotionPhotoMask != 0,
+ hasHdrGainMap: flags & _hasHdrGainMapMask != 0,
// `rotationDegrees` should default to `sourceRotationDegrees`, not 0
rotationDegrees: map['rotationDegrees'],
xmpSubjects: map['xmpSubjects'] ?? '',
@@ -106,7 +112,7 @@ class CatalogMetadata {
'id': id,
'mimeType': mimeType,
'dateMillis': dateMillis,
- 'flags': (isAnimated ? _isAnimatedMask : 0) | (isFlipped ? _isFlippedMask : 0) | (isGeotiff ? _isGeotiffMask : 0) | (is360 ? _is360Mask : 0) | (isMultiPage ? _isMultiPageMask : 0) | (isMotionPhoto ? _isMotionPhotoMask : 0),
+ 'flags': (isAnimated ? _isAnimatedMask : 0) | (isFlipped ? _isFlippedMask : 0) | (isGeotiff ? _isGeotiffMask : 0) | (is360 ? _is360Mask : 0) | (isMultiPage ? _isMultiPageMask : 0) | (isMotionPhoto ? _isMotionPhotoMask : 0) | (hasHdrGainMap ? _hasHdrGainMapMask : 0),
'rotationDegrees': rotationDegrees,
'xmpSubjects': xmpSubjects,
'xmpTitle': xmpTitle,
diff --git a/lib/model/multipage.dart b/lib/model/multipage.dart
index 278a62e6a..286dda44d 100644
--- a/lib/model/multipage.dart
+++ b/lib/model/multipage.dart
@@ -9,6 +9,7 @@ class MultiPageInfo {
final AvesEntry mainEntry;
final List _pages;
final Map _pageEntries = {};
+ final Set _transientEntries = {};
int get pageCount => _pages.length;
@@ -16,6 +17,13 @@ class MultiPageInfo {
required this.mainEntry,
required List pages,
}) : _pages = pages {
+ if (kFlutterMemoryAllocationsEnabled) {
+ MemoryAllocations.instance.dispatchObjectCreated(
+ library: 'aves',
+ className: '$MultiPageInfo',
+ object: this,
+ );
+ }
if (_pages.isNotEmpty) {
_pages.sort();
// make sure there is a page marked as default
@@ -34,6 +42,13 @@ class MultiPageInfo {
}
}
+ void dispose() {
+ if (kFlutterMemoryAllocationsEnabled) {
+ MemoryAllocations.instance.dispatchObjectDisposed(object: this);
+ }
+ _transientEntries.forEach((entry) => entry.dispose());
+ }
+
factory MultiPageInfo.fromPageMaps(AvesEntry mainEntry, List