Merge branch 'develop'
2
.flutter
|
@ -1 +1 @@
|
||||||
Subproject commit 54e66469a933b60ddf175f858f82eaeb97e48c8d
|
Subproject commit 761747bfc538b5af34aa0d3fac380f1bc331ec49
|
21
CHANGELOG.md
|
@ -4,6 +4,27 @@ All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
## <a id="unreleased"></a>[Unreleased]
|
## <a id="unreleased"></a>[Unreleased]
|
||||||
|
|
||||||
|
## <a id="v1.11.2"></a>[v1.11.2] - 2024-06-11
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Albums / Countries / Tags: show selection in Collection
|
||||||
|
- allow shifting dates by seconds
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- opening app from launcher shows home page only when exited by back button
|
||||||
|
- Screen saver: black background, consistent with slideshow
|
||||||
|
- upgraded Flutter to stable v3.22.2
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
|
||||||
|
- support for Android KitKat (API 19)
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- crash when cataloguing large images
|
||||||
|
|
||||||
## <a id="v1.11.1"></a>[v1.11.1] - 2024-05-03
|
## <a id="v1.11.1"></a>[v1.11.1] - 2024-05-03
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
|
@ -66,9 +66,6 @@ android {
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId packageName
|
applicationId packageName
|
||||||
// minSdk constraints:
|
|
||||||
// - Flutter & other plugins: 19 (cf `flutter.minSdkVersion`)
|
|
||||||
// - google_maps_flutter v2.1.1: 20
|
|
||||||
minSdk flutter.minSdkVersion
|
minSdk flutter.minSdkVersion
|
||||||
targetSdk 34
|
targetSdk 34
|
||||||
versionCode flutterVersionCode.toInteger()
|
versionCode flutterVersionCode.toInteger()
|
||||||
|
@ -197,11 +194,11 @@ repositories {
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.8.0'
|
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.8.1'
|
||||||
|
|
||||||
implementation "androidx.appcompat:appcompat:1.6.1"
|
implementation "androidx.appcompat:appcompat:1.6.1"
|
||||||
implementation 'androidx.core:core-ktx:1.12.0'
|
implementation 'androidx.core:core-ktx:1.13.1'
|
||||||
implementation 'androidx.lifecycle:lifecycle-process:2.7.0'
|
implementation 'androidx.lifecycle:lifecycle-process:2.8.0'
|
||||||
implementation 'androidx.media:media:1.7.0'
|
implementation 'androidx.media:media:1.7.0'
|
||||||
implementation 'androidx.multidex:multidex:2.0.1'
|
implementation 'androidx.multidex:multidex:2.0.1'
|
||||||
implementation 'androidx.security:security-crypto:1.1.0-alpha06'
|
implementation 'androidx.security:security-crypto:1.1.0-alpha06'
|
||||||
|
@ -211,9 +208,9 @@ dependencies {
|
||||||
implementation 'com.commonsware.cwac:document:0.5.0'
|
implementation 'com.commonsware.cwac:document:0.5.0'
|
||||||
implementation 'com.drewnoakes:metadata-extractor:2.19.0'
|
implementation 'com.drewnoakes:metadata-extractor:2.19.0'
|
||||||
implementation "com.github.bumptech.glide:glide:$glide_version"
|
implementation "com.github.bumptech.glide:glide:$glide_version"
|
||||||
implementation 'com.google.android.material:material:1.11.0'
|
implementation 'com.google.android.material:material:1.12.0'
|
||||||
// SLF4J implementation for `mp4parser`
|
// SLF4J implementation for `mp4parser`
|
||||||
implementation 'org.slf4j:slf4j-simple:2.0.12'
|
implementation 'org.slf4j:slf4j-simple:2.0.13'
|
||||||
|
|
||||||
// forked, built by JitPack:
|
// forked, built by JitPack:
|
||||||
// - https://jitpack.io/p/deckerst/Android-TiffBitmapFactory
|
// - https://jitpack.io/p/deckerst/Android-TiffBitmapFactory
|
||||||
|
@ -229,7 +226,7 @@ dependencies {
|
||||||
|
|
||||||
testImplementation 'org.junit.jupiter:junit-jupiter-engine:5.10.2'
|
testImplementation 'org.junit.jupiter:junit-jupiter-engine:5.10.2'
|
||||||
|
|
||||||
kapt 'androidx.annotation:annotation:1.7.1'
|
kapt 'androidx.annotation:annotation:1.8.0'
|
||||||
ksp "com.github.bumptech.glide:ksp:$glide_version"
|
ksp "com.github.bumptech.glide:ksp:$glide_version"
|
||||||
|
|
||||||
compileOnly rootProject.findProject(':streams_channel')
|
compileOnly rootProject.findProject(':streams_channel')
|
||||||
|
|
|
@ -72,12 +72,10 @@
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
allow install on API 19, despite the `minSdk` declared in dependencies:
|
allow install on API 21, despite the `minSdk` declared in dependencies:
|
||||||
- the Security library is from API 21
|
|
||||||
- FFmpegKit for Flutter is from API 24 (when not LTS)
|
- FFmpegKit for Flutter is from API 24 (when not LTS)
|
||||||
- Google Maps is from API 20
|
|
||||||
-->
|
-->
|
||||||
<uses-sdk tools:overrideLibrary="androidx.security, com.arthenica.ffmpegkit.flutter, io.flutter.plugins.googlemaps" />
|
<uses-sdk tools:overrideLibrary="com.arthenica.ffmpegkit.flutter" />
|
||||||
|
|
||||||
<!-- from Android 11, we should define <queries> to make other apps visible to this app -->
|
<!-- from Android 11, we should define <queries> to make other apps visible to this app -->
|
||||||
<queries>
|
<queries>
|
||||||
|
@ -321,8 +319,8 @@
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="flutterEmbedding"
|
android:name="flutterEmbedding"
|
||||||
android:value="2" />
|
android:value="2" />
|
||||||
<!-- as of Flutter v3.19.0 (stable),
|
<!-- as of Flutter v3.22.0 (stable),
|
||||||
Impeller fails to render videos & platform views, has poor performance -->
|
Impeller fails to render videos (via `ffmpegkit`), and has random glitches -->
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="io.flutter.embedding.android.EnableImpeller"
|
android:name="io.flutter.embedding.android.EnableImpeller"
|
||||||
android:value="false" />
|
android:value="false" />
|
||||||
|
|
|
@ -161,13 +161,12 @@ class AnalysisWorker(context: Context, parameters: WorkerParameters) : Coroutine
|
||||||
applicationContext.getString(R.string.analysis_notification_action_stop),
|
applicationContext.getString(R.string.analysis_notification_action_stop),
|
||||||
WorkManager.getInstance(applicationContext).createCancelPendingIntent(id)
|
WorkManager.getInstance(applicationContext).createCancelPendingIntent(id)
|
||||||
).build()
|
).build()
|
||||||
val icon = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) R.drawable.ic_notification else R.mipmap.ic_launcher_round
|
|
||||||
val contentTitle = title ?: applicationContext.getText(R.string.analysis_notification_default_title)
|
val contentTitle = title ?: applicationContext.getText(R.string.analysis_notification_default_title)
|
||||||
val notification = NotificationCompat.Builder(applicationContext, NOTIFICATION_CHANNEL)
|
val notification = NotificationCompat.Builder(applicationContext, NOTIFICATION_CHANNEL)
|
||||||
.setContentTitle(contentTitle)
|
.setContentTitle(contentTitle)
|
||||||
.setTicker(contentTitle)
|
.setTicker(contentTitle)
|
||||||
.setContentText(message)
|
.setContentText(message)
|
||||||
.setSmallIcon(icon)
|
.setSmallIcon(R.drawable.ic_notification)
|
||||||
.setOngoing(true)
|
.setOngoing(true)
|
||||||
.setContentIntent(openAppIntent)
|
.setContentIntent(openAppIntent)
|
||||||
.addAction(stopAction)
|
.addAction(stopAction)
|
||||||
|
|
|
@ -4,8 +4,6 @@ import android.appwidget.AppWidgetManager
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import deckers.thibault.aves.model.FieldMap
|
import deckers.thibault.aves.model.FieldMap
|
||||||
import deckers.thibault.aves.utils.FlutterUtils
|
|
||||||
import deckers.thibault.aves.utils.FlutterUtils.enableSoftwareRendering
|
|
||||||
import io.flutter.embedding.engine.FlutterEngine
|
import io.flutter.embedding.engine.FlutterEngine
|
||||||
import io.flutter.plugin.common.MethodChannel
|
import io.flutter.plugin.common.MethodChannel
|
||||||
|
|
||||||
|
@ -13,9 +11,6 @@ class HomeWidgetSettingsActivity : MainActivity() {
|
||||||
private var appWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID
|
private var appWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID
|
||||||
|
|
||||||
public override fun onCreate(savedInstanceState: Bundle?) {
|
public override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
if (FlutterUtils.isSoftwareRenderingRequired()) {
|
|
||||||
intent.enableSoftwareRendering()
|
|
||||||
}
|
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
// cancel if user does not complete widget setup
|
// cancel if user does not complete widget setup
|
||||||
|
|
|
@ -17,13 +17,37 @@ import androidx.core.content.pm.ShortcutManagerCompat
|
||||||
import androidx.core.graphics.drawable.IconCompat
|
import androidx.core.graphics.drawable.IconCompat
|
||||||
import app.loup.streams_channel.StreamsChannel
|
import app.loup.streams_channel.StreamsChannel
|
||||||
import deckers.thibault.aves.channel.AvesByteSendingMethodCodec
|
import deckers.thibault.aves.channel.AvesByteSendingMethodCodec
|
||||||
import deckers.thibault.aves.channel.calls.*
|
import deckers.thibault.aves.channel.calls.AccessibilityHandler
|
||||||
|
import deckers.thibault.aves.channel.calls.AnalysisHandler
|
||||||
|
import deckers.thibault.aves.channel.calls.AppAdapterHandler
|
||||||
|
import deckers.thibault.aves.channel.calls.DebugHandler
|
||||||
|
import deckers.thibault.aves.channel.calls.DeviceHandler
|
||||||
|
import deckers.thibault.aves.channel.calls.EmbeddedDataHandler
|
||||||
|
import deckers.thibault.aves.channel.calls.GeocodingHandler
|
||||||
|
import deckers.thibault.aves.channel.calls.GlobalSearchHandler
|
||||||
|
import deckers.thibault.aves.channel.calls.HomeWidgetHandler
|
||||||
|
import deckers.thibault.aves.channel.calls.MediaEditHandler
|
||||||
|
import deckers.thibault.aves.channel.calls.MediaFetchBytesHandler
|
||||||
|
import deckers.thibault.aves.channel.calls.MediaFetchObjectHandler
|
||||||
|
import deckers.thibault.aves.channel.calls.MediaSessionHandler
|
||||||
|
import deckers.thibault.aves.channel.calls.MediaStoreHandler
|
||||||
|
import deckers.thibault.aves.channel.calls.MetadataEditHandler
|
||||||
|
import deckers.thibault.aves.channel.calls.MetadataFetchHandler
|
||||||
|
import deckers.thibault.aves.channel.calls.SecurityHandler
|
||||||
|
import deckers.thibault.aves.channel.calls.StorageHandler
|
||||||
import deckers.thibault.aves.channel.calls.window.ActivityWindowHandler
|
import deckers.thibault.aves.channel.calls.window.ActivityWindowHandler
|
||||||
import deckers.thibault.aves.channel.calls.window.WindowHandler
|
import deckers.thibault.aves.channel.calls.window.WindowHandler
|
||||||
import deckers.thibault.aves.channel.streams.*
|
import deckers.thibault.aves.channel.streams.ActivityResultStreamHandler
|
||||||
|
import deckers.thibault.aves.channel.streams.AnalysisStreamHandler
|
||||||
|
import deckers.thibault.aves.channel.streams.ErrorStreamHandler
|
||||||
|
import deckers.thibault.aves.channel.streams.ImageByteStreamHandler
|
||||||
|
import deckers.thibault.aves.channel.streams.ImageOpStreamHandler
|
||||||
|
import deckers.thibault.aves.channel.streams.IntentStreamHandler
|
||||||
|
import deckers.thibault.aves.channel.streams.MediaCommandStreamHandler
|
||||||
|
import deckers.thibault.aves.channel.streams.MediaStoreChangeStreamHandler
|
||||||
|
import deckers.thibault.aves.channel.streams.MediaStoreStreamHandler
|
||||||
|
import deckers.thibault.aves.channel.streams.SettingsChangeStreamHandler
|
||||||
import deckers.thibault.aves.model.FieldMap
|
import deckers.thibault.aves.model.FieldMap
|
||||||
import deckers.thibault.aves.utils.FlutterUtils.enableSoftwareRendering
|
|
||||||
import deckers.thibault.aves.utils.FlutterUtils.isSoftwareRenderingRequired
|
|
||||||
import deckers.thibault.aves.utils.LogUtils
|
import deckers.thibault.aves.utils.LogUtils
|
||||||
import deckers.thibault.aves.utils.getParcelableExtraCompat
|
import deckers.thibault.aves.utils.getParcelableExtraCompat
|
||||||
import io.flutter.embedding.android.FlutterFragmentActivity
|
import io.flutter.embedding.android.FlutterFragmentActivity
|
||||||
|
@ -52,13 +76,6 @@ open class MainActivity : FlutterFragmentActivity() {
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
Log.i(LOG_TAG, "onCreate intent=$intent")
|
Log.i(LOG_TAG, "onCreate intent=$intent")
|
||||||
|
|
||||||
if (isSoftwareRenderingRequired()) {
|
|
||||||
intent.enableSoftwareRendering()
|
|
||||||
// running the app from Android Studio automatically adds to the intent the `start-paused` flag
|
|
||||||
// so the IDE can connect to the app, but launching on KitKat emulators fails because of a timeout
|
|
||||||
intent.removeExtra("start-paused")
|
|
||||||
}
|
|
||||||
|
|
||||||
intent.extras?.takeUnless { it.isEmpty }?.let {
|
intent.extras?.takeUnless { it.isEmpty }?.let {
|
||||||
Log.i(LOG_TAG, "onCreate intent extras=$it")
|
Log.i(LOG_TAG, "onCreate intent extras=$it")
|
||||||
}
|
}
|
||||||
|
@ -168,12 +185,10 @@ open class MainActivity : FlutterFragmentActivity() {
|
||||||
// as of Flutter v3.0.1, the window `viewInsets` and `viewPadding`
|
// as of Flutter v3.0.1, the window `viewInsets` and `viewPadding`
|
||||||
// are incorrect on startup in some environments (e.g. API 29 emulator),
|
// are incorrect on startup in some environments (e.g. API 29 emulator),
|
||||||
// so we manually request to apply the insets to update the window metrics
|
// so we manually request to apply the insets to update the window metrics
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) {
|
|
||||||
Handler(Looper.getMainLooper()).postDelayed({
|
Handler(Looper.getMainLooper()).postDelayed({
|
||||||
window.decorView.requestApplyInsets()
|
window.decorView.requestApplyInsets()
|
||||||
}, 100)
|
}, 100)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
override fun onStop() {
|
override fun onStop() {
|
||||||
Log.i(LOG_TAG, "onStop")
|
Log.i(LOG_TAG, "onStop")
|
||||||
|
@ -270,10 +285,10 @@ open class MainActivity : FlutterFragmentActivity() {
|
||||||
open fun extractIntentData(intent: Intent?): FieldMap {
|
open fun extractIntentData(intent: Intent?): FieldMap {
|
||||||
when (val action = intent?.action) {
|
when (val action = intent?.action) {
|
||||||
Intent.ACTION_MAIN -> {
|
Intent.ACTION_MAIN -> {
|
||||||
val fields = hashMapOf<String, Any?>(
|
val fields = HashMap<String, Any?>()
|
||||||
INTENT_DATA_KEY_LAUNCHER to intent.hasCategory(Intent.CATEGORY_LAUNCHER),
|
if (intent.getBooleanExtra(EXTRA_KEY_SAFE_MODE, false)) {
|
||||||
INTENT_DATA_KEY_SAFE_MODE to intent.getBooleanExtra(EXTRA_KEY_SAFE_MODE, false),
|
fields[INTENT_DATA_KEY_SAFE_MODE] = true
|
||||||
)
|
}
|
||||||
intent.getStringExtra(EXTRA_KEY_PAGE)?.let { page ->
|
intent.getStringExtra(EXTRA_KEY_PAGE)?.let { page ->
|
||||||
val filters = extractFiltersFromIntent(intent)
|
val filters = extractFiltersFromIntent(intent)
|
||||||
fields[INTENT_DATA_KEY_PAGE] = page
|
fields[INTENT_DATA_KEY_PAGE] = page
|
||||||
|
@ -482,7 +497,6 @@ open class MainActivity : FlutterFragmentActivity() {
|
||||||
const val INTENT_DATA_KEY_ACTION = "action"
|
const val INTENT_DATA_KEY_ACTION = "action"
|
||||||
const val INTENT_DATA_KEY_ALLOW_MULTIPLE = "allowMultiple"
|
const val INTENT_DATA_KEY_ALLOW_MULTIPLE = "allowMultiple"
|
||||||
const val INTENT_DATA_KEY_FILTERS = "filters"
|
const val INTENT_DATA_KEY_FILTERS = "filters"
|
||||||
const val INTENT_DATA_KEY_LAUNCHER = "launcher"
|
|
||||||
const val INTENT_DATA_KEY_MIME_TYPE = "mimeType"
|
const val INTENT_DATA_KEY_MIME_TYPE = "mimeType"
|
||||||
const val INTENT_DATA_KEY_PAGE = "page"
|
const val INTENT_DATA_KEY_PAGE = "page"
|
||||||
const val INTENT_DATA_KEY_QUERY = "query"
|
const val INTENT_DATA_KEY_QUERY = "query"
|
||||||
|
|
|
@ -9,6 +9,7 @@ import deckers.thibault.aves.channel.calls.*
|
||||||
import deckers.thibault.aves.channel.calls.window.ServiceWindowHandler
|
import deckers.thibault.aves.channel.calls.window.ServiceWindowHandler
|
||||||
import deckers.thibault.aves.channel.calls.window.WindowHandler
|
import deckers.thibault.aves.channel.calls.window.WindowHandler
|
||||||
import deckers.thibault.aves.channel.streams.ImageByteStreamHandler
|
import deckers.thibault.aves.channel.streams.ImageByteStreamHandler
|
||||||
|
import deckers.thibault.aves.channel.streams.MediaCommandStreamHandler
|
||||||
import deckers.thibault.aves.channel.streams.MediaStoreStreamHandler
|
import deckers.thibault.aves.channel.streams.MediaStoreStreamHandler
|
||||||
import deckers.thibault.aves.utils.LogUtils
|
import deckers.thibault.aves.utils.LogUtils
|
||||||
import io.flutter.FlutterInjector
|
import io.flutter.FlutterInjector
|
||||||
|
@ -18,12 +19,14 @@ import io.flutter.embedding.android.FlutterView
|
||||||
import io.flutter.embedding.engine.FlutterEngine
|
import io.flutter.embedding.engine.FlutterEngine
|
||||||
import io.flutter.embedding.engine.dart.DartExecutor.DartEntrypoint
|
import io.flutter.embedding.engine.dart.DartExecutor.DartEntrypoint
|
||||||
import io.flutter.embedding.engine.plugins.util.GeneratedPluginRegister
|
import io.flutter.embedding.engine.plugins.util.GeneratedPluginRegister
|
||||||
|
import io.flutter.plugin.common.EventChannel
|
||||||
import io.flutter.plugin.common.MethodChannel
|
import io.flutter.plugin.common.MethodChannel
|
||||||
|
|
||||||
// for FlutterView-level integration, cf https://docs.flutter.dev/development/add-to-app/android/add-flutter-view
|
// for FlutterView-level integration, cf https://docs.flutter.dev/development/add-to-app/android/add-flutter-view
|
||||||
class ScreenSaverService : DreamService() {
|
class ScreenSaverService : DreamService() {
|
||||||
private var flutterEngine: FlutterEngine? = null
|
private var flutterEngine: FlutterEngine? = null
|
||||||
private var flutterView: FlutterView? = null
|
private var flutterView: FlutterView? = null
|
||||||
|
private lateinit var mediaSessionHandler: MediaSessionHandler
|
||||||
|
|
||||||
override fun onAttachedToWindow() {
|
override fun onAttachedToWindow() {
|
||||||
Log.i(LOG_TAG, "onAttachedToWindow")
|
Log.i(LOG_TAG, "onAttachedToWindow")
|
||||||
|
@ -77,6 +80,7 @@ class ScreenSaverService : DreamService() {
|
||||||
|
|
||||||
private fun release() {
|
private fun release() {
|
||||||
destroyView()
|
destroyView()
|
||||||
|
mediaSessionHandler.dispose()
|
||||||
flutterEngine = null
|
flutterEngine = null
|
||||||
flutterView = null
|
flutterView = null
|
||||||
}
|
}
|
||||||
|
@ -96,12 +100,19 @@ class ScreenSaverService : DreamService() {
|
||||||
private fun initChannels() {
|
private fun initChannels() {
|
||||||
val messenger = flutterEngine!!.dartExecutor
|
val messenger = flutterEngine!!.dartExecutor
|
||||||
|
|
||||||
|
// notification: platform -> dart
|
||||||
|
val mediaCommandStreamHandler = MediaCommandStreamHandler().apply {
|
||||||
|
EventChannel(messenger, MediaCommandStreamHandler.CHANNEL).setStreamHandler(this)
|
||||||
|
}
|
||||||
|
|
||||||
// dart -> platform -> dart
|
// dart -> platform -> dart
|
||||||
// - need Context
|
// - need Context
|
||||||
|
mediaSessionHandler = MediaSessionHandler(this, mediaCommandStreamHandler)
|
||||||
MethodChannel(messenger, DeviceHandler.CHANNEL).setMethodCallHandler(DeviceHandler(this))
|
MethodChannel(messenger, DeviceHandler.CHANNEL).setMethodCallHandler(DeviceHandler(this))
|
||||||
MethodChannel(messenger, EmbeddedDataHandler.CHANNEL).setMethodCallHandler(EmbeddedDataHandler(this))
|
MethodChannel(messenger, EmbeddedDataHandler.CHANNEL).setMethodCallHandler(EmbeddedDataHandler(this))
|
||||||
MethodChannel(messenger, MediaFetchBytesHandler.CHANNEL, AvesByteSendingMethodCodec.INSTANCE).setMethodCallHandler(MediaFetchBytesHandler(this))
|
MethodChannel(messenger, MediaFetchBytesHandler.CHANNEL, AvesByteSendingMethodCodec.INSTANCE).setMethodCallHandler(MediaFetchBytesHandler(this))
|
||||||
MethodChannel(messenger, MediaFetchObjectHandler.CHANNEL).setMethodCallHandler(MediaFetchObjectHandler(this))
|
MethodChannel(messenger, MediaFetchObjectHandler.CHANNEL).setMethodCallHandler(MediaFetchObjectHandler(this))
|
||||||
|
MethodChannel(messenger, MediaSessionHandler.CHANNEL).setMethodCallHandler(mediaSessionHandler)
|
||||||
MethodChannel(messenger, MediaStoreHandler.CHANNEL).setMethodCallHandler(MediaStoreHandler(this))
|
MethodChannel(messenger, MediaStoreHandler.CHANNEL).setMethodCallHandler(MediaStoreHandler(this))
|
||||||
MethodChannel(messenger, MetadataFetchHandler.CHANNEL).setMethodCallHandler(MetadataFetchHandler(this))
|
MethodChannel(messenger, MetadataFetchHandler.CHANNEL).setMethodCallHandler(MetadataFetchHandler(this))
|
||||||
MethodChannel(messenger, StorageHandler.CHANNEL).setMethodCallHandler(StorageHandler(this))
|
MethodChannel(messenger, StorageHandler.CHANNEL).setMethodCallHandler(StorageHandler(this))
|
||||||
|
|
|
@ -34,7 +34,7 @@ class SearchSuggestionsProvider : ContentProvider() {
|
||||||
val columns = arrayOf(
|
val columns = arrayOf(
|
||||||
SearchManager.SUGGEST_COLUMN_INTENT_DATA,
|
SearchManager.SUGGEST_COLUMN_INTENT_DATA,
|
||||||
SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA,
|
SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA,
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) SearchManager.SUGGEST_COLUMN_CONTENT_TYPE else "mimeType",
|
SearchManager.SUGGEST_COLUMN_CONTENT_TYPE,
|
||||||
SearchManager.SUGGEST_COLUMN_TEXT_1,
|
SearchManager.SUGGEST_COLUMN_TEXT_1,
|
||||||
SearchManager.SUGGEST_COLUMN_TEXT_2,
|
SearchManager.SUGGEST_COLUMN_TEXT_2,
|
||||||
SearchManager.SUGGEST_COLUMN_ICON_1,
|
SearchManager.SUGGEST_COLUMN_ICON_1,
|
||||||
|
|
|
@ -2,21 +2,26 @@ package deckers.thibault.aves
|
||||||
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Build
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import app.loup.streams_channel.StreamsChannel
|
import app.loup.streams_channel.StreamsChannel
|
||||||
import deckers.thibault.aves.channel.AvesByteSendingMethodCodec
|
import deckers.thibault.aves.channel.AvesByteSendingMethodCodec
|
||||||
import deckers.thibault.aves.channel.calls.*
|
import deckers.thibault.aves.channel.calls.AccessibilityHandler
|
||||||
|
import deckers.thibault.aves.channel.calls.DeviceHandler
|
||||||
|
import deckers.thibault.aves.channel.calls.EmbeddedDataHandler
|
||||||
|
import deckers.thibault.aves.channel.calls.MediaFetchBytesHandler
|
||||||
|
import deckers.thibault.aves.channel.calls.MediaFetchObjectHandler
|
||||||
|
import deckers.thibault.aves.channel.calls.MediaSessionHandler
|
||||||
|
import deckers.thibault.aves.channel.calls.MetadataFetchHandler
|
||||||
|
import deckers.thibault.aves.channel.calls.StorageHandler
|
||||||
|
import deckers.thibault.aves.channel.calls.WallpaperHandler
|
||||||
import deckers.thibault.aves.channel.calls.window.ActivityWindowHandler
|
import deckers.thibault.aves.channel.calls.window.ActivityWindowHandler
|
||||||
import deckers.thibault.aves.channel.calls.window.WindowHandler
|
import deckers.thibault.aves.channel.calls.window.WindowHandler
|
||||||
import deckers.thibault.aves.channel.streams.ImageByteStreamHandler
|
import deckers.thibault.aves.channel.streams.ImageByteStreamHandler
|
||||||
import deckers.thibault.aves.channel.streams.MediaCommandStreamHandler
|
import deckers.thibault.aves.channel.streams.MediaCommandStreamHandler
|
||||||
import deckers.thibault.aves.model.FieldMap
|
import deckers.thibault.aves.model.FieldMap
|
||||||
import deckers.thibault.aves.utils.FlutterUtils
|
|
||||||
import deckers.thibault.aves.utils.FlutterUtils.enableSoftwareRendering
|
|
||||||
import deckers.thibault.aves.utils.LogUtils
|
import deckers.thibault.aves.utils.LogUtils
|
||||||
import deckers.thibault.aves.utils.getParcelableExtraCompat
|
import deckers.thibault.aves.utils.getParcelableExtraCompat
|
||||||
import io.flutter.embedding.android.FlutterFragmentActivity
|
import io.flutter.embedding.android.FlutterFragmentActivity
|
||||||
|
@ -30,9 +35,6 @@ class WallpaperActivity : FlutterFragmentActivity() {
|
||||||
private lateinit var mediaSessionHandler: MediaSessionHandler
|
private lateinit var mediaSessionHandler: MediaSessionHandler
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
if (FlutterUtils.isSoftwareRenderingRequired()) {
|
|
||||||
intent.enableSoftwareRendering()
|
|
||||||
}
|
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
Log.i(LOG_TAG, "onCreate intent=$intent")
|
Log.i(LOG_TAG, "onCreate intent=$intent")
|
||||||
|
@ -83,12 +85,10 @@ class WallpaperActivity : FlutterFragmentActivity() {
|
||||||
// as of Flutter v3.0.1, the window `viewInsets` and `viewPadding`
|
// as of Flutter v3.0.1, the window `viewInsets` and `viewPadding`
|
||||||
// are incorrect on startup in some environments (e.g. API 29 emulator),
|
// are incorrect on startup in some environments (e.g. API 29 emulator),
|
||||||
// so we manually request to apply the insets to update the window metrics
|
// so we manually request to apply the insets to update the window metrics
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) {
|
|
||||||
Handler(Looper.getMainLooper()).postDelayed({
|
Handler(Looper.getMainLooper()).postDelayed({
|
||||||
window.decorView.requestApplyInsets()
|
window.decorView.requestApplyInsets()
|
||||||
}, 100)
|
}, 100)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDestroy() {
|
override fun onDestroy() {
|
||||||
mediaSessionHandler.dispose()
|
mediaSessionHandler.dispose()
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package deckers.thibault.aves.channel.calls
|
package deckers.thibault.aves.channel.calls
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import androidx.core.app.ComponentActivity
|
import androidx.activity.ComponentActivity
|
||||||
import androidx.work.ExistingWorkPolicy
|
import androidx.work.ExistingWorkPolicy
|
||||||
import androidx.work.OneTimeWorkRequest
|
import androidx.work.OneTimeWorkRequest
|
||||||
import androidx.work.OneTimeWorkRequestBuilder
|
import androidx.work.OneTimeWorkRequestBuilder
|
||||||
|
|
|
@ -79,15 +79,9 @@ class DebugHandler(private val context: Context) : MethodCallHandler {
|
||||||
"obbDir" to context.obbDir,
|
"obbDir" to context.obbDir,
|
||||||
"externalCacheDir" to context.externalCacheDir,
|
"externalCacheDir" to context.externalCacheDir,
|
||||||
"externalFilesDir" to context.getExternalFilesDir(null),
|
"externalFilesDir" to context.getExternalFilesDir(null),
|
||||||
).apply {
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
|
||||||
putAll(
|
|
||||||
hashMapOf(
|
|
||||||
"codeCacheDir" to context.codeCacheDir,
|
"codeCacheDir" to context.codeCacheDir,
|
||||||
"noBackupFilesDir" to context.noBackupFilesDir,
|
"noBackupFilesDir" to context.noBackupFilesDir,
|
||||||
)
|
).apply {
|
||||||
)
|
|
||||||
}
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||||
put("dataDir", context.dataDir)
|
put("dataDir", context.dataDir)
|
||||||
}
|
}
|
||||||
|
@ -108,8 +102,6 @@ class DebugHandler(private val context: Context) : MethodCallHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getCodecs(@Suppress("unused_parameter") call: MethodCall, result: MethodChannel.Result) {
|
private fun getCodecs(@Suppress("unused_parameter") call: MethodCall, result: MethodChannel.Result) {
|
||||||
val codecs = ArrayList<FieldMap>()
|
|
||||||
|
|
||||||
fun getFields(info: MediaCodecInfo): FieldMap {
|
fun getFields(info: MediaCodecInfo): FieldMap {
|
||||||
val fields: FieldMap = hashMapOf(
|
val fields: FieldMap = hashMapOf(
|
||||||
"name" to info.name,
|
"name" to info.name,
|
||||||
|
@ -126,18 +118,7 @@ class DebugHandler(private val context: Context) : MethodCallHandler {
|
||||||
return fields
|
return fields
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
val codecs = MediaCodecList(MediaCodecList.REGULAR_CODECS).codecInfos.map(::getFields).toList()
|
||||||
codecs.addAll(MediaCodecList(MediaCodecList.REGULAR_CODECS).codecInfos.map(::getFields))
|
|
||||||
} else {
|
|
||||||
@Suppress("deprecation")
|
|
||||||
val count = MediaCodecList.getCodecCount()
|
|
||||||
for (i in 0 until count) {
|
|
||||||
@Suppress("deprecation")
|
|
||||||
val info = MediaCodecList.getCodecInfoAt(i)
|
|
||||||
codecs.add(getFields(info))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
result.success(codecs)
|
result.success(codecs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -294,7 +275,7 @@ class DebugHandler(private val context: Context) : MethodCallHandler {
|
||||||
if (canReadWithMetadataExtractor(mimeType)) {
|
if (canReadWithMetadataExtractor(mimeType)) {
|
||||||
try {
|
try {
|
||||||
Metadata.openSafeInputStream(context, uri, mimeType, sizeBytes)?.use { input ->
|
Metadata.openSafeInputStream(context, uri, mimeType, sizeBytes)?.use { input ->
|
||||||
val metadata = Helper.safeRead(input)
|
val metadata = Helper.safeRead(input, sizeBytes)
|
||||||
metadataMap["mimeType"] = metadata.getDirectoriesOfType(FileTypeDirectory::class.java).joinToString { dir ->
|
metadataMap["mimeType"] = metadata.getDirectoriesOfType(FileTypeDirectory::class.java).joinToString { dir ->
|
||||||
if (dir.containsTag(FileTypeDirectory.TAG_DETECTED_FILE_MIME_TYPE)) {
|
if (dir.containsTag(FileTypeDirectory.TAG_DETECTED_FILE_MIME_TYPE)) {
|
||||||
dir.getString(FileTypeDirectory.TAG_DETECTED_FILE_MIME_TYPE)
|
dir.getString(FileTypeDirectory.TAG_DETECTED_FILE_MIME_TYPE)
|
||||||
|
|
|
@ -69,16 +69,11 @@ class DeviceHandler(private val context: Context) : MethodCallHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getLocales(@Suppress("unused_parameter") call: MethodCall, result: MethodChannel.Result) {
|
private fun getLocales(@Suppress("unused_parameter") call: MethodCall, result: MethodChannel.Result) {
|
||||||
fun toMap(locale: Locale): FieldMap {
|
fun toMap(locale: Locale): FieldMap = hashMapOf(
|
||||||
val fields: HashMap<String, Any?> = hashMapOf(
|
|
||||||
"language" to locale.language,
|
"language" to locale.language,
|
||||||
"country" to locale.country,
|
"country" to locale.country,
|
||||||
|
"script" to locale.script,
|
||||||
)
|
)
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
|
||||||
fields["script"] = locale.script
|
|
||||||
}
|
|
||||||
return fields
|
|
||||||
}
|
|
||||||
|
|
||||||
val locales = ArrayList<FieldMap>()
|
val locales = ArrayList<FieldMap>()
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||||
|
@ -106,11 +101,7 @@ class DeviceHandler(private val context: Context) : MethodCallHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isSystemFilePickerEnabled(@Suppress("unused_parameter") call: MethodCall, result: MethodChannel.Result) {
|
private fun isSystemFilePickerEnabled(@Suppress("unused_parameter") call: MethodCall, result: MethodChannel.Result) {
|
||||||
val enabled = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
val enabled = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE).resolveActivity(context.packageManager) != null
|
||||||
Intent(Intent.ACTION_OPEN_DOCUMENT_TREE).resolveActivity(context.packageManager) != null
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
result.success(enabled)
|
result.success(enabled)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -102,7 +102,7 @@ class EmbeddedDataHandler(private val context: Context) : MethodCallHandler {
|
||||||
if (canReadWithMetadataExtractor(mimeType)) {
|
if (canReadWithMetadataExtractor(mimeType)) {
|
||||||
try {
|
try {
|
||||||
Metadata.openSafeInputStream(context, uri, mimeType, sizeBytes)?.use { input ->
|
Metadata.openSafeInputStream(context, uri, mimeType, sizeBytes)?.use { input ->
|
||||||
val metadata = Helper.safeRead(input)
|
val metadata = Helper.safeRead(input, sizeBytes)
|
||||||
// data can be large and stored in "Extended XMP",
|
// data can be large and stored in "Extended XMP",
|
||||||
// which is returned as a second XMP directory
|
// which is returned as a second XMP directory
|
||||||
val xmpDirs = metadata.getDirectoriesOfType(XmpDirectory::class.java)
|
val xmpDirs = metadata.getDirectoriesOfType(XmpDirectory::class.java)
|
||||||
|
@ -272,7 +272,7 @@ class EmbeddedDataHandler(private val context: Context) : MethodCallHandler {
|
||||||
if (canReadWithMetadataExtractor(mimeType)) {
|
if (canReadWithMetadataExtractor(mimeType)) {
|
||||||
try {
|
try {
|
||||||
Metadata.openSafeInputStream(context, uri, mimeType, sizeBytes)?.use { input ->
|
Metadata.openSafeInputStream(context, uri, mimeType, sizeBytes)?.use { input ->
|
||||||
val metadata = Helper.safeRead(input)
|
val metadata = Helper.safeRead(input, sizeBytes)
|
||||||
// data can be large and stored in "Extended XMP",
|
// data can be large and stored in "Extended XMP",
|
||||||
// which is returned as a second XMP directory
|
// which is returned as a second XMP directory
|
||||||
val xmpDirs = metadata.getDirectoriesOfType(XmpDirectory::class.java)
|
val xmpDirs = metadata.getDirectoriesOfType(XmpDirectory::class.java)
|
||||||
|
|
|
@ -74,7 +74,7 @@ class MetadataEditHandler(private val contextWrapper: ContextWrapper) : MethodCa
|
||||||
|
|
||||||
private fun editDate(call: MethodCall, result: MethodChannel.Result) {
|
private fun editDate(call: MethodCall, result: MethodChannel.Result) {
|
||||||
val dateMillis = call.argument<Number>("dateMillis")?.toLong()
|
val dateMillis = call.argument<Number>("dateMillis")?.toLong()
|
||||||
val shiftMinutes = call.argument<Number>("shiftMinutes")?.toLong()
|
val shiftSeconds = call.argument<Number>("shiftSeconds")?.toLong()
|
||||||
val fields = call.argument<List<String>>("fields")
|
val fields = call.argument<List<String>>("fields")
|
||||||
val entryMap = call.argument<FieldMap>("entry")
|
val entryMap = call.argument<FieldMap>("entry")
|
||||||
if (entryMap == null || fields == null) {
|
if (entryMap == null || fields == null) {
|
||||||
|
@ -97,7 +97,7 @@ class MetadataEditHandler(private val contextWrapper: ContextWrapper) : MethodCa
|
||||||
}
|
}
|
||||||
|
|
||||||
val callback = MetadataOpCallback("editDate", entryMap, result)
|
val callback = MetadataOpCallback("editDate", entryMap, result)
|
||||||
provider.editDate(contextWrapper, path, uri, mimeType, dateMillis, shiftMinutes, fields, callback)
|
provider.editDate(contextWrapper, path, uri, mimeType, dateMillis, shiftSeconds, fields, callback)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun editMetadata(call: MethodCall, result: MethodChannel.Result) {
|
private fun editMetadata(call: MethodCall, result: MethodChannel.Result) {
|
||||||
|
|
|
@ -229,7 +229,7 @@ class MetadataFetchHandler(private val context: Context) : MethodCallHandler {
|
||||||
if (canReadWithMetadataExtractor(mimeType)) {
|
if (canReadWithMetadataExtractor(mimeType)) {
|
||||||
try {
|
try {
|
||||||
Metadata.openSafeInputStream(context, uri, mimeType, sizeBytes)?.use { input ->
|
Metadata.openSafeInputStream(context, uri, mimeType, sizeBytes)?.use { input ->
|
||||||
val metadata = Helper.safeRead(input)
|
val metadata = Helper.safeRead(input, sizeBytes)
|
||||||
foundExif = metadata.directories.any { it is ExifDirectoryBase && it.tagCount > 0 }
|
foundExif = metadata.directories.any { it is ExifDirectoryBase && it.tagCount > 0 }
|
||||||
foundMp4Uuid = metadata.directories.any { it is Mp4UuidBoxDirectory && it.tagCount > 0 }
|
foundMp4Uuid = metadata.directories.any { it is Mp4UuidBoxDirectory && it.tagCount > 0 }
|
||||||
|
|
||||||
|
@ -296,7 +296,7 @@ class MetadataFetchHandler(private val context: Context) : MethodCallHandler {
|
||||||
byGeoTiff[false]?.map { exifTagMapper(it) }?.let { dirMap.putAll(it) }
|
byGeoTiff[false]?.map { exifTagMapper(it) }?.let { dirMap.putAll(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
mimeType == MimeTypes.DNG -> {
|
mimeType == MimeTypes.DNG || mimeType == MimeTypes.DNG_ADOBE -> {
|
||||||
// split DNG tags in their own directory
|
// split DNG tags in their own directory
|
||||||
val dngDirMap = metadataMap[DIR_DNG] ?: HashMap()
|
val dngDirMap = metadataMap[DIR_DNG] ?: HashMap()
|
||||||
metadataMap[DIR_DNG] = dngDirMap
|
metadataMap[DIR_DNG] = dngDirMap
|
||||||
|
@ -599,7 +599,7 @@ class MetadataFetchHandler(private val context: Context) : MethodCallHandler {
|
||||||
if (canReadWithMetadataExtractor(mimeType)) {
|
if (canReadWithMetadataExtractor(mimeType)) {
|
||||||
try {
|
try {
|
||||||
Metadata.openSafeInputStream(context, uri, mimeType, sizeBytes)?.use { input ->
|
Metadata.openSafeInputStream(context, uri, mimeType, sizeBytes)?.use { input ->
|
||||||
val metadata = Helper.safeRead(input)
|
val metadata = Helper.safeRead(input, sizeBytes)
|
||||||
foundExif = metadata.directories.any { it is ExifDirectoryBase && it.tagCount > 0 }
|
foundExif = metadata.directories.any { it is ExifDirectoryBase && it.tagCount > 0 }
|
||||||
foundMp4Uuid = metadata.directories.any { it is Mp4UuidBoxDirectory && it.tagCount > 0 }
|
foundMp4Uuid = metadata.directories.any { it is Mp4UuidBoxDirectory && it.tagCount > 0 }
|
||||||
|
|
||||||
|
@ -803,7 +803,7 @@ class MetadataFetchHandler(private val context: Context) : MethodCallHandler {
|
||||||
}
|
}
|
||||||
StorageUtils.openInputStream(context, uri)?.let { input ->
|
StorageUtils.openInputStream(context, uri)?.let { input ->
|
||||||
input.skip(dataOffset)
|
input.skip(dataOffset)
|
||||||
val pageMetadata = Helper.safeRead(input)
|
val pageMetadata = Helper.safeRead(input, sizeBytes)
|
||||||
if (pageMetadata.getDirectoriesOfType(XmpDirectory::class.java).any { it.xmpMeta.hasHdrGainMap() }) {
|
if (pageMetadata.getDirectoriesOfType(XmpDirectory::class.java).any { it.xmpMeta.hasHdrGainMap() }) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -897,7 +897,7 @@ class MetadataFetchHandler(private val context: Context) : MethodCallHandler {
|
||||||
if (canReadWithMetadataExtractor(mimeType)) {
|
if (canReadWithMetadataExtractor(mimeType)) {
|
||||||
try {
|
try {
|
||||||
Metadata.openSafeInputStream(context, uri, mimeType, sizeBytes)?.use { input ->
|
Metadata.openSafeInputStream(context, uri, mimeType, sizeBytes)?.use { input ->
|
||||||
val metadata = Helper.safeRead(input)
|
val metadata = Helper.safeRead(input, sizeBytes)
|
||||||
for (dir in metadata.getDirectoriesOfType(ExifSubIFDDirectory::class.java)) {
|
for (dir in metadata.getDirectoriesOfType(ExifSubIFDDirectory::class.java)) {
|
||||||
foundExif = true
|
foundExif = true
|
||||||
if (fields.contains(KEY_APERTURE)) {
|
if (fields.contains(KEY_APERTURE)) {
|
||||||
|
@ -1007,7 +1007,7 @@ class MetadataFetchHandler(private val context: Context) : MethodCallHandler {
|
||||||
if (canReadWithMetadataExtractor(mimeType)) {
|
if (canReadWithMetadataExtractor(mimeType)) {
|
||||||
try {
|
try {
|
||||||
Metadata.openSafeInputStream(context, uri, mimeType, sizeBytes)?.use { input ->
|
Metadata.openSafeInputStream(context, uri, mimeType, sizeBytes)?.use { input ->
|
||||||
val metadata = Helper.safeRead(input)
|
val metadata = Helper.safeRead(input, sizeBytes)
|
||||||
val fields = HashMap<Int, Any?>()
|
val fields = HashMap<Int, Any?>()
|
||||||
for (dir in metadata.getDirectoriesOfType(ExifIFD0Directory::class.java)) {
|
for (dir in metadata.getDirectoriesOfType(ExifIFD0Directory::class.java)) {
|
||||||
if (dir.containsGeoTiffTags()) {
|
if (dir.containsGeoTiffTags()) {
|
||||||
|
@ -1084,7 +1084,7 @@ class MetadataFetchHandler(private val context: Context) : MethodCallHandler {
|
||||||
if (canReadWithMetadataExtractor(mimeType) && !isLargeMp4(mimeType, sizeBytes)) {
|
if (canReadWithMetadataExtractor(mimeType) && !isLargeMp4(mimeType, sizeBytes)) {
|
||||||
try {
|
try {
|
||||||
Metadata.openSafeInputStream(context, uri, mimeType, sizeBytes)?.use { input ->
|
Metadata.openSafeInputStream(context, uri, mimeType, sizeBytes)?.use { input ->
|
||||||
val metadata = Helper.safeRead(input)
|
val metadata = Helper.safeRead(input, sizeBytes)
|
||||||
metadata.getDirectoriesOfType(XmpDirectory::class.java).map { it.xmpMeta }.forEach {
|
metadata.getDirectoriesOfType(XmpDirectory::class.java).map { it.xmpMeta }.forEach {
|
||||||
processXmp(it, allowMultiple = true)
|
processXmp(it, allowMultiple = true)
|
||||||
}
|
}
|
||||||
|
@ -1166,7 +1166,7 @@ class MetadataFetchHandler(private val context: Context) : MethodCallHandler {
|
||||||
if (canReadWithMetadataExtractor(mimeType) && !isLargeMp4(mimeType, sizeBytes)) {
|
if (canReadWithMetadataExtractor(mimeType) && !isLargeMp4(mimeType, sizeBytes)) {
|
||||||
try {
|
try {
|
||||||
Metadata.openSafeInputStream(context, uri, mimeType, sizeBytes)?.use { input ->
|
Metadata.openSafeInputStream(context, uri, mimeType, sizeBytes)?.use { input ->
|
||||||
val metadata = Helper.safeRead(input)
|
val metadata = Helper.safeRead(input, sizeBytes)
|
||||||
metadata.getDirectoriesOfType(XmpDirectory::class.java).map { it.xmpMeta }.forEach {
|
metadata.getDirectoriesOfType(XmpDirectory::class.java).map { it.xmpMeta }.forEach {
|
||||||
processXmp(it, allowMultiple = true)
|
processXmp(it, allowMultiple = true)
|
||||||
}
|
}
|
||||||
|
@ -1244,7 +1244,7 @@ class MetadataFetchHandler(private val context: Context) : MethodCallHandler {
|
||||||
if (canReadWithMetadataExtractor(mimeType)) {
|
if (canReadWithMetadataExtractor(mimeType)) {
|
||||||
try {
|
try {
|
||||||
Metadata.openSafeInputStream(context, uri, mimeType, sizeBytes)?.use { input ->
|
Metadata.openSafeInputStream(context, uri, mimeType, sizeBytes)?.use { input ->
|
||||||
val metadata = Helper.safeRead(input)
|
val metadata = Helper.safeRead(input, sizeBytes)
|
||||||
val tag = when (field) {
|
val tag = when (field) {
|
||||||
ExifInterface.TAG_DATETIME -> ExifIFD0Directory.TAG_DATETIME
|
ExifInterface.TAG_DATETIME -> ExifIFD0Directory.TAG_DATETIME
|
||||||
ExifInterface.TAG_DATETIME_DIGITIZED -> ExifSubIFDDirectory.TAG_DATETIME_DIGITIZED
|
ExifInterface.TAG_DATETIME_DIGITIZED -> ExifSubIFDDirectory.TAG_DATETIME_DIGITIZED
|
||||||
|
@ -1345,7 +1345,7 @@ class MetadataFetchHandler(private val context: Context) : MethodCallHandler {
|
||||||
if (canReadWithMetadataExtractor(mimeType)) {
|
if (canReadWithMetadataExtractor(mimeType)) {
|
||||||
try {
|
try {
|
||||||
Metadata.openSafeInputStream(context, uri, mimeType, sizeBytes)?.use { input ->
|
Metadata.openSafeInputStream(context, uri, mimeType, sizeBytes)?.use { input ->
|
||||||
val metadata = Helper.safeRead(input)
|
val metadata = Helper.safeRead(input, sizeBytes)
|
||||||
for (dir in metadata.getDirectoriesOfType(ExifDirectoryBase::class.java)) {
|
for (dir in metadata.getDirectoriesOfType(ExifDirectoryBase::class.java)) {
|
||||||
foundExif = true
|
foundExif = true
|
||||||
val allTags = ExifInterfaceHelper.allTags
|
val allTags = ExifInterfaceHelper.allTags
|
||||||
|
|
|
@ -47,9 +47,7 @@ class StorageHandler(private val context: Context) : MethodCallHandler {
|
||||||
|
|
||||||
private fun getDataUsage(@Suppress("unused_parameter") call: MethodCall, result: MethodChannel.Result) {
|
private fun getDataUsage(@Suppress("unused_parameter") call: MethodCall, result: MethodChannel.Result) {
|
||||||
var internalCache = getFolderSize(context.cacheDir)
|
var internalCache = getFolderSize(context.cacheDir)
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
|
||||||
internalCache += getFolderSize(context.codeCacheDir)
|
internalCache += getFolderSize(context.codeCacheDir)
|
||||||
}
|
|
||||||
val externalCache = context.externalCacheDirs.map(::getFolderSize).sum()
|
val externalCache = context.externalCacheDirs.map(::getFolderSize).sum()
|
||||||
|
|
||||||
val dataDir = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) context.dataDir else File(context.applicationInfo.dataDir)
|
val dataDir = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) context.dataDir else File(context.applicationInfo.dataDir)
|
||||||
|
@ -105,12 +103,7 @@ class StorageHandler(private val context: Context) : MethodCallHandler {
|
||||||
val volumeFile = File(volumePath)
|
val volumeFile = File(volumePath)
|
||||||
try {
|
try {
|
||||||
val isPrimary = volumePath == primaryVolumePath
|
val isPrimary = volumePath == primaryVolumePath
|
||||||
val isRemovable = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
val isRemovable = Environment.isExternalStorageRemovable(volumeFile)
|
||||||
Environment.isExternalStorageRemovable(volumeFile)
|
|
||||||
} else {
|
|
||||||
// random guess
|
|
||||||
!isPrimary
|
|
||||||
}
|
|
||||||
volumes.add(
|
volumes.add(
|
||||||
hashMapOf(
|
hashMapOf(
|
||||||
"path" to volumePath,
|
"path" to volumePath,
|
||||||
|
@ -202,11 +195,6 @@ class StorageHandler(private val context: Context) : MethodCallHandler {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
|
|
||||||
result.error("revokeDirectoryAccess-unsupported", "volume access is not allowed before Android Lollipop", null)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
val success = PermissionManager.revokeDirectoryAccess(context, path)
|
val success = PermissionManager.revokeDirectoryAccess(context, path)
|
||||||
result.success(success)
|
result.success(success)
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,10 +14,12 @@ import deckers.thibault.aves.decoder.MultiPageImage
|
||||||
import deckers.thibault.aves.utils.BitmapRegionDecoderCompat
|
import deckers.thibault.aves.utils.BitmapRegionDecoderCompat
|
||||||
import deckers.thibault.aves.utils.BitmapUtils.ARGB_8888_BYTE_SIZE
|
import deckers.thibault.aves.utils.BitmapUtils.ARGB_8888_BYTE_SIZE
|
||||||
import deckers.thibault.aves.utils.BitmapUtils.getBytes
|
import deckers.thibault.aves.utils.BitmapUtils.getBytes
|
||||||
|
import deckers.thibault.aves.utils.MathUtils
|
||||||
import deckers.thibault.aves.utils.MemoryUtils
|
import deckers.thibault.aves.utils.MemoryUtils
|
||||||
import deckers.thibault.aves.utils.MimeTypes
|
import deckers.thibault.aves.utils.MimeTypes
|
||||||
import deckers.thibault.aves.utils.StorageUtils
|
import deckers.thibault.aves.utils.StorageUtils
|
||||||
import io.flutter.plugin.common.MethodChannel
|
import io.flutter.plugin.common.MethodChannel
|
||||||
|
import kotlin.math.max
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
// As of Android 14 (API 34), `BitmapRegionDecoder` documentation states
|
// As of Android 14 (API 34), `BitmapRegionDecoder` documentation states
|
||||||
|
@ -60,10 +62,6 @@ class RegionFetcher internal constructor(
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val options = BitmapFactory.Options().apply {
|
|
||||||
inSampleSize = sampleSize
|
|
||||||
}
|
|
||||||
|
|
||||||
var currentDecoderRef = lastDecoderRef
|
var currentDecoderRef = lastDecoderRef
|
||||||
if (currentDecoderRef != null && currentDecoderRef.uri != uri) {
|
if (currentDecoderRef != null && currentDecoderRef.uri != uri) {
|
||||||
currentDecoderRef = null
|
currentDecoderRef = null
|
||||||
|
@ -85,27 +83,35 @@ class RegionFetcher internal constructor(
|
||||||
|
|
||||||
// with raw images, the known image size may not match the decoded image size
|
// with raw images, the known image size may not match the decoded image size
|
||||||
// so we scale the requested region accordingly
|
// so we scale the requested region accordingly
|
||||||
val effectiveRect = if (imageWidth != decoder.width || imageHeight != decoder.height) {
|
var effectiveRect = regionRect
|
||||||
|
var effectiveSampleSize = sampleSize
|
||||||
|
|
||||||
|
if (imageWidth != decoder.width || imageHeight != decoder.height) {
|
||||||
val xf = decoder.width.toDouble() / imageWidth
|
val xf = decoder.width.toDouble() / imageWidth
|
||||||
val yf = decoder.height.toDouble() / imageHeight
|
val yf = decoder.height.toDouble() / imageHeight
|
||||||
Rect(
|
effectiveRect = Rect(
|
||||||
(regionRect.left * xf).roundToInt(),
|
(regionRect.left * xf).roundToInt(),
|
||||||
(regionRect.top * yf).roundToInt(),
|
(regionRect.top * yf).roundToInt(),
|
||||||
(regionRect.right * xf).roundToInt(),
|
(regionRect.right * xf).roundToInt(),
|
||||||
(regionRect.bottom * yf).roundToInt(),
|
(regionRect.bottom * yf).roundToInt(),
|
||||||
)
|
)
|
||||||
} else {
|
val factor = MathUtils.highestPowerOf2((1 / max(xf, yf)).roundToInt())
|
||||||
regionRect
|
if (factor > 1) {
|
||||||
|
effectiveSampleSize = max(1, effectiveSampleSize / factor)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// use `Long` as rect size could be unexpectedly large and go beyond `Int` max
|
// use `Long` as rect size could be unexpectedly large and go beyond `Int` max
|
||||||
val targetBitmapSizeBytes: Long = ARGB_8888_BYTE_SIZE.toLong() * effectiveRect.width() * effectiveRect.height() / sampleSize
|
val targetBitmapSizeBytes: Long = ARGB_8888_BYTE_SIZE.toLong() * effectiveRect.width() * effectiveRect.height() / effectiveSampleSize
|
||||||
if (!MemoryUtils.canAllocate(targetBitmapSizeBytes)) {
|
if (!MemoryUtils.canAllocate(targetBitmapSizeBytes)) {
|
||||||
// decoding a region that large would yield an OOM when creating the bitmap
|
// decoding a region that large would yield an OOM when creating the bitmap
|
||||||
result.error("fetch-large-region", "Region too large for uri=$uri regionRect=$regionRect", null)
|
result.error("fetch-large-region", "Region too large for uri=$uri regionRect=$regionRect", null)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val options = BitmapFactory.Options().apply {
|
||||||
|
inSampleSize = effectiveSampleSize
|
||||||
|
}
|
||||||
val bitmap = decoder.decodeRegion(effectiveRect, options)
|
val bitmap = decoder.decodeRegion(effectiveRect, options)
|
||||||
if (bitmap != null) {
|
if (bitmap != null) {
|
||||||
result.success(bitmap.getBytes(MimeTypes.canHaveAlpha(mimeType), recycle = true))
|
result.success(bitmap.getBytes(MimeTypes.canHaveAlpha(mimeType), recycle = true))
|
||||||
|
|
|
@ -61,11 +61,6 @@ class ActivityResultStreamHandler(private val activity: Activity, arguments: Any
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
|
|
||||||
error("requestDirectoryAccess-unsupported", "directory access is not allowed before Android Lollipop", null)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
PermissionManager.requestDirectoryAccess(activity, ensureTrailingSeparator(path), {
|
PermissionManager.requestDirectoryAccess(activity, ensureTrailingSeparator(path), {
|
||||||
success(true)
|
success(true)
|
||||||
endOfStream()
|
endOfStream()
|
||||||
|
|
|
@ -4,14 +4,18 @@ import android.util.Log
|
||||||
import androidx.exifinterface.media.ExifInterface
|
import androidx.exifinterface.media.ExifInterface
|
||||||
import com.drew.lang.Rational
|
import com.drew.lang.Rational
|
||||||
import com.drew.metadata.Directory
|
import com.drew.metadata.Directory
|
||||||
import com.drew.metadata.exif.*
|
import com.drew.metadata.exif.ExifDirectoryBase
|
||||||
|
import com.drew.metadata.exif.ExifIFD0Directory
|
||||||
|
import com.drew.metadata.exif.ExifThumbnailDirectory
|
||||||
|
import com.drew.metadata.exif.GpsDirectory
|
||||||
|
import com.drew.metadata.exif.PanasonicRawIFD0Directory
|
||||||
import com.drew.metadata.exif.makernotes.OlympusCameraSettingsMakernoteDirectory
|
import com.drew.metadata.exif.makernotes.OlympusCameraSettingsMakernoteDirectory
|
||||||
import com.drew.metadata.exif.makernotes.OlympusImageProcessingMakernoteDirectory
|
import com.drew.metadata.exif.makernotes.OlympusImageProcessingMakernoteDirectory
|
||||||
import com.drew.metadata.exif.makernotes.OlympusMakernoteDirectory
|
import com.drew.metadata.exif.makernotes.OlympusMakernoteDirectory
|
||||||
import deckers.thibault.aves.utils.LogUtils
|
import deckers.thibault.aves.utils.LogUtils
|
||||||
import java.text.ParseException
|
import java.text.ParseException
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.*
|
import java.util.Locale
|
||||||
import kotlin.math.abs
|
import kotlin.math.abs
|
||||||
import kotlin.math.floor
|
import kotlin.math.floor
|
||||||
import kotlin.math.roundToLong
|
import kotlin.math.roundToLong
|
||||||
|
@ -22,7 +26,7 @@ object ExifInterfaceHelper {
|
||||||
val GPS_DATE_FORMAT = SimpleDateFormat("yyyy:MM:dd", Locale.ROOT)
|
val GPS_DATE_FORMAT = SimpleDateFormat("yyyy:MM:dd", Locale.ROOT)
|
||||||
val GPS_TIME_FORMAT = SimpleDateFormat("HH:mm:ss", Locale.ROOT)
|
val GPS_TIME_FORMAT = SimpleDateFormat("HH:mm:ss", Locale.ROOT)
|
||||||
|
|
||||||
private const val precisionErrorTolerance = 1e-10
|
private const val PRECISION_ERROR_TOLERANCE = 1e-10
|
||||||
|
|
||||||
// ExifInterface always states it has the following attributes
|
// ExifInterface always states it has the following attributes
|
||||||
// and returns "0" instead of "null" when they are actually missing
|
// and returns "0" instead of "null" when they are actually missing
|
||||||
|
@ -220,7 +224,7 @@ object ExifInterfaceHelper {
|
||||||
// initialize metadata-extractor directories that we will fill
|
// initialize metadata-extractor directories that we will fill
|
||||||
// by tags converted from the ExifInterface attributes
|
// by tags converted from the ExifInterface attributes
|
||||||
// so that we can rely on metadata-extractor descriptions
|
// so that we can rely on metadata-extractor descriptions
|
||||||
val dirs = DirType.values().associateWith { it.createDirectory() }
|
val dirs = DirType.entries.associateWith { it.createDirectory() }
|
||||||
|
|
||||||
// exclude Exif directory when it only includes image size
|
// exclude Exif directory when it only includes image size
|
||||||
val isUselessExif = fun(it: Map<String, String>): Boolean {
|
val isUselessExif = fun(it: Map<String, String>): Boolean {
|
||||||
|
@ -308,7 +312,7 @@ object ExifInterfaceHelper {
|
||||||
val numerator = 1L
|
val numerator = 1L
|
||||||
val f = numerator / d
|
val f = numerator / d
|
||||||
val denominator = f.roundToLong()
|
val denominator = f.roundToLong()
|
||||||
if (abs(f - denominator) < precisionErrorTolerance) {
|
if (abs(f - denominator) < PRECISION_ERROR_TOLERANCE) {
|
||||||
return Rational(numerator, denominator)
|
return Rational(numerator, denominator)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -120,7 +120,7 @@ object Metadata {
|
||||||
return date.time + parseSubSecond(subSecond)
|
return date.time + parseSubSecond(subSecond)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Opening large PSD/TIFF files yields an OOM (both with `metadata-extractor` v2.15.0 and `ExifInterface` v1.3.1),
|
// Opening some large files yields an OOM (both with `metadata-extractor` v2.15.0 and `ExifInterface` v1.3.1),
|
||||||
// so we define an arbitrary threshold to avoid a crash on launch.
|
// so we define an arbitrary threshold to avoid a crash on launch.
|
||||||
// It is not clear whether it is because of the file itself or its metadata.
|
// It is not clear whether it is because of the file itself or its metadata.
|
||||||
private const val FILE_SIZE_MAX = 100 * (1 shl 20) // MB
|
private const val FILE_SIZE_MAX = 100 * (1 shl 20) // MB
|
||||||
|
@ -134,14 +134,8 @@ object Metadata {
|
||||||
private val previewFiles = HashMap<Uri, File>()
|
private val previewFiles = HashMap<Uri, File>()
|
||||||
|
|
||||||
private fun getSafeUri(context: Context, uri: Uri, mimeType: String, sizeBytes: Long?): Uri {
|
private fun getSafeUri(context: Context, uri: Uri, mimeType: String, sizeBytes: Long?): Uri {
|
||||||
return when (mimeType) {
|
|
||||||
// formats known to yield OOM for large files
|
// formats known to yield OOM for large files
|
||||||
MimeTypes.HEIC,
|
return if ((MimeTypes.isImage(mimeType) || mimeType == MimeTypes.MP4)) {
|
||||||
MimeTypes.HEIF,
|
|
||||||
MimeTypes.MP4,
|
|
||||||
MimeTypes.PSD_VND,
|
|
||||||
MimeTypes.PSD_X,
|
|
||||||
MimeTypes.TIFF -> {
|
|
||||||
if (isDangerouslyLarge(sizeBytes)) {
|
if (isDangerouslyLarge(sizeBytes)) {
|
||||||
// make a preview from the beginning of the file,
|
// make a preview from the beginning of the file,
|
||||||
// hoping the metadata is accessible in the copied chunk
|
// hoping the metadata is accessible in the copied chunk
|
||||||
|
@ -155,9 +149,9 @@ object Metadata {
|
||||||
// small enough to be safe as it is
|
// small enough to be safe as it is
|
||||||
uri
|
uri
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
// *probably* safe
|
// *probably* safe
|
||||||
else -> uri
|
uri
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -97,7 +97,7 @@ object MultiPage {
|
||||||
if (canReadWithMetadataExtractor(mimeType)) {
|
if (canReadWithMetadataExtractor(mimeType)) {
|
||||||
try {
|
try {
|
||||||
Metadata.openSafeInputStream(context, uri, mimeType, sizeBytes)?.use { input ->
|
Metadata.openSafeInputStream(context, uri, mimeType, sizeBytes)?.use { input ->
|
||||||
val metadata = Helper.safeRead(input)
|
val metadata = Helper.safeRead(input, sizeBytes)
|
||||||
foundExif = metadata.directories.any { it is ExifDirectoryBase && it.tagCount > 0 }
|
foundExif = metadata.directories.any { it is ExifDirectoryBase && it.tagCount > 0 }
|
||||||
for (dir in metadata.getDirectoriesOfType(ExifIFD0Directory::class.java)) {
|
for (dir in metadata.getDirectoriesOfType(ExifIFD0Directory::class.java)) {
|
||||||
dir.getSafeInt(ExifDirectoryBase.TAG_ORIENTATION) {
|
dir.getSafeInt(ExifDirectoryBase.TAG_ORIENTATION) {
|
||||||
|
@ -168,7 +168,7 @@ object MultiPage {
|
||||||
val mimeType = MimeTypes.JPEG
|
val mimeType = MimeTypes.JPEG
|
||||||
try {
|
try {
|
||||||
Metadata.openSafeInputStream(context, uri, mimeType, sizeBytes)?.use { input ->
|
Metadata.openSafeInputStream(context, uri, mimeType, sizeBytes)?.use { input ->
|
||||||
val metadata = Helper.safeRead(input)
|
val metadata = Helper.safeRead(input, sizeBytes)
|
||||||
return metadata.getDirectoriesOfType(MpEntryDirectory::class.java).map { it.entry }
|
return metadata.getDirectoriesOfType(MpEntryDirectory::class.java).map { it.entry }
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
|
@ -332,7 +332,7 @@ object MultiPage {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Metadata.openSafeInputStream(context, uri, mimeType, sizeBytes)?.use { input ->
|
Metadata.openSafeInputStream(context, uri, mimeType, sizeBytes)?.use { input ->
|
||||||
val metadata = Helper.safeRead(input)
|
val metadata = Helper.safeRead(input, sizeBytes)
|
||||||
foundXmp = metadata.directories.any { it is XmpDirectory && it.tagCount > 0 }
|
foundXmp = metadata.directories.any { it is XmpDirectory && it.tagCount > 0 }
|
||||||
metadata.getDirectoriesOfType(XmpDirectory::class.java).map { it.xmpMeta }.forEach(::processXmp)
|
metadata.getDirectoriesOfType(XmpDirectory::class.java).map { it.xmpMeta }.forEach(::processXmp)
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@ import deckers.thibault.aves.metadata.GeoTiffKeys
|
||||||
import deckers.thibault.aves.metadata.Metadata
|
import deckers.thibault.aves.metadata.Metadata
|
||||||
import deckers.thibault.aves.metadata.metadataextractor.mpf.MpfReader
|
import deckers.thibault.aves.metadata.metadataextractor.mpf.MpfReader
|
||||||
import deckers.thibault.aves.utils.LogUtils
|
import deckers.thibault.aves.utils.LogUtils
|
||||||
|
import deckers.thibault.aves.utils.MemoryUtils
|
||||||
import java.io.BufferedInputStream
|
import java.io.BufferedInputStream
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
|
@ -59,19 +60,21 @@ object Helper {
|
||||||
// e.g. "exif [...] 134 [...] 4578696600004949[...]"
|
// e.g. "exif [...] 134 [...] 4578696600004949[...]"
|
||||||
private val PNG_RAW_PROFILE_PATTERN = Regex("^\\n(.*?)\\n\\s*(\\d+)\\n(.*)", RegexOption.DOT_MATCHES_ALL)
|
private val PNG_RAW_PROFILE_PATTERN = Regex("^\\n(.*?)\\n\\s*(\\d+)\\n(.*)", RegexOption.DOT_MATCHES_ALL)
|
||||||
|
|
||||||
// providing the stream length is risky, as it may crash if it is incorrect
|
|
||||||
private const val safeReadStreamLength = -1L
|
|
||||||
|
|
||||||
fun readMimeType(input: InputStream): String? {
|
fun readMimeType(input: InputStream): String? {
|
||||||
val bufferedInputStream = if (input is BufferedInputStream) input else BufferedInputStream(input)
|
val bufferedInputStream = if (input is BufferedInputStream) input else BufferedInputStream(input)
|
||||||
return FileTypeDetector.detectFileType(bufferedInputStream).mimeType
|
return FileTypeDetector.detectFileType(bufferedInputStream).mimeType
|
||||||
}
|
}
|
||||||
|
|
||||||
@Throws(IOException::class, ImageProcessingException::class)
|
@Throws(IOException::class, ImageProcessingException::class)
|
||||||
fun safeRead(input: InputStream): com.drew.metadata.Metadata {
|
fun safeRead(input: InputStream, @Suppress("unused_parameter") sizeBytes: Long?): com.drew.metadata.Metadata {
|
||||||
val inputStream = if (input is BufferedInputStream) input else BufferedInputStream(input)
|
val inputStream = if (input is BufferedInputStream) input else BufferedInputStream(input)
|
||||||
val fileType = FileTypeDetector.detectFileType(inputStream)
|
val fileType = FileTypeDetector.detectFileType(inputStream)
|
||||||
|
|
||||||
|
// Providing the stream length is risky, as it may crash if it is incorrect.
|
||||||
|
// Not providing the stream length is also risky, as it may lead to OOM
|
||||||
|
// when `RandomAccessStreamReader` reads the entire stream to validate offsets.
|
||||||
|
val undefinedStreamLength = -1L
|
||||||
|
|
||||||
val metadata = when (fileType) {
|
val metadata = when (fileType) {
|
||||||
FileType.Jpeg -> safeReadJpeg(inputStream)
|
FileType.Jpeg -> safeReadJpeg(inputStream)
|
||||||
FileType.Mp4 -> safeReadMp4(inputStream)
|
FileType.Mp4 -> safeReadMp4(inputStream)
|
||||||
|
@ -82,9 +85,9 @@ object Helper {
|
||||||
FileType.Cr2,
|
FileType.Cr2,
|
||||||
FileType.Nef,
|
FileType.Nef,
|
||||||
FileType.Orf,
|
FileType.Orf,
|
||||||
FileType.Rw2 -> safeReadTiff(inputStream)
|
FileType.Rw2 -> safeReadTiff(inputStream, undefinedStreamLength)
|
||||||
|
|
||||||
else -> ImageMetadataReader.readMetadata(inputStream, safeReadStreamLength, fileType)
|
else -> ImageMetadataReader.readMetadata(inputStream, undefinedStreamLength, fileType)
|
||||||
}
|
}
|
||||||
|
|
||||||
metadata.addDirectory(FileTypeDirectory(fileType))
|
metadata.addDirectory(FileTypeDirectory(fileType))
|
||||||
|
@ -115,8 +118,8 @@ object Helper {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Throws(IOException::class, TiffProcessingException::class)
|
@Throws(IOException::class, TiffProcessingException::class)
|
||||||
fun safeReadTiff(input: InputStream): com.drew.metadata.Metadata {
|
fun safeReadTiff(input: InputStream, streamLength: Long): com.drew.metadata.Metadata {
|
||||||
val reader = RandomAccessStreamReader(input, RandomAccessStreamReader.DEFAULT_CHUNK_LENGTH, safeReadStreamLength)
|
val reader = RandomAccessStreamReader(input, RandomAccessStreamReader.DEFAULT_CHUNK_LENGTH, streamLength)
|
||||||
val metadata = com.drew.metadata.Metadata()
|
val metadata = com.drew.metadata.Metadata()
|
||||||
val handler = SafeExifTiffHandler(metadata, null, 0)
|
val handler = SafeExifTiffHandler(metadata, null, 0)
|
||||||
TiffReader().processTiff(reader, handler, 0)
|
TiffReader().processTiff(reader, handler, 0)
|
||||||
|
@ -294,9 +297,7 @@ object Helper {
|
||||||
if (!modelTiePoints && !modelTransformation) return false
|
if (!modelTiePoints && !modelTransformation) return false
|
||||||
|
|
||||||
val modelPixelScale = this.containsTag(ExifGeoTiffTags.TAG_MODEL_PIXEL_SCALE)
|
val modelPixelScale = this.containsTag(ExifGeoTiffTags.TAG_MODEL_PIXEL_SCALE)
|
||||||
if ((modelTransformation && modelPixelScale) || (modelPixelScale && !modelTiePoints)) return false
|
return !((modelTransformation && modelPixelScale) || (modelPixelScale && !modelTiePoints))
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO TLAD use `GeoTiffDirectory` from the Java version of `metadata-extractor` when available
|
// TODO TLAD use `GeoTiffDirectory` from the Java version of `metadata-extractor` when available
|
||||||
|
|
|
@ -31,6 +31,7 @@ import deckers.thibault.aves.utils.LogUtils
|
||||||
import java.io.ByteArrayInputStream
|
import java.io.ByteArrayInputStream
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
|
import java.util.Locale
|
||||||
import java.util.zip.InflaterInputStream
|
import java.util.zip.InflaterInputStream
|
||||||
import java.util.zip.ZipException
|
import java.util.zip.ZipException
|
||||||
|
|
||||||
|
@ -42,7 +43,7 @@ object SafePngMetadataReader {
|
||||||
private val LOG_TAG = LogUtils.createTag<SafePngMetadataReader>()
|
private val LOG_TAG = LogUtils.createTag<SafePngMetadataReader>()
|
||||||
|
|
||||||
// arbitrary size to detect chunks that may yield an OOM
|
// arbitrary size to detect chunks that may yield an OOM
|
||||||
private const val chunkSizeDangerThreshold = SafeXmpReader.SEGMENT_TYPE_SIZE_DANGER_THRESHOLD
|
private const val CHUNK_SIZE_DANGER_THRESHOLD = SafeXmpReader.SEGMENT_TYPE_SIZE_DANGER_THRESHOLD
|
||||||
|
|
||||||
private val latin1Encoding = Charsets.ISO_8859_1
|
private val latin1Encoding = Charsets.ISO_8859_1
|
||||||
private val utf8Encoding = Charsets.UTF_8
|
private val utf8Encoding = Charsets.UTF_8
|
||||||
|
@ -85,7 +86,7 @@ object SafePngMetadataReader {
|
||||||
val bytes = chunk.bytes
|
val bytes = chunk.bytes
|
||||||
|
|
||||||
// TLAD insert start
|
// TLAD insert start
|
||||||
if (bytes.size > chunkSizeDangerThreshold) {
|
if (bytes.size > CHUNK_SIZE_DANGER_THRESHOLD) {
|
||||||
Log.w(LOG_TAG, "PNG chunk $chunkType is too large, with a size of ${bytes.size} B")
|
Log.w(LOG_TAG, "PNG chunk $chunkType is too large, with a size of ${bytes.size} B")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -290,11 +291,12 @@ object SafePngMetadataReader {
|
||||||
val second = reader.uInt8.toInt()
|
val second = reader.uInt8.toInt()
|
||||||
val directory = PngDirectory(PngChunkType.tIME)
|
val directory = PngDirectory(PngChunkType.tIME)
|
||||||
if (DateUtil.isValidDate(year, month - 1, day) && DateUtil.isValidTime(hour, minute, second)) {
|
if (DateUtil.isValidDate(year, month - 1, day) && DateUtil.isValidTime(hour, minute, second)) {
|
||||||
val dateString = String.format("%04d:%02d:%02d %02d:%02d:%02d", year, month, day, hour, minute, second)
|
val dateString = String.format(Locale.ROOT, "%04d:%02d:%02d %02d:%02d:%02d", year, month, day, hour, minute, second)
|
||||||
directory.setString(PngDirectory.TAG_LAST_MODIFICATION_TIME, dateString)
|
directory.setString(PngDirectory.TAG_LAST_MODIFICATION_TIME, dateString)
|
||||||
} else {
|
} else {
|
||||||
directory.addError(
|
directory.addError(
|
||||||
String.format(
|
String.format(
|
||||||
|
Locale.ROOT,
|
||||||
"PNG tIME data describes an invalid date/time: year=%d month=%d day=%d hour=%d minute=%d second=%d",
|
"PNG tIME data describes an invalid date/time: year=%d month=%d day=%d hour=%d minute=%d second=%d",
|
||||||
year, month, day, hour, minute, second
|
year, month, day, hour, minute, second
|
||||||
)
|
)
|
||||||
|
|
|
@ -16,6 +16,7 @@ import com.drew.metadata.xmp.XmpDirectory
|
||||||
import com.drew.metadata.xmp.XmpReader
|
import com.drew.metadata.xmp.XmpReader
|
||||||
import deckers.thibault.aves.utils.LogUtils
|
import deckers.thibault.aves.utils.LogUtils
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
|
import java.util.Locale
|
||||||
|
|
||||||
class SafeXmpReader : XmpReader() {
|
class SafeXmpReader : XmpReader() {
|
||||||
// adapted from `XmpReader` to detect and skip large extended XMP
|
// adapted from `XmpReader` to detect and skip large extended XMP
|
||||||
|
@ -133,7 +134,7 @@ class SafeXmpReader : XmpReader() {
|
||||||
System.arraycopy(segmentBytes, totalOffset, extendedXMPBuffer, chunkOffset, segmentLength - totalOffset)
|
System.arraycopy(segmentBytes, totalOffset, extendedXMPBuffer, chunkOffset, segmentLength - totalOffset)
|
||||||
} else {
|
} else {
|
||||||
val directory = XmpDirectory()
|
val directory = XmpDirectory()
|
||||||
directory.addError(String.format("Inconsistent length for the Extended XMP buffer: %d instead of %d", fullLength, extendedXMPBuffer.size))
|
directory.addError(String.format(Locale.ROOT, "Inconsistent length for the Extended XMP buffer: %d instead of %d", fullLength, extendedXMPBuffer.size))
|
||||||
metadata.addDirectory(directory)
|
metadata.addDirectory(directory)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,8 +16,6 @@ class MpfDirectory : Directory() {
|
||||||
return _tagNameMap
|
return _tagNameMap
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getNumberOfImages() = getInt(TAG_NUMBER_OF_IMAGES)
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val TAG_MPF_VERSION = 0xb000
|
const val TAG_MPF_VERSION = 0xb000
|
||||||
const val TAG_NUMBER_OF_IMAGES = 0xb001
|
const val TAG_NUMBER_OF_IMAGES = 0xb001
|
||||||
|
|
|
@ -15,7 +15,7 @@ class AvesEntry(map: FieldMap) {
|
||||||
val trashed = map["trashed"] as Boolean
|
val trashed = map["trashed"] as Boolean
|
||||||
val trashPath = map["trashPath"] as String?
|
val trashPath = map["trashPath"] as String?
|
||||||
|
|
||||||
val isRotated: Boolean
|
private val isRotated: Boolean
|
||||||
get() = rotationDegrees % 180 == 90
|
get() = rotationDegrees % 180 == 90
|
||||||
|
|
||||||
val displayWidth: Int
|
val displayWidth: Int
|
||||||
|
|
|
@ -163,7 +163,7 @@ class SourceEntry {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Metadata.openSafeInputStream(context, uri, sourceMimeType, sizeBytes)?.use { input ->
|
Metadata.openSafeInputStream(context, uri, sourceMimeType, sizeBytes)?.use { input ->
|
||||||
val metadata = Helper.safeRead(input)
|
val metadata = Helper.safeRead(input, sizeBytes)
|
||||||
|
|
||||||
// do not switch on specific MIME types, as the reported MIME type could be wrong
|
// do not switch on specific MIME types, as the reported MIME type could be wrong
|
||||||
// (e.g. PNG registered as JPG)
|
// (e.g. PNG registered as JPG)
|
||||||
|
|
|
@ -1026,7 +1026,7 @@ abstract class ImageProvider {
|
||||||
uri: Uri,
|
uri: Uri,
|
||||||
mimeType: String,
|
mimeType: String,
|
||||||
dateMillis: Long?,
|
dateMillis: Long?,
|
||||||
shiftMinutes: Long?,
|
shiftSeconds: Long?,
|
||||||
fields: List<String>,
|
fields: List<String>,
|
||||||
callback: ImageOpCallback,
|
callback: ImageOpCallback,
|
||||||
) {
|
) {
|
||||||
|
@ -1057,9 +1057,9 @@ abstract class ImageProvider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
shiftMinutes != null -> {
|
shiftSeconds != null -> {
|
||||||
// shift
|
// shift
|
||||||
val shiftMillis = shiftMinutes * 60000
|
val shiftMillis = shiftSeconds * 1000
|
||||||
listOf(
|
listOf(
|
||||||
ExifInterface.TAG_DATETIME,
|
ExifInterface.TAG_DATETIME,
|
||||||
ExifInterface.TAG_DATETIME_ORIGINAL,
|
ExifInterface.TAG_DATETIME_ORIGINAL,
|
||||||
|
|
|
@ -56,13 +56,7 @@ fun Geocoder.getFromLocationCompat(
|
||||||
onError: (errorCode: String, errorMessage: String?, errorDetails: Any?) -> Unit,
|
onError: (errorCode: String, errorMessage: String?, errorDetails: Any?) -> Unit,
|
||||||
) {
|
) {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||||
getFromLocation(latitude, longitude, maxResults, object : Geocoder.GeocodeListener {
|
Compat33.geocoderGetFromLocation(this, latitude, longitude, maxResults, processAddresses, onError)
|
||||||
override fun onGeocode(addresses: List<Address?>) = processAddresses(addresses.filterNotNull())
|
|
||||||
|
|
||||||
override fun onError(errorMessage: String?) {
|
|
||||||
onError("getAddress-asyncerror", "failed to get address", errorMessage)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
@Suppress("deprecation")
|
@Suppress("deprecation")
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
package deckers.thibault.aves.utils
|
||||||
|
|
||||||
|
import android.location.Address
|
||||||
|
import android.location.Geocoder
|
||||||
|
import android.os.Build
|
||||||
|
import androidx.annotation.RequiresApi
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compatibility layer in a separate object to avoid class loading issues on older Android versions.
|
||||||
|
* e.g. `ClassNotFoundException` for `android.location.Geocoder$GeocodeListener`
|
||||||
|
*/
|
||||||
|
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
|
||||||
|
object Compat33 {
|
||||||
|
fun geocoderGetFromLocation(
|
||||||
|
geocoder: Geocoder,
|
||||||
|
latitude: Double,
|
||||||
|
longitude: Double,
|
||||||
|
maxResults: Int,
|
||||||
|
processAddresses: (addresses: List<Address>) -> Unit,
|
||||||
|
onError: (errorCode: String, errorMessage: String?, errorDetails: Any?) -> Unit,
|
||||||
|
) {
|
||||||
|
geocoder.getFromLocation(latitude, longitude, maxResults, object : Geocoder.GeocodeListener {
|
||||||
|
override fun onGeocode(addresses: List<Address?>) = processAddresses(addresses.filterNotNull())
|
||||||
|
|
||||||
|
override fun onError(errorMessage: String?) {
|
||||||
|
onError("getAddress-asyncerror", "failed to get address", errorMessage)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,8 +1,6 @@
|
||||||
package deckers.thibault.aves.utils
|
package deckers.thibault.aves.utils
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
|
||||||
import android.os.Build
|
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
@ -71,29 +69,4 @@ object FlutterUtils {
|
||||||
r.run()
|
r.run()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Intent.enableSoftwareRendering() {
|
|
||||||
putExtra("enable-software-rendering", true)
|
|
||||||
Log.i(LOG_TAG, "Enable software rendering")
|
|
||||||
}
|
|
||||||
|
|
||||||
fun isSoftwareRenderingRequired() = Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT && isEmulator
|
|
||||||
|
|
||||||
private val isEmulator: Boolean
|
|
||||||
get() = (Build.BRAND.startsWith("generic") && Build.DEVICE.startsWith("generic")
|
|
||||||
|| Build.FINGERPRINT.startsWith("generic")
|
|
||||||
|| Build.FINGERPRINT.startsWith("unknown")
|
|
||||||
|| Build.HARDWARE.contains("goldfish")
|
|
||||||
|| Build.HARDWARE.contains("ranchu")
|
|
||||||
|| Build.MODEL.contains("google_sdk")
|
|
||||||
|| Build.MODEL.contains("Emulator")
|
|
||||||
|| Build.MODEL.contains("Android SDK built for x86")
|
|
||||||
|| Build.MANUFACTURER.contains("Genymotion")
|
|
||||||
|| Build.PRODUCT.contains("sdk_google")
|
|
||||||
|| Build.PRODUCT.contains("google_sdk")
|
|
||||||
|| Build.PRODUCT.contains("sdk")
|
|
||||||
|| Build.PRODUCT.contains("sdk_x86")
|
|
||||||
|| Build.PRODUCT.contains("vbox86p")
|
|
||||||
|| Build.PRODUCT.contains("emulator")
|
|
||||||
|| Build.PRODUCT.contains("simulator"))
|
|
||||||
}
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
package deckers.thibault.aves.utils
|
||||||
|
|
||||||
|
import kotlin.math.log2
|
||||||
|
import kotlin.math.pow
|
||||||
|
|
||||||
|
object MathUtils {
|
||||||
|
fun highestPowerOf2(x: Int): Int = highestPowerOf2(x.toDouble())
|
||||||
|
fun highestPowerOf2(x: Double): Int = if (x < 1) 0 else 2.toDouble().pow(log2(x).toInt()).toInt()
|
||||||
|
}
|
|
@ -28,7 +28,8 @@ object MimeTypes {
|
||||||
private const val CR2 = "image/x-canon-cr2"
|
private const val CR2 = "image/x-canon-cr2"
|
||||||
private const val CRW = "image/x-canon-crw"
|
private const val CRW = "image/x-canon-crw"
|
||||||
private const val DCR = "image/x-kodak-dcr"
|
private const val DCR = "image/x-kodak-dcr"
|
||||||
const val DNG = "image/x-adobe-dng"
|
const val DNG = "image/dng"
|
||||||
|
const val DNG_ADOBE = "image/x-adobe-dng"
|
||||||
private const val ERF = "image/x-epson-erf"
|
private const val ERF = "image/x-epson-erf"
|
||||||
private const val K25 = "image/x-kodak-k25"
|
private const val K25 = "image/x-kodak-k25"
|
||||||
private const val KDC = "image/x-kodak-kdc"
|
private const val KDC = "image/x-kodak-kdc"
|
||||||
|
@ -71,7 +72,7 @@ object MimeTypes {
|
||||||
|
|
||||||
fun isRaw(mimeType: String): Boolean {
|
fun isRaw(mimeType: String): Boolean {
|
||||||
return when (mimeType) {
|
return when (mimeType) {
|
||||||
ARW, CR2, CRW, DCR, DNG, ERF, K25, KDC, MRW, NEF, NRW, ORF, PEF, RAF, RAW, RW2, SR2, SRF, SRW, X3F -> true
|
ARW, CR2, CRW, DCR, DNG, DNG_ADOBE, ERF, K25, KDC, MRW, NEF, NRW, ORF, PEF, RAF, RAW, RW2, SR2, SRF, SRW, X3F -> true
|
||||||
else -> false
|
else -> false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -142,7 +143,7 @@ object MimeTypes {
|
||||||
return if (pageId != null && MultiPageImage.isSupported(mimeType)) {
|
return if (pageId != null && MultiPageImage.isSupported(mimeType)) {
|
||||||
true
|
true
|
||||||
} else when (mimeType) {
|
} else when (mimeType) {
|
||||||
DNG, HEIC, HEIF, PNG, WEBP -> true
|
DNG, DNG_ADOBE, HEIC, HEIF, PNG, WEBP -> true
|
||||||
else -> false
|
else -> false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -151,7 +152,7 @@ object MimeTypes {
|
||||||
// according to EXIF orientation when decoding images of known formats
|
// according to EXIF orientation when decoding images of known formats
|
||||||
// but we need to rotate the decoded bitmap for the other formats
|
// but we need to rotate the decoded bitmap for the other formats
|
||||||
fun needRotationAfterContentResolverThumbnail(mimeType: String) = when (mimeType) {
|
fun needRotationAfterContentResolverThumbnail(mimeType: String) = when (mimeType) {
|
||||||
DNG, PNG -> true
|
DNG, DNG_ADOBE, PNG -> true
|
||||||
else -> false
|
else -> false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,6 @@ object PermissionManager {
|
||||||
Environment.DIRECTORY_PICTURES,
|
Environment.DIRECTORY_PICTURES,
|
||||||
)
|
)
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
|
|
||||||
suspend fun requestDirectoryAccess(activity: Activity, path: String, onGranted: (uri: Uri) -> Unit, onDenied: () -> Unit) {
|
suspend fun requestDirectoryAccess(activity: Activity, path: String, onGranted: (uri: Uri) -> Unit, onDenied: () -> Unit) {
|
||||||
Log.i(LOG_TAG, "request user to select and grant access permission to path=$path")
|
Log.i(LOG_TAG, "request user to select and grant access permission to path=$path")
|
||||||
|
|
||||||
|
@ -151,7 +150,6 @@ object PermissionManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
|
|
||||||
fun revokeDirectoryAccess(context: Context, path: String): Boolean {
|
fun revokeDirectoryAccess(context: Context, path: String): Boolean {
|
||||||
return StorageUtils.convertDirPathToTreeDocumentUri(context, path)?.let {
|
return StorageUtils.convertDirPathToTreeDocumentUri(context, path)?.let {
|
||||||
releaseUriPermission(context, it)
|
releaseUriPermission(context, it)
|
||||||
|
@ -162,12 +160,10 @@ object PermissionManager {
|
||||||
// returns paths matching directory URIs granted by the user
|
// returns paths matching directory URIs granted by the user
|
||||||
fun getGrantedDirs(context: Context): Set<String> {
|
fun getGrantedDirs(context: Context): Set<String> {
|
||||||
val grantedDirs = HashSet<String>()
|
val grantedDirs = HashSet<String>()
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
|
||||||
for (uriPermission in context.contentResolver.persistedUriPermissions) {
|
for (uriPermission in context.contentResolver.persistedUriPermissions) {
|
||||||
val dirPath = StorageUtils.convertTreeDocumentUriToDirPath(context, uriPermission.uri)
|
val dirPath = StorageUtils.convertTreeDocumentUriToDirPath(context, uriPermission.uri)
|
||||||
dirPath?.let { grantedDirs.add(it) }
|
dirPath?.let { grantedDirs.add(it) }
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return grantedDirs
|
return grantedDirs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -216,19 +212,6 @@ object PermissionManager {
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
} else if (Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT
|
|
||||||
|| Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT_WATCH
|
|
||||||
) {
|
|
||||||
// removable storage requires access permission, at the file level
|
|
||||||
// without directory access, we consider the whole volume restricted
|
|
||||||
val primaryVolume = StorageUtils.getPrimaryVolumePath(context)
|
|
||||||
val nonPrimaryVolumes = StorageUtils.getVolumePaths(context).filter { it != primaryVolume }
|
|
||||||
dirs.addAll(nonPrimaryVolumes.map {
|
|
||||||
hashMapOf(
|
|
||||||
"volumePath" to it,
|
|
||||||
"relativeDir" to "",
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
return dirs
|
return dirs
|
||||||
}
|
}
|
||||||
|
@ -236,7 +219,6 @@ object PermissionManager {
|
||||||
// As of Android 11, `MediaStore.getDocumentUri` fails if any of the persisted
|
// As of Android 11, `MediaStore.getDocumentUri` fails if any of the persisted
|
||||||
// URI permissions we hold points to a folder that no longer exists,
|
// URI permissions we hold points to a folder that no longer exists,
|
||||||
// so we should remove these obsolete URIs before proceeding.
|
// so we should remove these obsolete URIs before proceeding.
|
||||||
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
|
|
||||||
fun sanitizePersistedUriPermissions(context: Context) {
|
fun sanitizePersistedUriPermissions(context: Context) {
|
||||||
try {
|
try {
|
||||||
for (uriPermission in context.contentResolver.persistedUriPermissions) {
|
for (uriPermission in context.contentResolver.persistedUriPermissions) {
|
||||||
|
@ -252,7 +234,6 @@ object PermissionManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
|
|
||||||
private fun releaseUriPermission(context: Context, it: Uri) {
|
private fun releaseUriPermission(context: Context, it: Uri) {
|
||||||
val flags = Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
|
val flags = Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
|
||||||
context.contentResolver.releasePersistableUriPermission(it, flags)
|
context.contentResolver.releasePersistableUriPermission(it, flags)
|
||||||
|
|
|
@ -16,7 +16,6 @@ import android.provider.DocumentsContract
|
||||||
import android.provider.MediaStore
|
import android.provider.MediaStore
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.annotation.RequiresApi
|
|
||||||
import com.commonsware.cwac.document.DocumentFileCompat
|
import com.commonsware.cwac.document.DocumentFileCompat
|
||||||
import deckers.thibault.aves.model.provider.ImageProvider
|
import deckers.thibault.aves.model.provider.ImageProvider
|
||||||
import deckers.thibault.aves.utils.FileUtils.transferFrom
|
import deckers.thibault.aves.utils.FileUtils.transferFrom
|
||||||
|
@ -29,7 +28,7 @@ import java.io.FileInputStream
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
import java.io.OutputStream
|
import java.io.OutputStream
|
||||||
import java.util.*
|
import java.util.Locale
|
||||||
import java.util.regex.Pattern
|
import java.util.regex.Pattern
|
||||||
|
|
||||||
object StorageUtils {
|
object StorageUtils {
|
||||||
|
@ -381,7 +380,6 @@ object StorageUtils {
|
||||||
// e.g.
|
// e.g.
|
||||||
// /storage/emulated/0/ -> content://com.android.externalstorage.documents/tree/primary%3A
|
// /storage/emulated/0/ -> content://com.android.externalstorage.documents/tree/primary%3A
|
||||||
// /storage/10F9-3F13/Pictures/ -> content://com.android.externalstorage.documents/tree/10F9-3F13%3APictures
|
// /storage/10F9-3F13/Pictures/ -> content://com.android.externalstorage.documents/tree/10F9-3F13%3APictures
|
||||||
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
|
|
||||||
fun convertDirPathToTreeDocumentUri(context: Context, dirPath: String): Uri? {
|
fun convertDirPathToTreeDocumentUri(context: Context, dirPath: String): Uri? {
|
||||||
val uuid = getVolumeUuidForDocumentUri(context, dirPath)
|
val uuid = getVolumeUuidForDocumentUri(context, dirPath)
|
||||||
if (uuid != null) {
|
if (uuid != null) {
|
||||||
|
@ -446,7 +444,7 @@ object StorageUtils {
|
||||||
|
|
||||||
fun getDocumentFile(context: Context, anyPath: String, mediaUri: Uri): DocumentFileCompat? {
|
fun getDocumentFile(context: Context, anyPath: String, mediaUri: Uri): DocumentFileCompat? {
|
||||||
try {
|
try {
|
||||||
if (requireAccessPermission(context, anyPath) && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
if (requireAccessPermission(context, anyPath)) {
|
||||||
// need a document URI (not a media content URI) to open a `DocumentFile` output stream
|
// need a document URI (not a media content URI) to open a `DocumentFile` output stream
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && isMediaStoreContentUri(mediaUri)) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && isMediaStoreContentUri(mediaUri)) {
|
||||||
// cleanest API to get it
|
// cleanest API to get it
|
||||||
|
@ -485,7 +483,7 @@ object StorageUtils {
|
||||||
fun createDirectoryDocIfAbsent(context: Context, dirPath: String): DocumentFileCompat? {
|
fun createDirectoryDocIfAbsent(context: Context, dirPath: String): DocumentFileCompat? {
|
||||||
try {
|
try {
|
||||||
val cleanDirPath = ensureTrailingSeparator(dirPath)
|
val cleanDirPath = ensureTrailingSeparator(dirPath)
|
||||||
return if (requireAccessPermission(context, cleanDirPath) && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
return if (requireAccessPermission(context, cleanDirPath)) {
|
||||||
val grantedDir = getGrantedDirForPath(context, cleanDirPath) ?: return null
|
val grantedDir = getGrantedDirForPath(context, cleanDirPath) ?: return null
|
||||||
val rootTreeDocumentUri = convertDirPathToTreeDocumentUri(context, grantedDir) ?: return null
|
val rootTreeDocumentUri = convertDirPathToTreeDocumentUri(context, grantedDir) ?: return null
|
||||||
var parentFile: DocumentFileCompat? = DocumentFileCompat.fromTreeUri(context, rootTreeDocumentUri) ?: return null
|
var parentFile: DocumentFileCompat? = DocumentFileCompat.fromTreeUri(context, rootTreeDocumentUri) ?: return null
|
||||||
|
|
|
@ -10,9 +10,9 @@ class ImageProviderTest {
|
||||||
@Test
|
@Test
|
||||||
fun imageProvider_CorrectEmailSimple_ReturnsTrue() {
|
fun imageProvider_CorrectEmailSimple_ReturnsTrue() {
|
||||||
val date = LocalDate.of(1990, Month.FEBRUARY, 11).toEpochDay()
|
val date = LocalDate.of(1990, Month.FEBRUARY, 11).toEpochDay()
|
||||||
assertEquals(ImageProvider.getTimeZoneString(TimeZone.getTimeZone("Europe/Paris"), date), "+01:00")
|
assertEquals("+01:00", ImageProvider.getTimeZoneString(TimeZone.getTimeZone("Europe/Paris"), date))
|
||||||
assertEquals(ImageProvider.getTimeZoneString(TimeZone.getTimeZone("UTC"), date), "+00:00")
|
assertEquals("+00:00", ImageProvider.getTimeZoneString(TimeZone.getTimeZone("UTC"), date))
|
||||||
assertEquals(ImageProvider.getTimeZoneString(TimeZone.getTimeZone("Asia/Kolkata"), date), "+05:30")
|
assertEquals("+05:30", ImageProvider.getTimeZoneString(TimeZone.getTimeZone("Asia/Kolkata"), date))
|
||||||
assertEquals(ImageProvider.getTimeZoneString(TimeZone.getTimeZone("America/Chicago"), date), "-06:00")
|
assertEquals("-06:00", ImageProvider.getTimeZoneString(TimeZone.getTimeZone("America/Chicago"), date))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
package deckers.thibault.aves.utils
|
||||||
|
|
||||||
|
import deckers.thibault.aves.utils.MathUtils.highestPowerOf2
|
||||||
|
import org.junit.jupiter.api.Assertions.assertEquals
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
|
||||||
|
class MathUtilsTest {
|
||||||
|
@Test
|
||||||
|
fun mathUtils_highestPowerOf2() {
|
||||||
|
assertEquals(1024, highestPowerOf2(1024))
|
||||||
|
assertEquals(32, highestPowerOf2(42))
|
||||||
|
assertEquals(0, highestPowerOf2(0))
|
||||||
|
assertEquals(0, highestPowerOf2(-42))
|
||||||
|
assertEquals(0, highestPowerOf2(.5))
|
||||||
|
assertEquals(1, highestPowerOf2(1.5))
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
buildscript {
|
buildscript {
|
||||||
ext {
|
ext {
|
||||||
agp_version = '8.4.0-rc02' // same as `settings.ext.agp_version` in `/android/settings.gradle`
|
agp_version = '8.4.1' // same as `settings.ext.agp_version` in `/android/settings.gradle`
|
||||||
glide_version = '4.16.0'
|
glide_version = '4.16.0'
|
||||||
// AppGallery Connect plugin versions: https://developer.huawei.com/consumer/en/doc/development/AppGallery-connect-Guides/agc-sdk-changenotes-0000001058732550
|
// AppGallery Connect plugin versions: https://developer.huawei.com/consumer/en/doc/development/AppGallery-connect-Guides/agc-sdk-changenotes-0000001058732550
|
||||||
huawei_agconnect_version = '1.9.1.300'
|
huawei_agconnect_version = '1.9.1.300'
|
||||||
|
@ -25,7 +25,7 @@ buildscript {
|
||||||
|
|
||||||
if (useCrashlytics) {
|
if (useCrashlytics) {
|
||||||
// GMS & Firebase Crashlytics (used by some flavors only)
|
// GMS & Firebase Crashlytics (used by some flavors only)
|
||||||
classpath 'com.google.gms:google-services:4.4.0'
|
classpath 'com.google.gms:google-services:4.4.1'
|
||||||
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.9.9'
|
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.9.9'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,5 +26,5 @@ android {
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation 'androidx.annotation:annotation:1.7.1'
|
implementation 'androidx.annotation:annotation:1.8.0'
|
||||||
}
|
}
|
|
@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
|
||||||
|
|
|
@ -8,9 +8,9 @@ pluginManagement {
|
||||||
}
|
}
|
||||||
settings.ext.flutterSdkPath = flutterSdkPath()
|
settings.ext.flutterSdkPath = flutterSdkPath()
|
||||||
|
|
||||||
settings.ext.kotlin_version = '1.9.21'
|
settings.ext.kotlin_version = '1.9.24'
|
||||||
settings.ext.ksp_version = "$kotlin_version-1.0.15"
|
settings.ext.ksp_version = "$kotlin_version-1.0.20"
|
||||||
settings.ext.agp_version = '8.4.0-rc02'
|
settings.ext.agp_version = '8.4.1'
|
||||||
|
|
||||||
includeBuild("${settings.ext.flutterSdkPath}/packages/flutter_tools/gradle")
|
includeBuild("${settings.ext.flutterSdkPath}/packages/flutter_tools/gradle")
|
||||||
|
|
||||||
|
|
3
devtools_options.yaml
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
description: This file stores settings for Dart & Flutter DevTools.
|
||||||
|
documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states
|
||||||
|
extensions:
|
3
fastlane/metadata/android/en-US/changelogs/121.txt
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
In v1.11.2:
|
||||||
|
- show selected albums together in Collection
|
||||||
|
Full changelog available on GitHub
|
3
fastlane/metadata/android/en-US/changelogs/12101.txt
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
In v1.11.2:
|
||||||
|
- show selected albums together in Collection
|
||||||
|
Full changelog available on GitHub
|
|
@ -2,4 +2,4 @@
|
||||||
|
|
||||||
<b>پیمایش و جستجو</b>یک بخش مهم از <i>اِیوْز</i> است. هدف این است که کاربران به راحتی از آلبوم ها به عکس ها به برچسب ها به نقشه ها و غیره دست پیدا کنند.
|
<b>پیمایش و جستجو</b>یک بخش مهم از <i>اِیوْز</i> است. هدف این است که کاربران به راحتی از آلبوم ها به عکس ها به برچسب ها به نقشه ها و غیره دست پیدا کنند.
|
||||||
|
|
||||||
<i>اِیوْز</i> با اندروید سازگار است (از نسخه KitKat تا اندروید 14, شامل تلوزیون اندرویدی) با قابلیت هایی مانند <b>ابزارک ها</b>, <b>میانبر ها</b>, <b>ذخیره نیرو</b> و <b>جستجو عمومی</b> و همچنین میتوان از آن به عنوان <b>نمایشگر و انتخابگز رسانه</b> استفاده کرد.
|
<i>اِیوْز</i> با اندروید سازگار است (از نسخه KitKat تا اندروید 14, شامل تلوزیون اندرویدی) با قابلیت هایی مانند <b>ابزارک ها</b>, <b>میانبر ها</b>, <b>ذخیره نیرو</b> و <b>جستجو عمومی</b> و همچنین میتوان از آن به عنوان <b>نمایشگر و انتخابگر رسانه</b> استفاده کرد.
|
||||||
|
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 278 KiB After Width: | Height: | Size: 279 KiB |
Before Width: | Height: | Size: 495 KiB After Width: | Height: | Size: 495 KiB |
Before Width: | Height: | Size: 189 KiB After Width: | Height: | Size: 189 KiB |
Before Width: | Height: | Size: 120 KiB After Width: | Height: | Size: 119 KiB |
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 71 KiB |
Before Width: | Height: | Size: 322 KiB After Width: | Height: | Size: 322 KiB |
Before Width: | Height: | Size: 333 KiB After Width: | Height: | Size: 333 KiB |
|
@ -1,4 +1,5 @@
|
||||||
enum AppMode {
|
enum AppMode {
|
||||||
|
initialization,
|
||||||
main,
|
main,
|
||||||
pickCollectionFiltersExternal,
|
pickCollectionFiltersExternal,
|
||||||
pickSingleMediaExternal,
|
pickSingleMediaExternal,
|
||||||
|
@ -31,7 +32,10 @@ extension ExtraAppMode on AppMode {
|
||||||
AppMode.pickMultipleMediaExternal,
|
AppMode.pickMultipleMediaExternal,
|
||||||
}.contains(this);
|
}.contains(this);
|
||||||
|
|
||||||
bool get canSelectFilter => this == AppMode.main;
|
bool get canSelectFilter => {
|
||||||
|
AppMode.main,
|
||||||
|
AppMode.pickCollectionFiltersExternal,
|
||||||
|
}.contains(this);
|
||||||
|
|
||||||
bool get canCreateFilter => {
|
bool get canCreateFilter => {
|
||||||
AppMode.main,
|
AppMode.main,
|
||||||
|
|
|
@ -887,7 +887,7 @@
|
||||||
"@placePageTitle": {},
|
"@placePageTitle": {},
|
||||||
"filterOnThisDayLabel": "في هذا اليوم",
|
"filterOnThisDayLabel": "في هذا اليوم",
|
||||||
"@filterOnThisDayLabel": {},
|
"@filterOnThisDayLabel": {},
|
||||||
"columnCount": "{count, plural, =1{1 عمود} other{{count} أعمدة}}{count}",
|
"columnCount": "{count, plural, =1{{count} عمود} other{{count} أعمدة}}{count}",
|
||||||
"@columnCount": {
|
"@columnCount": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"count": {}
|
"count": {}
|
||||||
|
@ -941,7 +941,7 @@
|
||||||
"@albumMimeTypeMixed": {},
|
"@albumMimeTypeMixed": {},
|
||||||
"settingsViewerQuickActionEditorAvailableButtonsSectionTitle": "الأزرار المتاحة",
|
"settingsViewerQuickActionEditorAvailableButtonsSectionTitle": "الأزرار المتاحة",
|
||||||
"@settingsViewerQuickActionEditorAvailableButtonsSectionTitle": {},
|
"@settingsViewerQuickActionEditorAvailableButtonsSectionTitle": {},
|
||||||
"itemCount": "{count, plural, =1{1 عنصر} other{{count} عناصر}}",
|
"itemCount": "{count, plural, =1{{count} عنصر} other{{count} عناصر}}",
|
||||||
"@itemCount": {
|
"@itemCount": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"count": {}
|
"count": {}
|
||||||
|
@ -1247,7 +1247,7 @@
|
||||||
"@drawerCollectionImages": {},
|
"@drawerCollectionImages": {},
|
||||||
"sortOrderSmallestFirst": "الأصغر أولاً",
|
"sortOrderSmallestFirst": "الأصغر أولاً",
|
||||||
"@sortOrderSmallestFirst": {},
|
"@sortOrderSmallestFirst": {},
|
||||||
"timeSeconds": "{seconds, plural, =1{1 ثانية} other{{seconds} ثواني}}",
|
"timeSeconds": "{count, plural, =1{{count} ثانية} other{{count} ثواني}}",
|
||||||
"@timeSeconds": {
|
"@timeSeconds": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"seconds": {}
|
"seconds": {}
|
||||||
|
@ -1393,7 +1393,7 @@
|
||||||
"@subtitlePositionBottom": {},
|
"@subtitlePositionBottom": {},
|
||||||
"castDialogTitle": "أجهزة البث",
|
"castDialogTitle": "أجهزة البث",
|
||||||
"@castDialogTitle": {},
|
"@castDialogTitle": {},
|
||||||
"timeDays": "{days, plural, =1{1 يوم} other{{days} أيام}}",
|
"timeDays": "{count, plural, =1{{count} يوم} other{{count} أيام}}",
|
||||||
"@timeDays": {
|
"@timeDays": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"days": {}
|
"days": {}
|
||||||
|
@ -1425,7 +1425,7 @@
|
||||||
"@newVaultDialogTitle": {},
|
"@newVaultDialogTitle": {},
|
||||||
"entryInfoActionEditRating": "تحرير التقييم",
|
"entryInfoActionEditRating": "تحرير التقييم",
|
||||||
"@entryInfoActionEditRating": {},
|
"@entryInfoActionEditRating": {},
|
||||||
"timeMinutes": "{minutes, plural, =1{1 دقيقة} other{{minutes} دقائق}}",
|
"timeMinutes": "{count, plural, =1{{count} دقيقة} other{{count} دقائق}}",
|
||||||
"@timeMinutes": {
|
"@timeMinutes": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"minutes": {}
|
"minutes": {}
|
||||||
|
@ -1536,5 +1536,7 @@
|
||||||
"settingsForceWesternArabicNumeralsTile": "فرض الأرقام العربية",
|
"settingsForceWesternArabicNumeralsTile": "فرض الأرقام العربية",
|
||||||
"@settingsForceWesternArabicNumeralsTile": {},
|
"@settingsForceWesternArabicNumeralsTile": {},
|
||||||
"renameProcessorHash": "تجزئة",
|
"renameProcessorHash": "تجزئة",
|
||||||
"@renameProcessorHash": {}
|
"@renameProcessorHash": {},
|
||||||
|
"chipActionShowCollection": "عرض في المجموعة",
|
||||||
|
"@chipActionShowCollection": {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
"@welcomeOptional": {},
|
"@welcomeOptional": {},
|
||||||
"welcomeMessage": "Сардэчна запрашаем ў Aves",
|
"welcomeMessage": "Сардэчна запрашаем ў Aves",
|
||||||
"@welcomeMessage": {},
|
"@welcomeMessage": {},
|
||||||
"itemCount": "{count, plural, =1{1 элемент} other{{count} элементаў}}",
|
"itemCount": "{count, plural, =1{{count} элемент} other{{count} элементаў}}",
|
||||||
"@itemCount": {
|
"@itemCount": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"count": {}
|
"count": {}
|
||||||
|
@ -1495,25 +1495,25 @@
|
||||||
"@settingsViewerShowHistogram": {},
|
"@settingsViewerShowHistogram": {},
|
||||||
"settingsVideoPlaybackTile": "Прайграванне",
|
"settingsVideoPlaybackTile": "Прайграванне",
|
||||||
"@settingsVideoPlaybackTile": {},
|
"@settingsVideoPlaybackTile": {},
|
||||||
"columnCount": "{count, plural, =1{1 слупок} few{{count} слупкі} other{{count} слупкоў}}",
|
"columnCount": "{count, plural, =1{{count} слупок} few{{count} слупкі} other{{count} слупкоў}}",
|
||||||
"@columnCount": {
|
"@columnCount": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"count": {}
|
"count": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"timeSeconds": "{seconds, plural, =1{1 секунда} few{{seconds} секунды} other{{seconds} секунд}}",
|
"timeSeconds": "{count, plural, =1{{count} секунда} few{{count} секунды} other{{count} секунд}}",
|
||||||
"@timeSeconds": {
|
"@timeSeconds": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"seconds": {}
|
"seconds": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"timeDays": "{days, plural, =1{1 дзень} few{{days} дні} other{{days} дзён}}",
|
"timeDays": "{count, plural, =1{{count} дзень} few{{count} дні} other{{count} дзён}}",
|
||||||
"@timeDays": {
|
"@timeDays": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"days": {}
|
"days": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"timeMinutes": "{minutes, plural, =1{1 хвіліна} few{{minutes} хвіліны} other{{minutes} хвілін}}",
|
"timeMinutes": "{count, plural, =1{{count} хвіліна} few{{count} хвіліны} other{{count} хвілін}}",
|
||||||
"@timeMinutes": {
|
"@timeMinutes": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"minutes": {}
|
"minutes": {}
|
||||||
|
@ -1536,5 +1536,7 @@
|
||||||
"renameProcessorHash": "Хэш",
|
"renameProcessorHash": "Хэш",
|
||||||
"@renameProcessorHash": {},
|
"@renameProcessorHash": {},
|
||||||
"settingsForceWesternArabicNumeralsTile": "Прымусовыя арабскія лічбы",
|
"settingsForceWesternArabicNumeralsTile": "Прымусовыя арабскія лічбы",
|
||||||
"@settingsForceWesternArabicNumeralsTile": {}
|
"@settingsForceWesternArabicNumeralsTile": {},
|
||||||
|
"chipActionShowCollection": "Паказаць ў Калекцыі",
|
||||||
|
"@chipActionShowCollection": {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,13 +7,13 @@
|
||||||
"@welcomeOptional": {},
|
"@welcomeOptional": {},
|
||||||
"welcomeTermsToggle": "Estic d’acord amb els termes i condicions",
|
"welcomeTermsToggle": "Estic d’acord amb els termes i condicions",
|
||||||
"@welcomeTermsToggle": {},
|
"@welcomeTermsToggle": {},
|
||||||
"itemCount": "{count, plural, =1{1 element} other{{count} elements}}",
|
"itemCount": "{count, plural, =1{{count} element} other{{count} elements}}",
|
||||||
"@itemCount": {
|
"@itemCount": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"count": {}
|
"count": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"columnCount": "{count, plural, =1{1 columna} other{{count} columnes}}",
|
"columnCount": "{count, plural, =1{{count} columna} other{{count} columnes}}",
|
||||||
"@columnCount": {
|
"@columnCount": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"count": {}
|
"count": {}
|
||||||
|
@ -479,19 +479,19 @@
|
||||||
"@policyPageTitle": {},
|
"@policyPageTitle": {},
|
||||||
"collectionPageTitle": "Coŀlecció",
|
"collectionPageTitle": "Coŀlecció",
|
||||||
"@collectionPageTitle": {},
|
"@collectionPageTitle": {},
|
||||||
"timeSeconds": "{seconds, plural, =1{1 segon} other{{seconds} segons}}",
|
"timeSeconds": "{count, plural, =1{{count} segon} other{{count} segons}}",
|
||||||
"@timeSeconds": {
|
"@timeSeconds": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"seconds": {}
|
"seconds": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"timeMinutes": "{minutes, plural, =1{1 minut} other{{minutes} minuts}}",
|
"timeMinutes": "{count, plural, =1{{count} minut} other{{count} minuts}}",
|
||||||
"@timeMinutes": {
|
"@timeMinutes": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"minutes": {}
|
"minutes": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"timeDays": "{days, plural, =1{1 dia} other{{days} dies}}",
|
"timeDays": "{count, plural, =1{{count} dia} other{{count} dies}}",
|
||||||
"@timeDays": {
|
"@timeDays": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"days": {}
|
"days": {}
|
||||||
|
@ -1524,5 +1524,7 @@
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"count": {}
|
"count": {}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
"chipActionShowCollection": "Mostrar a Coŀlecció",
|
||||||
|
"@chipActionShowCollection": {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,13 +4,13 @@
|
||||||
"@welcomeOptional": {},
|
"@welcomeOptional": {},
|
||||||
"welcomeTermsToggle": "ڕازیم بە مەرج و یاساکانی بەکارهێنان",
|
"welcomeTermsToggle": "ڕازیم بە مەرج و یاساکانی بەکارهێنان",
|
||||||
"@welcomeTermsToggle": {},
|
"@welcomeTermsToggle": {},
|
||||||
"columnCount": "{count, plural, =1{١ ڕیز} other{ڕیز {count}}}",
|
"columnCount": "{count, plural, other{ڕیز {count}}}",
|
||||||
"@columnCount": {
|
"@columnCount": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"count": {}
|
"count": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"timeSeconds": "{seconds, plural, =1{١ چرکە} other{چرکە {seconds}}}",
|
"timeSeconds": "{count, plural, other{چرکە {count}}}",
|
||||||
"@timeSeconds": {
|
"@timeSeconds": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"seconds": {}
|
"seconds": {}
|
||||||
|
@ -92,7 +92,7 @@
|
||||||
"@entryActionInfo": {},
|
"@entryActionInfo": {},
|
||||||
"entryActionRestore": "گێڕانەوە",
|
"entryActionRestore": "گێڕانەوە",
|
||||||
"@entryActionRestore": {},
|
"@entryActionRestore": {},
|
||||||
"timeDays": "{days, plural, =1{١ ڕۆژ} other{ڕۆژ {days}}}",
|
"timeDays": "{count, plural, other{ڕۆژ {count}}}",
|
||||||
"@timeDays": {
|
"@timeDays": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"days": {}
|
"days": {}
|
||||||
|
@ -131,7 +131,7 @@
|
||||||
"@videoActionPause": {},
|
"@videoActionPause": {},
|
||||||
"videoActionPlay": "لێدان",
|
"videoActionPlay": "لێدان",
|
||||||
"@videoActionPlay": {},
|
"@videoActionPlay": {},
|
||||||
"itemCount": "{count, plural, =1{١ دانە} other{دانە {count}}}",
|
"itemCount": "{count, plural, other{دانە {count}}}",
|
||||||
"@itemCount": {
|
"@itemCount": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"count": {}
|
"count": {}
|
||||||
|
@ -155,7 +155,7 @@
|
||||||
"@chipActionCreateAlbum": {},
|
"@chipActionCreateAlbum": {},
|
||||||
"entryActionRename": "ناوگۆڕین",
|
"entryActionRename": "ناوگۆڕین",
|
||||||
"@entryActionRename": {},
|
"@entryActionRename": {},
|
||||||
"timeMinutes": "{minutes, plural, =1{١ خولەک} other{خولەک {minutes}}}",
|
"timeMinutes": "{count, plural, other{خولەک {count}}}",
|
||||||
"@timeMinutes": {
|
"@timeMinutes": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"minutes": {}
|
"minutes": {}
|
||||||
|
|
|
@ -44,19 +44,19 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"timeDays": "{days, plural, =1{1 den} few{{days} dny} other{{days} dnů}}",
|
"timeDays": "{count, plural, =1{{count} den} few{{count} dny} other{{count} dnů}}",
|
||||||
"@timeDays": {
|
"@timeDays": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"days": {}
|
"days": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"itemCount": "{count, plural, =1{1 položka} few{{count} položky} other{{count} položek}}",
|
"itemCount": "{count, plural, =1{{count} položka} few{{count} položky} other{{count} položek}}",
|
||||||
"@itemCount": {
|
"@itemCount": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"count": {}
|
"count": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"columnCount": "{count, plural, =1{1 sloupec} few{{count} sloupce} other{{count} sloupců}}",
|
"columnCount": "{count, plural, =1{{count} sloupec} few{{count} sloupce} other{{count} sloupců}}",
|
||||||
"@columnCount": {
|
"@columnCount": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"count": {}
|
"count": {}
|
||||||
|
@ -1279,13 +1279,13 @@
|
||||||
"@settingsThumbnailShowVideoDuration": {},
|
"@settingsThumbnailShowVideoDuration": {},
|
||||||
"settingsCollectionQuickActionsTile": "Rychlé akce",
|
"settingsCollectionQuickActionsTile": "Rychlé akce",
|
||||||
"@settingsCollectionQuickActionsTile": {},
|
"@settingsCollectionQuickActionsTile": {},
|
||||||
"timeMinutes": "{minutes, plural, =1{1 minuta} few{{minutes} minuty} other{{minutes} minut}}",
|
"timeMinutes": "{count, plural, =1{{count} minuta} few{{count} minuty} other{{count} minut}}",
|
||||||
"@timeMinutes": {
|
"@timeMinutes": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"minutes": {}
|
"minutes": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"timeSeconds": "{seconds, plural, =1{1 sekunda} few{{seconds} sekundy} other{{seconds} sekund}}",
|
"timeSeconds": "{count, plural, =1{{count} sekunda} few{{count} sekundy} other{{count} sekund}}",
|
||||||
"@timeSeconds": {
|
"@timeSeconds": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"seconds": {}
|
"seconds": {}
|
||||||
|
@ -1532,5 +1532,7 @@
|
||||||
"videoRepeatActionSetEnd": "Nastavit konec",
|
"videoRepeatActionSetEnd": "Nastavit konec",
|
||||||
"@videoRepeatActionSetEnd": {},
|
"@videoRepeatActionSetEnd": {},
|
||||||
"videoActionABRepeat": "Opakování A-B",
|
"videoActionABRepeat": "Opakování A-B",
|
||||||
"@videoActionABRepeat": {}
|
"@videoActionABRepeat": {},
|
||||||
|
"chipActionShowCollection": "Zobrazit ve sbírce",
|
||||||
|
"@chipActionShowCollection": {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,13 +7,13 @@
|
||||||
"@welcomeOptional": {},
|
"@welcomeOptional": {},
|
||||||
"welcomeTermsToggle": "Ich stimme den Bedingungen und Konditionen zu",
|
"welcomeTermsToggle": "Ich stimme den Bedingungen und Konditionen zu",
|
||||||
"@welcomeTermsToggle": {},
|
"@welcomeTermsToggle": {},
|
||||||
"itemCount": "{count, plural, =1{1 Element} other{{count} Elemente}}",
|
"itemCount": "{count, plural, =1{{count} Element} other{{count} Elemente}}",
|
||||||
"@itemCount": {},
|
"@itemCount": {},
|
||||||
"timeSeconds": "{seconds, plural, =1{1 Sekunde} other{{seconds} Sekunde}}",
|
"timeSeconds": "{count, plural, =1{{count} Sekunde} other{{count} Sekunde}}",
|
||||||
"@timeSeconds": {},
|
"@timeSeconds": {},
|
||||||
"timeMinutes": "{minutes, plural, =1{1 Minute} other{{minutes} Minuten}}",
|
"timeMinutes": "{count, plural, =1{{count} Minute} other{{count} Minuten}}",
|
||||||
"@timeMinutes": {},
|
"@timeMinutes": {},
|
||||||
"timeDays": "{days, plural, =1{1 Tag} other{{days} Tage}}",
|
"timeDays": "{count, plural, =1{{count} Tag} other{{count} Tage}}",
|
||||||
"@timeDays": {},
|
"@timeDays": {},
|
||||||
"focalLength": "{length} mm",
|
"focalLength": "{length} mm",
|
||||||
"@focalLength": {},
|
"@focalLength": {},
|
||||||
|
@ -1193,7 +1193,7 @@
|
||||||
"@settingsAccessibilityShowPinchGestureAlternatives": {},
|
"@settingsAccessibilityShowPinchGestureAlternatives": {},
|
||||||
"settingsDisplayUseTvInterface": "Android-TV Oberfläche",
|
"settingsDisplayUseTvInterface": "Android-TV Oberfläche",
|
||||||
"@settingsDisplayUseTvInterface": {},
|
"@settingsDisplayUseTvInterface": {},
|
||||||
"columnCount": "{count, plural, =1{1 Spalte} other{{count} Spalten}}",
|
"columnCount": "{count, plural, =1{{count} Spalte} other{{count} Spalten}}",
|
||||||
"@columnCount": {
|
"@columnCount": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"count": {}
|
"count": {}
|
||||||
|
@ -1366,5 +1366,19 @@
|
||||||
"entryActionCast": "Übertragen",
|
"entryActionCast": "Übertragen",
|
||||||
"@entryActionCast": {},
|
"@entryActionCast": {},
|
||||||
"castDialogTitle": "Geräte zur Übertragung",
|
"castDialogTitle": "Geräte zur Übertragung",
|
||||||
"@castDialogTitle": {}
|
"@castDialogTitle": {},
|
||||||
|
"renameProcessorHash": "Raute",
|
||||||
|
"@renameProcessorHash": {},
|
||||||
|
"settingsForceWesternArabicNumeralsTile": "Arabische Ziffern erzwingen",
|
||||||
|
"@settingsForceWesternArabicNumeralsTile": {},
|
||||||
|
"videoActionABRepeat": "A-B-Wiederholung",
|
||||||
|
"@videoActionABRepeat": {},
|
||||||
|
"videoRepeatActionSetStart": "Start festlegen",
|
||||||
|
"@videoRepeatActionSetStart": {},
|
||||||
|
"stopTooltip": "Stop",
|
||||||
|
"@stopTooltip": {},
|
||||||
|
"videoRepeatActionSetEnd": "Ende festlegen",
|
||||||
|
"@videoRepeatActionSetEnd": {},
|
||||||
|
"chipActionShowCollection": "In Sammlung anzeigen",
|
||||||
|
"@chipActionShowCollection": {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,13 +7,13 @@
|
||||||
"@welcomeOptional": {},
|
"@welcomeOptional": {},
|
||||||
"welcomeTermsToggle": "Συμφωνώ με τους όρους και τις προυποθέσεις",
|
"welcomeTermsToggle": "Συμφωνώ με τους όρους και τις προυποθέσεις",
|
||||||
"@welcomeTermsToggle": {},
|
"@welcomeTermsToggle": {},
|
||||||
"itemCount": "{count, plural, =1{1 στοιχείο} other{{count} στοιχεία}}",
|
"itemCount": "{count, plural, =1{{count} στοιχείο} other{{count} στοιχεία}}",
|
||||||
"@itemCount": {},
|
"@itemCount": {},
|
||||||
"timeSeconds": "{seconds, plural, =1{1 δευτερόλεπτο} other{{seconds} δευτερόλεπτα}}",
|
"timeSeconds": "{count, plural, =1{{count} δευτερόλεπτο} other{{count} δευτερόλεπτα}}",
|
||||||
"@timeSeconds": {},
|
"@timeSeconds": {},
|
||||||
"timeMinutes": "{minutes, plural, =1{1 λεπτό} other{{minutes} λεπτά}}",
|
"timeMinutes": "{count, plural, =1{{count} λεπτό} other{{count} λεπτά}}",
|
||||||
"@timeMinutes": {},
|
"@timeMinutes": {},
|
||||||
"timeDays": "{days, plural, =1{1 ημέρα} other{{days} ημέρες}}",
|
"timeDays": "{count, plural, =1{{count} ημέρα} other{{count} ημέρες}}",
|
||||||
"@timeDays": {},
|
"@timeDays": {},
|
||||||
"focalLength": "{length} mm",
|
"focalLength": "{length} mm",
|
||||||
"@focalLength": {},
|
"@focalLength": {},
|
||||||
|
@ -1169,7 +1169,7 @@
|
||||||
"@settingsSubtitleThemeTextPositionDialogTitle": {},
|
"@settingsSubtitleThemeTextPositionDialogTitle": {},
|
||||||
"entryInfoActionExportMetadata": "Εξαγωγή μεταδεδομένων",
|
"entryInfoActionExportMetadata": "Εξαγωγή μεταδεδομένων",
|
||||||
"@entryInfoActionExportMetadata": {},
|
"@entryInfoActionExportMetadata": {},
|
||||||
"columnCount": "{count, plural, =1{1 στήλη} other{{count} στήλες}}",
|
"columnCount": "{count, plural, =1{{count} στήλη} other{{count} στήλες}}",
|
||||||
"@columnCount": {
|
"@columnCount": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"count": {}
|
"count": {}
|
||||||
|
@ -1338,5 +1338,7 @@
|
||||||
"overlayHistogramRGB": "RGB",
|
"overlayHistogramRGB": "RGB",
|
||||||
"@overlayHistogramRGB": {},
|
"@overlayHistogramRGB": {},
|
||||||
"overlayHistogramLuminance": "Φωτεινότητα",
|
"overlayHistogramLuminance": "Φωτεινότητα",
|
||||||
"@overlayHistogramLuminance": {}
|
"@overlayHistogramLuminance": {},
|
||||||
|
"chipActionShowCollection": "Εμφάνιση στη Συλλογή",
|
||||||
|
"@chipActionShowCollection": {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,35 +3,45 @@
|
||||||
"welcomeMessage": "Welcome to Aves",
|
"welcomeMessage": "Welcome to Aves",
|
||||||
"welcomeOptional": "Optional",
|
"welcomeOptional": "Optional",
|
||||||
"welcomeTermsToggle": "I agree to the terms and conditions",
|
"welcomeTermsToggle": "I agree to the terms and conditions",
|
||||||
"itemCount": "{count, plural, =1{1 item} other{{count} items}}",
|
"itemCount": "{count, plural, =1{{count} item} other{{count} items}}",
|
||||||
"@itemCount": {
|
"@itemCount": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"count": {}
|
"count": {
|
||||||
|
"format": "decimalPattern"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"columnCount": "{count, plural, =1{1 column} other{{count} columns}}",
|
"columnCount": "{count, plural, =1{{count} column} other{{count} columns}}",
|
||||||
"@columnCount": {
|
"@columnCount": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"count": {}
|
"count": {
|
||||||
|
"format": "decimalPattern"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
"timeSeconds": "{seconds, plural, =1{1 second} other{{seconds} seconds}}",
|
"timeSeconds": "{count, plural, =1{{count} second} other{{count} seconds}}",
|
||||||
"@timeSeconds": {
|
"@timeSeconds": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"seconds": {}
|
"count": {
|
||||||
|
"format": "decimalPattern"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"timeMinutes": "{minutes, plural, =1{1 minute} other{{minutes} minutes}}",
|
"timeMinutes": "{count, plural, =1{{count} minute} other{{count} minutes}}",
|
||||||
"@timeMinutes": {
|
"@timeMinutes": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"minutes": {}
|
"count": {
|
||||||
|
"format": "decimalPattern"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"timeDays": "{days, plural, =1{1 day} other{{days} days}}",
|
"timeDays": "{count, plural, =1{{count} day} other{{count} days}}",
|
||||||
"@timeDays": {
|
"@timeDays": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"days": {}
|
"count": {
|
||||||
|
"format": "decimalPattern"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"focalLength": "{length} mm",
|
"focalLength": "{length} mm",
|
||||||
|
@ -75,6 +85,7 @@
|
||||||
"sourceStateLocatingPlaces": "Locating places",
|
"sourceStateLocatingPlaces": "Locating places",
|
||||||
|
|
||||||
"chipActionDelete": "Delete",
|
"chipActionDelete": "Delete",
|
||||||
|
"chipActionShowCollection": "Show in Collection",
|
||||||
"chipActionGoToAlbumPage": "Show in Albums",
|
"chipActionGoToAlbumPage": "Show in Albums",
|
||||||
"chipActionGoToCountryPage": "Show in Countries",
|
"chipActionGoToCountryPage": "Show in Countries",
|
||||||
"chipActionGoToPlacePage": "Show in Places",
|
"chipActionGoToPlacePage": "Show in Places",
|
||||||
|
@ -376,13 +387,17 @@
|
||||||
"binEntriesConfirmationDialogMessage": "{count, plural, =1{Move this item to the recycle bin?} other{Move these {count} items to the recycle bin?}}",
|
"binEntriesConfirmationDialogMessage": "{count, plural, =1{Move this item to the recycle bin?} other{Move these {count} items to the recycle bin?}}",
|
||||||
"@binEntriesConfirmationDialogMessage": {
|
"@binEntriesConfirmationDialogMessage": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"count": {}
|
"count": {
|
||||||
|
"format": "decimalPattern"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"deleteEntriesConfirmationDialogMessage": "{count, plural, =1{Delete this item?} other{Delete these {count} items?}}",
|
"deleteEntriesConfirmationDialogMessage": "{count, plural, =1{Delete this item?} other{Delete these {count} items?}}",
|
||||||
"@deleteEntriesConfirmationDialogMessage": {
|
"@deleteEntriesConfirmationDialogMessage": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"count": {}
|
"count": {
|
||||||
|
"format": "decimalPattern"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"moveUndatedConfirmationDialogMessage": "Save item dates before proceeding?",
|
"moveUndatedConfirmationDialogMessage": "Save item dates before proceeding?",
|
||||||
|
@ -446,13 +461,17 @@
|
||||||
"deleteSingleAlbumConfirmationDialogMessage": "{count, plural, =1{Delete this album and the item in it?} other{Delete this album and the {count} items in it?}}",
|
"deleteSingleAlbumConfirmationDialogMessage": "{count, plural, =1{Delete this album and the item in it?} other{Delete this album and the {count} items in it?}}",
|
||||||
"@deleteSingleAlbumConfirmationDialogMessage": {
|
"@deleteSingleAlbumConfirmationDialogMessage": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"count": {}
|
"count": {
|
||||||
|
"format": "decimalPattern"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"deleteMultiAlbumConfirmationDialogMessage": "{count, plural, =1{Delete these albums and the item in them?} other{Delete these albums and the {count} items in them?}}",
|
"deleteMultiAlbumConfirmationDialogMessage": "{count, plural, =1{Delete these albums and the item in them?} other{Delete these albums and the {count} items in them?}}",
|
||||||
"@deleteMultiAlbumConfirmationDialogMessage": {
|
"@deleteMultiAlbumConfirmationDialogMessage": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"count": {}
|
"count": {
|
||||||
|
"format": "decimalPattern"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -597,61 +616,81 @@
|
||||||
"collectionDeleteFailureFeedback": "{count, plural, =1{Failed to delete 1 item} other{Failed to delete {count} items}}",
|
"collectionDeleteFailureFeedback": "{count, plural, =1{Failed to delete 1 item} other{Failed to delete {count} items}}",
|
||||||
"@collectionDeleteFailureFeedback": {
|
"@collectionDeleteFailureFeedback": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"count": {}
|
"count": {
|
||||||
|
"format": "decimalPattern"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"collectionCopyFailureFeedback": "{count, plural, =1{Failed to copy 1 item} other{Failed to copy {count} items}}",
|
"collectionCopyFailureFeedback": "{count, plural, =1{Failed to copy 1 item} other{Failed to copy {count} items}}",
|
||||||
"@collectionCopyFailureFeedback": {
|
"@collectionCopyFailureFeedback": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"count": {}
|
"count": {
|
||||||
|
"format": "decimalPattern"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"collectionMoveFailureFeedback": "{count, plural, =1{Failed to move 1 item} other{Failed to move {count} items}}",
|
"collectionMoveFailureFeedback": "{count, plural, =1{Failed to move 1 item} other{Failed to move {count} items}}",
|
||||||
"@collectionMoveFailureFeedback": {
|
"@collectionMoveFailureFeedback": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"count": {}
|
"count": {
|
||||||
|
"format": "decimalPattern"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"collectionRenameFailureFeedback": "{count, plural, =1{Failed to rename 1 item} other{Failed to rename {count} items}}",
|
"collectionRenameFailureFeedback": "{count, plural, =1{Failed to rename 1 item} other{Failed to rename {count} items}}",
|
||||||
"@collectionRenameFailureFeedback": {
|
"@collectionRenameFailureFeedback": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"count": {}
|
"count": {
|
||||||
|
"format": "decimalPattern"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"collectionEditFailureFeedback": "{count, plural, =1{Failed to edit 1 item} other{Failed to edit {count} items}}",
|
"collectionEditFailureFeedback": "{count, plural, =1{Failed to edit 1 item} other{Failed to edit {count} items}}",
|
||||||
"@collectionEditFailureFeedback": {
|
"@collectionEditFailureFeedback": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"count": {}
|
"count": {
|
||||||
|
"format": "decimalPattern"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"collectionExportFailureFeedback": "{count, plural, =1{Failed to export 1 page} other{Failed to export {count} pages}}",
|
"collectionExportFailureFeedback": "{count, plural, =1{Failed to export 1 page} other{Failed to export {count} pages}}",
|
||||||
"@collectionExportFailureFeedback": {
|
"@collectionExportFailureFeedback": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"count": {}
|
"count": {
|
||||||
|
"format": "decimalPattern"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"collectionCopySuccessFeedback": "{count, plural, =1{Copied 1 item} other{Copied {count} items}}",
|
"collectionCopySuccessFeedback": "{count, plural, =1{Copied 1 item} other{Copied {count} items}}",
|
||||||
"@collectionCopySuccessFeedback": {
|
"@collectionCopySuccessFeedback": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"count": {}
|
"count": {
|
||||||
|
"format": "decimalPattern"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"collectionMoveSuccessFeedback": "{count, plural, =1{Moved 1 item} other{Moved {count} items}}",
|
"collectionMoveSuccessFeedback": "{count, plural, =1{Moved 1 item} other{Moved {count} items}}",
|
||||||
"@collectionMoveSuccessFeedback": {
|
"@collectionMoveSuccessFeedback": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"count": {}
|
"count": {
|
||||||
|
"format": "decimalPattern"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"collectionRenameSuccessFeedback": "{count, plural, =1{Renamed 1 item} other{Renamed {count} items}}",
|
"collectionRenameSuccessFeedback": "{count, plural, =1{Renamed 1 item} other{Renamed {count} items}}",
|
||||||
"@collectionRenameSuccessFeedback": {
|
"@collectionRenameSuccessFeedback": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"count": {}
|
"count": {
|
||||||
|
"format": "decimalPattern"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"collectionEditSuccessFeedback": "{count, plural, =1{Edited 1 item} other{Edited {count} items}}",
|
"collectionEditSuccessFeedback": "{count, plural, =1{Edited 1 item} other{Edited {count} items}}",
|
||||||
"@collectionEditSuccessFeedback": {
|
"@collectionEditSuccessFeedback": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"count": {}
|
"count": {
|
||||||
|
"format": "decimalPattern"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -949,7 +988,9 @@
|
||||||
"statsWithGps": "{count, plural, =1{1 item with location} other{{count} items with location}}",
|
"statsWithGps": "{count, plural, =1{1 item with location} other{{count} items with location}}",
|
||||||
"@statsWithGps": {
|
"@statsWithGps": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"count": {}
|
"count": {
|
||||||
|
"format": "decimalPattern"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"statsTopCountriesSectionTitle": "Top Countries",
|
"statsTopCountriesSectionTitle": "Top Countries",
|
||||||
|
|
|
@ -7,13 +7,13 @@
|
||||||
"@welcomeOptional": {},
|
"@welcomeOptional": {},
|
||||||
"welcomeTermsToggle": "Acepto los términos y condiciones",
|
"welcomeTermsToggle": "Acepto los términos y condiciones",
|
||||||
"@welcomeTermsToggle": {},
|
"@welcomeTermsToggle": {},
|
||||||
"itemCount": "{count, plural, =1{1 elemento} other{{count} elementos}}",
|
"itemCount": "{count, plural, =1{{count} elemento} other{{count} elementos}}",
|
||||||
"@itemCount": {},
|
"@itemCount": {},
|
||||||
"timeSeconds": "{seconds, plural, =1{1 segundo} other{{seconds} segundos}}",
|
"timeSeconds": "{count, plural, =1{{count} segundo} other{{count} segundos}}",
|
||||||
"@timeSeconds": {},
|
"@timeSeconds": {},
|
||||||
"timeMinutes": "{minutes, plural, =1{1 minuto} other{{minutes} minutos}}",
|
"timeMinutes": "{count, plural, =1{{count} minuto} other{{count} minutos}}",
|
||||||
"@timeMinutes": {},
|
"@timeMinutes": {},
|
||||||
"timeDays": "{days, plural, =1{1 día} other{{days} días}}",
|
"timeDays": "{count, plural, =1{{count} día} other{{count} días}}",
|
||||||
"@timeDays": {},
|
"@timeDays": {},
|
||||||
"focalLength": "{length} mm",
|
"focalLength": "{length} mm",
|
||||||
"@focalLength": {},
|
"@focalLength": {},
|
||||||
|
@ -1187,7 +1187,7 @@
|
||||||
"@keepScreenOnVideoPlayback": {},
|
"@keepScreenOnVideoPlayback": {},
|
||||||
"settingsAccessibilityShowPinchGestureAlternatives": "Mostrar alternativas a gestos multitáctiles",
|
"settingsAccessibilityShowPinchGestureAlternatives": "Mostrar alternativas a gestos multitáctiles",
|
||||||
"@settingsAccessibilityShowPinchGestureAlternatives": {},
|
"@settingsAccessibilityShowPinchGestureAlternatives": {},
|
||||||
"columnCount": "{count, plural, =1{1 columna} other{{count} columnas}}",
|
"columnCount": "{count, plural, =1{{count} columna} other{{count} columnas}}",
|
||||||
"@columnCount": {
|
"@columnCount": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"count": {}
|
"count": {}
|
||||||
|
@ -1378,5 +1378,7 @@
|
||||||
"settingsForceWesternArabicNumeralsTile": "Forzar números arábigos",
|
"settingsForceWesternArabicNumeralsTile": "Forzar números arábigos",
|
||||||
"@settingsForceWesternArabicNumeralsTile": {},
|
"@settingsForceWesternArabicNumeralsTile": {},
|
||||||
"renameProcessorHash": "Hash",
|
"renameProcessorHash": "Hash",
|
||||||
"@renameProcessorHash": {}
|
"@renameProcessorHash": {},
|
||||||
|
"chipActionShowCollection": "Mostrar en Colección",
|
||||||
|
"@chipActionShowCollection": {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,25 +1,25 @@
|
||||||
{
|
{
|
||||||
"saveTooltip": "Gorde",
|
"saveTooltip": "Gorde",
|
||||||
"@saveTooltip": {},
|
"@saveTooltip": {},
|
||||||
"columnCount": "{count, plural, =1{zutabe 1} other{{count} zutabe}}",
|
"columnCount": "{count, plural, =1{zutabe {count}} other{{count} zutabe}}",
|
||||||
"@columnCount": {
|
"@columnCount": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"count": {}
|
"count": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"timeSeconds": "{seconds, plural, =1{segundu 1} other{{seconds} segundu}}",
|
"timeSeconds": "{count, plural, =1{segundu {count}} other{{count} segundu}}",
|
||||||
"@timeSeconds": {
|
"@timeSeconds": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"seconds": {}
|
"seconds": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"timeMinutes": "{minutes, plural, =1{minutu 1} other{{minutes} minutu}}",
|
"timeMinutes": "{count, plural, =1{minutu {count}} other{{count} minutu}}",
|
||||||
"@timeMinutes": {
|
"@timeMinutes": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"minutes": {}
|
"minutes": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"timeDays": "{days, plural, =1{egun 1} other{{days} egun}}",
|
"timeDays": "{count, plural, =1{egun {count}} other{{count} egun}}",
|
||||||
"@timeDays": {
|
"@timeDays": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"days": {}
|
"days": {}
|
||||||
|
@ -50,7 +50,7 @@
|
||||||
"@welcomeMessage": {},
|
"@welcomeMessage": {},
|
||||||
"welcomeOptional": "Aukerazkoa",
|
"welcomeOptional": "Aukerazkoa",
|
||||||
"@welcomeOptional": {},
|
"@welcomeOptional": {},
|
||||||
"itemCount": "{count, plural, =1{elementu 1} other{{count} elementu}}",
|
"itemCount": "{count, plural, =1{elementu {count}} other{{count} elementu}}",
|
||||||
"@itemCount": {
|
"@itemCount": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"count": {}
|
"count": {}
|
||||||
|
@ -1536,5 +1536,7 @@
|
||||||
"videoActionABRepeat": "Atik Brako errepikapena",
|
"videoActionABRepeat": "Atik Brako errepikapena",
|
||||||
"@videoActionABRepeat": {},
|
"@videoActionABRepeat": {},
|
||||||
"videoRepeatActionSetEnd": "Ezarri amaiera",
|
"videoRepeatActionSetEnd": "Ezarri amaiera",
|
||||||
"@videoRepeatActionSetEnd": {}
|
"@videoRepeatActionSetEnd": {},
|
||||||
|
"chipActionShowCollection": "Erakutsi bilduman",
|
||||||
|
"@chipActionShowCollection": {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,9 +65,9 @@
|
||||||
"@hideTooltip": {},
|
"@hideTooltip": {},
|
||||||
"chipActionCreateAlbum": "ایجاد البوم",
|
"chipActionCreateAlbum": "ایجاد البوم",
|
||||||
"@chipActionCreateAlbum": {},
|
"@chipActionCreateAlbum": {},
|
||||||
"filterNoRatingLabel": "بدون رتبه",
|
"filterNoRatingLabel": "بدون امتیاز",
|
||||||
"@filterNoRatingLabel": {},
|
"@filterNoRatingLabel": {},
|
||||||
"timeSeconds": "{seconds, plural, =1{1 ثانیع} other{{seconds} ثانیه}}",
|
"timeSeconds": "{count, plural, =1{{count} ثانیع} other{{count} ثانیه}}",
|
||||||
"@timeSeconds": {
|
"@timeSeconds": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"seconds": {}
|
"seconds": {}
|
||||||
|
@ -75,7 +75,7 @@
|
||||||
},
|
},
|
||||||
"deleteButtonLabel": "پاک کردن",
|
"deleteButtonLabel": "پاک کردن",
|
||||||
"@deleteButtonLabel": {},
|
"@deleteButtonLabel": {},
|
||||||
"itemCount": "{count, plural, =1{1 فایل} other{{count} فایل}}",
|
"itemCount": "{count, plural, =1{{count} فایل} other{{count} فایل}}",
|
||||||
"@itemCount": {
|
"@itemCount": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"count": {}
|
"count": {}
|
||||||
|
@ -99,7 +99,7 @@
|
||||||
"@doNotAskAgain": {},
|
"@doNotAskAgain": {},
|
||||||
"entryActionDelete": "پاککردن",
|
"entryActionDelete": "پاککردن",
|
||||||
"@entryActionDelete": {},
|
"@entryActionDelete": {},
|
||||||
"timeMinutes": "{minutes, plural, =1{1 دقیقه} other{{minutes} دقیقه}}",
|
"timeMinutes": "{count, plural, other{{count} دقیقه}}",
|
||||||
"@timeMinutes": {
|
"@timeMinutes": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"minutes": {}
|
"minutes": {}
|
||||||
|
@ -123,7 +123,7 @@
|
||||||
"@entryActionRotateCW": {},
|
"@entryActionRotateCW": {},
|
||||||
"entryInfoActionEditLocation": "ویرایش مکان",
|
"entryInfoActionEditLocation": "ویرایش مکان",
|
||||||
"@entryInfoActionEditLocation": {},
|
"@entryInfoActionEditLocation": {},
|
||||||
"entryActionFlip": "ایینه کردن افقی",
|
"entryActionFlip": "آینه کردن افقی",
|
||||||
"@entryActionFlip": {},
|
"@entryActionFlip": {},
|
||||||
"entryActionShare": "اشتراک گذاری",
|
"entryActionShare": "اشتراک گذاری",
|
||||||
"@entryActionShare": {},
|
"@entryActionShare": {},
|
||||||
|
@ -141,7 +141,7 @@
|
||||||
"@filterBinLabel": {},
|
"@filterBinLabel": {},
|
||||||
"filterNoDateLabel": "بدون تاریخ",
|
"filterNoDateLabel": "بدون تاریخ",
|
||||||
"@filterNoDateLabel": {},
|
"@filterNoDateLabel": {},
|
||||||
"timeDays": "{days, plural, =1{1 روز} other{{days} روز}}",
|
"timeDays": "{count, plural, other{{count} روز}}",
|
||||||
"@timeDays": {
|
"@timeDays": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"days": {}
|
"days": {}
|
||||||
|
@ -163,7 +163,7 @@
|
||||||
"@videoActionSkip10": {},
|
"@videoActionSkip10": {},
|
||||||
"viewerActionSettings": "تنظیمات",
|
"viewerActionSettings": "تنظیمات",
|
||||||
"@viewerActionSettings": {},
|
"@viewerActionSettings": {},
|
||||||
"entryInfoActionEditRating": "ویرایش رتبه",
|
"entryInfoActionEditRating": "ویرایش امتیاز",
|
||||||
"@entryInfoActionEditRating": {},
|
"@entryInfoActionEditRating": {},
|
||||||
"entryInfoActionEditTags": "ویرایش برچسب ها",
|
"entryInfoActionEditTags": "ویرایش برچسب ها",
|
||||||
"@entryInfoActionEditTags": {},
|
"@entryInfoActionEditTags": {},
|
||||||
|
@ -333,7 +333,7 @@
|
||||||
"@videoPlaybackMuted": {},
|
"@videoPlaybackMuted": {},
|
||||||
"storageVolumeDescriptionFallbackPrimary": "حافظه داخلی",
|
"storageVolumeDescriptionFallbackPrimary": "حافظه داخلی",
|
||||||
"@storageVolumeDescriptionFallbackPrimary": {},
|
"@storageVolumeDescriptionFallbackPrimary": {},
|
||||||
"columnCount": "{count, plural, =1{1 ستون} other{{count} ستون}}",
|
"columnCount": "{count, plural, other{{count} ستون}}",
|
||||||
"@columnCount": {
|
"@columnCount": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"count": {}
|
"count": {}
|
||||||
|
@ -363,7 +363,7 @@
|
||||||
"@nameConflictStrategyReplace": {},
|
"@nameConflictStrategyReplace": {},
|
||||||
"displayRefreshRatePreferHighest": "بیشترین مقدار",
|
"displayRefreshRatePreferHighest": "بیشترین مقدار",
|
||||||
"@displayRefreshRatePreferHighest": {},
|
"@displayRefreshRatePreferHighest": {},
|
||||||
"storageAccessDialogMessage": "لطفا شاخهٔ {directory} در «{volume}» را در صفحه بعد انتخاب کنید و اجازه را به برنامه بدهید.",
|
"storageAccessDialogMessage": "لطفا شاخهٔ {directory} در «{volume}» را در صفحه بعد انتخاب کنید و به برنامه اجازه بدهید.",
|
||||||
"@storageAccessDialogMessage": {
|
"@storageAccessDialogMessage": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"directory": {
|
"directory": {
|
||||||
|
@ -571,9 +571,9 @@
|
||||||
"@setCoverDialogCustom": {},
|
"@setCoverDialogCustom": {},
|
||||||
"nameConflictDialogSingleSourceMessage": "برخی از پرونده های موجود در پوشه مقصد به همین نام هستند.",
|
"nameConflictDialogSingleSourceMessage": "برخی از پرونده های موجود در پوشه مقصد به همین نام هستند.",
|
||||||
"@nameConflictDialogSingleSourceMessage": {},
|
"@nameConflictDialogSingleSourceMessage": {},
|
||||||
"missingSystemFilePickerDialogMessage": "انتخابگر پرونده سیستم وجود ندارد یا غیرفعال است. لطفا آن را فعال کنید و دوباره امتحان کنید",
|
"missingSystemFilePickerDialogMessage": "انتخابگر پرونده سامانه وجود ندارد یا غیرفعال است. لطفا آن را فعال کنید و دوباره امتحان کنید.",
|
||||||
"@missingSystemFilePickerDialogMessage": {},
|
"@missingSystemFilePickerDialogMessage": {},
|
||||||
"nameConflictDialogMultipleSourceMessage": "برخی پرونده ها نام های یکسانی دارند",
|
"nameConflictDialogMultipleSourceMessage": "برخی پرونده ها نام های یکسانی دارند.",
|
||||||
"@nameConflictDialogMultipleSourceMessage": {},
|
"@nameConflictDialogMultipleSourceMessage": {},
|
||||||
"noMatchingAppDialogMessage": "هیچ کاره ای وجود ندارد که بتواند این موضوع را مدیریت کند.",
|
"noMatchingAppDialogMessage": "هیچ کاره ای وجود ندارد که بتواند این موضوع را مدیریت کند.",
|
||||||
"@noMatchingAppDialogMessage": {},
|
"@noMatchingAppDialogMessage": {},
|
||||||
|
@ -605,7 +605,7 @@
|
||||||
"@drawerAlbumPage": {},
|
"@drawerAlbumPage": {},
|
||||||
"drawerTagPage": "برچسب ها",
|
"drawerTagPage": "برچسب ها",
|
||||||
"@drawerTagPage": {},
|
"@drawerTagPage": {},
|
||||||
"sortByRating": "با رتبهبندی",
|
"sortByRating": "با امتیازبندی",
|
||||||
"@sortByRating": {},
|
"@sortByRating": {},
|
||||||
"sortByAlbumFileName": "با آلبوم و نام پرونده",
|
"sortByAlbumFileName": "با آلبوم و نام پرونده",
|
||||||
"@sortByAlbumFileName": {},
|
"@sortByAlbumFileName": {},
|
||||||
|
@ -621,9 +621,9 @@
|
||||||
"@settingsViewerQuickActionEditorAvailableButtonsSectionTitle": {},
|
"@settingsViewerQuickActionEditorAvailableButtonsSectionTitle": {},
|
||||||
"settingsViewerQuickActionEmpty": "بدون دکمه",
|
"settingsViewerQuickActionEmpty": "بدون دکمه",
|
||||||
"@settingsViewerQuickActionEmpty": {},
|
"@settingsViewerQuickActionEmpty": {},
|
||||||
"settingsSlideshowVideoPlaybackTile": "بازپخش ویدیو",
|
"settingsSlideshowVideoPlaybackTile": "پخش ویدیو",
|
||||||
"@settingsSlideshowVideoPlaybackTile": {},
|
"@settingsSlideshowVideoPlaybackTile": {},
|
||||||
"settingsSlideshowVideoPlaybackDialogTitle": "بازپخش ویدیو",
|
"settingsSlideshowVideoPlaybackDialogTitle": "پخش ویدیو",
|
||||||
"@settingsSlideshowVideoPlaybackDialogTitle": {},
|
"@settingsSlideshowVideoPlaybackDialogTitle": {},
|
||||||
"settingsVideoResumptionModeTile": "ادامه پخش",
|
"settingsVideoResumptionModeTile": "ادامه پخش",
|
||||||
"@settingsVideoResumptionModeTile": {},
|
"@settingsVideoResumptionModeTile": {},
|
||||||
|
@ -639,9 +639,9 @@
|
||||||
"@viewerInfoSearchSuggestionDate": {},
|
"@viewerInfoSearchSuggestionDate": {},
|
||||||
"settingsSlideshowShuffle": "در هم",
|
"settingsSlideshowShuffle": "در هم",
|
||||||
"@settingsSlideshowShuffle": {},
|
"@settingsSlideshowShuffle": {},
|
||||||
"settingsVideoPlaybackTile": "بازپخش",
|
"settingsVideoPlaybackTile": "پخش",
|
||||||
"@settingsVideoPlaybackTile": {},
|
"@settingsVideoPlaybackTile": {},
|
||||||
"settingsVideoPlaybackPageTitle": "بازپخش",
|
"settingsVideoPlaybackPageTitle": "پخش",
|
||||||
"@settingsVideoPlaybackPageTitle": {},
|
"@settingsVideoPlaybackPageTitle": {},
|
||||||
"viewerInfoLabelResolution": "وضوح",
|
"viewerInfoLabelResolution": "وضوح",
|
||||||
"@viewerInfoLabelResolution": {},
|
"@viewerInfoLabelResolution": {},
|
||||||
|
@ -668,7 +668,7 @@
|
||||||
"@settingsViewerSlideshowPageTitle": {},
|
"@settingsViewerSlideshowPageTitle": {},
|
||||||
"viewerInfoLabelUri": "URI",
|
"viewerInfoLabelUri": "URI",
|
||||||
"@viewerInfoLabelUri": {},
|
"@viewerInfoLabelUri": {},
|
||||||
"moveUndatedConfirmationDialogSetDate": "ذخیره تاریخ ها",
|
"moveUndatedConfirmationDialogSetDate": "نگهداری تاریخ ها",
|
||||||
"@moveUndatedConfirmationDialogSetDate": {},
|
"@moveUndatedConfirmationDialogSetDate": {},
|
||||||
"editEntryLocationDialogLongitude": "طول جغرافیایی",
|
"editEntryLocationDialogLongitude": "طول جغرافیایی",
|
||||||
"@editEntryLocationDialogLongitude": {},
|
"@editEntryLocationDialogLongitude": {},
|
||||||
|
@ -865,7 +865,7 @@
|
||||||
},
|
},
|
||||||
"settingsConfirmationBeforeMoveToBinItems": "پیش از هدایت موارد به سطل زباله بپرسید",
|
"settingsConfirmationBeforeMoveToBinItems": "پیش از هدایت موارد به سطل زباله بپرسید",
|
||||||
"@settingsConfirmationBeforeMoveToBinItems": {},
|
"@settingsConfirmationBeforeMoveToBinItems": {},
|
||||||
"pinDialogEnter": "وارد کردن شماره",
|
"pinDialogEnter": "وارد کردن PIN",
|
||||||
"@pinDialogEnter": {},
|
"@pinDialogEnter": {},
|
||||||
"collectionGroupDay": "با روز",
|
"collectionGroupDay": "با روز",
|
||||||
"@collectionGroupDay": {},
|
"@collectionGroupDay": {},
|
||||||
|
@ -881,7 +881,7 @@
|
||||||
"@filePickerNoItems": {},
|
"@filePickerNoItems": {},
|
||||||
"settingsHomeDialogTitle": "خانه",
|
"settingsHomeDialogTitle": "خانه",
|
||||||
"@settingsHomeDialogTitle": {},
|
"@settingsHomeDialogTitle": {},
|
||||||
"settingsThumbnailShowRating": "نمایش رتبهبندی",
|
"settingsThumbnailShowRating": "نمایش امتیازبندی",
|
||||||
"@settingsThumbnailShowRating": {},
|
"@settingsThumbnailShowRating": {},
|
||||||
"settingsThumbnailShowTagIcon": "نمایش نماد برچسب",
|
"settingsThumbnailShowTagIcon": "نمایش نماد برچسب",
|
||||||
"@settingsThumbnailShowTagIcon": {},
|
"@settingsThumbnailShowTagIcon": {},
|
||||||
|
@ -1067,7 +1067,7 @@
|
||||||
"@drawerPlacePage": {},
|
"@drawerPlacePage": {},
|
||||||
"sortOrderNewestFirst": "اول جدیدترین",
|
"sortOrderNewestFirst": "اول جدیدترین",
|
||||||
"@sortOrderNewestFirst": {},
|
"@sortOrderNewestFirst": {},
|
||||||
"albumGroupTier": "با رتبه",
|
"albumGroupTier": "با امتیاز",
|
||||||
"@albumGroupTier": {},
|
"@albumGroupTier": {},
|
||||||
"sortOrderZtoA": "ی تا ا",
|
"sortOrderZtoA": "ی تا ا",
|
||||||
"@sortOrderZtoA": {},
|
"@sortOrderZtoA": {},
|
||||||
|
@ -1129,7 +1129,7 @@
|
||||||
"@settingsThumbnailShowHdrIcon": {},
|
"@settingsThumbnailShowHdrIcon": {},
|
||||||
"settingsCollectionQuickActionTabBrowsing": "مرور کردن",
|
"settingsCollectionQuickActionTabBrowsing": "مرور کردن",
|
||||||
"@settingsCollectionQuickActionTabBrowsing": {},
|
"@settingsCollectionQuickActionTabBrowsing": {},
|
||||||
"settingsCollectionQuickActionEditorPageTitle": "کنش سریع",
|
"settingsCollectionQuickActionEditorPageTitle": "کنش های سریع",
|
||||||
"@settingsCollectionQuickActionEditorPageTitle": {},
|
"@settingsCollectionQuickActionEditorPageTitle": {},
|
||||||
"settingsCollectionQuickActionTabSelecting": "انتخاب کردن",
|
"settingsCollectionQuickActionTabSelecting": "انتخاب کردن",
|
||||||
"@settingsCollectionQuickActionTabSelecting": {},
|
"@settingsCollectionQuickActionTabSelecting": {},
|
||||||
|
@ -1153,7 +1153,7 @@
|
||||||
"@settingsSlideshowTransitionTile": {},
|
"@settingsSlideshowTransitionTile": {},
|
||||||
"settingsSlideshowIntervalTile": "فاصله",
|
"settingsSlideshowIntervalTile": "فاصله",
|
||||||
"@settingsSlideshowIntervalTile": {},
|
"@settingsSlideshowIntervalTile": {},
|
||||||
"settingsVideoEnableHardwareAcceleration": "شتاب سختافزاری",
|
"settingsVideoEnableHardwareAcceleration": "شتاب سختافزاری",
|
||||||
"@settingsVideoEnableHardwareAcceleration": {},
|
"@settingsVideoEnableHardwareAcceleration": {},
|
||||||
"settingsVideoAutoPlay": "پخش خودکار",
|
"settingsVideoAutoPlay": "پخش خودکار",
|
||||||
"@settingsVideoAutoPlay": {},
|
"@settingsVideoAutoPlay": {},
|
||||||
|
@ -1163,7 +1163,7 @@
|
||||||
"@settingsVideoControlsPageTitle": {},
|
"@settingsVideoControlsPageTitle": {},
|
||||||
"settingsVideoBackgroundModeDialogTitle": "حالت پسزمینه",
|
"settingsVideoBackgroundModeDialogTitle": "حالت پسزمینه",
|
||||||
"@settingsVideoBackgroundModeDialogTitle": {},
|
"@settingsVideoBackgroundModeDialogTitle": {},
|
||||||
"settingsVideoGestureDoubleTapTogglePlay": "برای پخش/ایست دوبار ضربه ردن",
|
"settingsVideoGestureDoubleTapTogglePlay": "برای پخش/ایست دوبار ضربه زدن",
|
||||||
"@settingsVideoGestureDoubleTapTogglePlay": {},
|
"@settingsVideoGestureDoubleTapTogglePlay": {},
|
||||||
"settingsVideoGestureSideDoubleTapSeek": "روی لبه های صفحه دوبار ضربه بزنید تا به عقب/جلو بروید",
|
"settingsVideoGestureSideDoubleTapSeek": "روی لبه های صفحه دوبار ضربه بزنید تا به عقب/جلو بروید",
|
||||||
"@settingsVideoGestureSideDoubleTapSeek": {},
|
"@settingsVideoGestureSideDoubleTapSeek": {},
|
||||||
|
@ -1249,7 +1249,7 @@
|
||||||
"@renameEntrySetPageInsertTooltip": {},
|
"@renameEntrySetPageInsertTooltip": {},
|
||||||
"renameEntrySetPageTitle": "تغییرنام",
|
"renameEntrySetPageTitle": "تغییرنام",
|
||||||
"@renameEntrySetPageTitle": {},
|
"@renameEntrySetPageTitle": {},
|
||||||
"videoSpeedDialogLabel": "سرعت پازپخش",
|
"videoSpeedDialogLabel": "سرعت پخش",
|
||||||
"@videoSpeedDialogLabel": {},
|
"@videoSpeedDialogLabel": {},
|
||||||
"collectionActionAddShortcut": "افزودن میانبر",
|
"collectionActionAddShortcut": "افزودن میانبر",
|
||||||
"@collectionActionAddShortcut": {},
|
"@collectionActionAddShortcut": {},
|
||||||
|
@ -1293,7 +1293,7 @@
|
||||||
"@settingsCollectionBurstPatternsTile": {},
|
"@settingsCollectionBurstPatternsTile": {},
|
||||||
"settingsCollectionBurstPatternsNone": "هیچکدام",
|
"settingsCollectionBurstPatternsNone": "هیچکدام",
|
||||||
"@settingsCollectionBurstPatternsNone": {},
|
"@settingsCollectionBurstPatternsNone": {},
|
||||||
"settingsCollectionQuickActionsTile": "کنش سریع",
|
"settingsCollectionQuickActionsTile": "کنش های سریع",
|
||||||
"@settingsCollectionQuickActionsTile": {},
|
"@settingsCollectionQuickActionsTile": {},
|
||||||
"settingsUnitSystemTile": "واحد ها",
|
"settingsUnitSystemTile": "واحد ها",
|
||||||
"@settingsUnitSystemTile": {},
|
"@settingsUnitSystemTile": {},
|
||||||
|
@ -1315,9 +1315,9 @@
|
||||||
"@settingsViewerSectionTitle": {},
|
"@settingsViewerSectionTitle": {},
|
||||||
"settingsViewerShowInformationSubtitle": "نمایش عنوان، تاریخ، مکان، و...",
|
"settingsViewerShowInformationSubtitle": "نمایش عنوان، تاریخ، مکان، و...",
|
||||||
"@settingsViewerShowInformationSubtitle": {},
|
"@settingsViewerShowInformationSubtitle": {},
|
||||||
"settingsViewerQuickActionsTile": "کنش های سزیع",
|
"settingsViewerQuickActionsTile": "کنش های سریع",
|
||||||
"@settingsViewerQuickActionsTile": {},
|
"@settingsViewerQuickActionsTile": {},
|
||||||
"settingsViewerQuickActionEditorPageTitle": "کنش های سزیع",
|
"settingsViewerQuickActionEditorPageTitle": "کنش های سریع",
|
||||||
"@settingsViewerQuickActionEditorPageTitle": {},
|
"@settingsViewerQuickActionEditorPageTitle": {},
|
||||||
"settingsViewerQuickActionEditorBanner": "لمس کنید و نگه دارید تا دکمه ها را حرکت دهید و انتخاب کنید که کدام کنش ها در بیننده نمایش داده می شود.",
|
"settingsViewerQuickActionEditorBanner": "لمس کنید و نگه دارید تا دکمه ها را حرکت دهید و انتخاب کنید که کدام کنش ها در بیننده نمایش داده می شود.",
|
||||||
"@settingsViewerQuickActionEditorBanner": {},
|
"@settingsViewerQuickActionEditorBanner": {},
|
||||||
|
@ -1440,5 +1440,103 @@
|
||||||
"settingsDisplayRefreshRateModeTile": "نمایش نرخ تازهسازی",
|
"settingsDisplayRefreshRateModeTile": "نمایش نرخ تازهسازی",
|
||||||
"@settingsDisplayRefreshRateModeTile": {},
|
"@settingsDisplayRefreshRateModeTile": {},
|
||||||
"settingsSubtitleThemeShowOutline": "نمایش نوار حاشیه و سایه",
|
"settingsSubtitleThemeShowOutline": "نمایش نوار حاشیه و سایه",
|
||||||
"@settingsSubtitleThemeShowOutline": {}
|
"@settingsSubtitleThemeShowOutline": {},
|
||||||
|
"collectionCopySuccessFeedback": "{count, plural, =1{۱ مورد رونوشت شد} other{{count} مورد رونوشت شد}}",
|
||||||
|
"@collectionCopySuccessFeedback": {
|
||||||
|
"placeholders": {
|
||||||
|
"count": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"statsWithGps": "{count, plural, =1{1 مورد دارای مکان} other{{count} مورد دارای مکان}}",
|
||||||
|
"@statsWithGps": {
|
||||||
|
"placeholders": {
|
||||||
|
"count": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"editEntryDateDialogShift": "جابهجایی",
|
||||||
|
"@editEntryDateDialogShift": {},
|
||||||
|
"collectionDeleteFailureFeedback": "{count, plural, =1{پاککردن ۱ مورد ناموفق بود} other{پاککردن {count} مورد ناموفق بود}}",
|
||||||
|
"@collectionDeleteFailureFeedback": {
|
||||||
|
"placeholders": {
|
||||||
|
"count": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"settingsDisablingBinWarningDialogMessage": "موارد موجود در سطل زباله برای همیشه نابود خواهند شد.",
|
||||||
|
"@settingsDisablingBinWarningDialogMessage": {},
|
||||||
|
"settingsAllowInstalledAppAccessSubtitle": "برای بهبود نمایش آلبوم بهرهوری میشود",
|
||||||
|
"@settingsAllowInstalledAppAccessSubtitle": {},
|
||||||
|
"settingsHiddenPathsBanner": "تصاویر و ویدیوهای موجود در این پوشهها یا هر یک از زیرپوشههای آنها در مجموعه شما دیده نمیشوند.",
|
||||||
|
"@settingsHiddenPathsBanner": {},
|
||||||
|
"settingsStorageAccessBanner": "برخی پوشه ها برای اصلاح پرونپه های موجود در آنها به یک مجوز دسترسی نیاز دارند. در اینجا می توانید پوشه هایی را که قبلاً به آنها دسترسی داشته اید، مرور کنید.",
|
||||||
|
"@settingsStorageAccessBanner": {},
|
||||||
|
"collectionMoveFailureFeedback": "{count, plural, =1{هدایت ۱ مورد ناموفق بود} other{هدایت {count} مورد ناموفق بود}}",
|
||||||
|
"@collectionMoveFailureFeedback": {
|
||||||
|
"placeholders": {
|
||||||
|
"count": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"collectionRenameFailureFeedback": "{count, plural, =1{تغییرنام ۱ مورد ناموفق بود} other{تغییرنام {count} مورد ناموفق بود}}",
|
||||||
|
"@collectionRenameFailureFeedback": {
|
||||||
|
"placeholders": {
|
||||||
|
"count": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"aboutCreditsWorldAtlas1": "این برنامه یک پرونده TopoJSON استفاده میکند از",
|
||||||
|
"@aboutCreditsWorldAtlas1": {},
|
||||||
|
"collectionCopyFailureFeedback": "{count, plural, =1{رونوشت ۱ مورد ناموفق بود} other{رونوشت {count} مورد ناموفق بود}}",
|
||||||
|
"@collectionCopyFailureFeedback": {
|
||||||
|
"placeholders": {
|
||||||
|
"count": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"collectionMoveSuccessFeedback": "{count, plural, =1{۱ مورد هدایت شد} other{{count} مورد هدایت شد}}",
|
||||||
|
"@collectionMoveSuccessFeedback": {
|
||||||
|
"placeholders": {
|
||||||
|
"count": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"collectionRenameSuccessFeedback": "{count, plural, =1{۱ مورد تغییرنام یافت} other{{count} مورد تغییرنام یافت}}",
|
||||||
|
"@collectionRenameSuccessFeedback": {
|
||||||
|
"placeholders": {
|
||||||
|
"count": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"collectionEditSuccessFeedback": "{count, plural, =1{۱ مورد ویرایش شد} other{{count} مورد ویرایش شد}}",
|
||||||
|
"@collectionEditSuccessFeedback": {
|
||||||
|
"placeholders": {
|
||||||
|
"count": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"settingsViewerUseCutout": "ناحیه برش را بکار بگیر",
|
||||||
|
"@settingsViewerUseCutout": {},
|
||||||
|
"settingsViewerShowHistogram": "نمایش نمودار",
|
||||||
|
"@settingsViewerShowHistogram": {},
|
||||||
|
"settingsVideoGestureVerticalDragBrightnessVolume": "برای تنظیم نور/صدا به بالا و پایین بکشید",
|
||||||
|
"@settingsVideoGestureVerticalDragBrightnessVolume": {},
|
||||||
|
"mapEmptyRegion": "تصویری در این ناحیه وجود ندارد",
|
||||||
|
"@mapEmptyRegion": {},
|
||||||
|
"mapAttributionOsmHot": "دادههای نقشه © [OpenStreetMap](https:www.openstreetmap.orgcopyright) مشارکتکنندگان • کاشی ها توسط [HOT](https:www.hotosm.org) • میزبانی شده به دست [OSM France](https:openstreetmap.fr)",
|
||||||
|
"@mapAttributionOsmHot": {},
|
||||||
|
"mapAttributionStamen": "دادههای نقشه © [OpenStreetMap](https:www.openstreetmap.org/copyright) مشارکتکنندگان • کاشی ها بدست [Stamen Design](https:stamen.com)، [CC BY 3.0](https:creativecommons.orglicensesby3.0)",
|
||||||
|
"@mapAttributionStamen": {},
|
||||||
|
"addShortcutButtonLabel": "افزودن",
|
||||||
|
"@addShortcutButtonLabel": {},
|
||||||
|
"aboutBugReportInstruction": "در گیتهاب با گزارش ها و ریزگان دستگاه گزارش کنید",
|
||||||
|
"@aboutBugReportInstruction": {},
|
||||||
|
"settingsViewerShowShootingDetails": "نمایش ریزگان تصویربرداری",
|
||||||
|
"@settingsViewerShowShootingDetails": {},
|
||||||
|
"settingsHiddenFiltersBanner": "تصاویر و ویدیوهایی که با پالایشهای مخفی سازگار نیستند در مجموعه شما دیده نمیشوند.",
|
||||||
|
"@settingsHiddenFiltersBanner": {},
|
||||||
|
"moveUndatedConfirmationDialogMessage": "پیش از ادامه دادن تاریخ موارد نگهداری شود؟",
|
||||||
|
"@moveUndatedConfirmationDialogMessage": {},
|
||||||
|
"settingsAllowInstalledAppAccess": "اجازه دسترسی به دارایی برنامه",
|
||||||
|
"@settingsAllowInstalledAppAccess": {},
|
||||||
|
"collectionEditFailureFeedback": "{count, plural, =1{ویرایش ۱ مورد ناموفق بود} other{ویرایش {count} مورد ناموفق بود}}",
|
||||||
|
"@collectionEditFailureFeedback": {
|
||||||
|
"placeholders": {
|
||||||
|
"count": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"chipActionShowCollection": "نمایش در مجموعه",
|
||||||
|
"@chipActionShowCollection": {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -137,7 +137,7 @@
|
||||||
"@viewerActionSettings": {},
|
"@viewerActionSettings": {},
|
||||||
"filterOnThisDayLabel": "Tänä päivänä",
|
"filterOnThisDayLabel": "Tänä päivänä",
|
||||||
"@filterOnThisDayLabel": {},
|
"@filterOnThisDayLabel": {},
|
||||||
"columnCount": "{count, plural, =1{1 sarake} other{{count} saraketta}}",
|
"columnCount": "{count, plural, =1{{count} sarake} other{{count} saraketta}}",
|
||||||
"@columnCount": {
|
"@columnCount": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"count": {}
|
"count": {}
|
||||||
|
@ -149,7 +149,7 @@
|
||||||
"@maxBrightnessNever": {},
|
"@maxBrightnessNever": {},
|
||||||
"videoActionReplay10": "kelaa taaksepäin 10 sekuntia",
|
"videoActionReplay10": "kelaa taaksepäin 10 sekuntia",
|
||||||
"@videoActionReplay10": {},
|
"@videoActionReplay10": {},
|
||||||
"itemCount": "{count, plural, =1{1 kohde} other{{count} kohdetta}}",
|
"itemCount": "{count, plural, =1{{count} kohde} other{{count} kohdetta}}",
|
||||||
"@itemCount": {
|
"@itemCount": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"count": {}
|
"count": {}
|
||||||
|
@ -231,7 +231,7 @@
|
||||||
"@keepScreenOnNever": {},
|
"@keepScreenOnNever": {},
|
||||||
"mapStyleOsmHot": "Humanitaarinen OSM",
|
"mapStyleOsmHot": "Humanitaarinen OSM",
|
||||||
"@mapStyleOsmHot": {},
|
"@mapStyleOsmHot": {},
|
||||||
"timeSeconds": "{seconds, plural, =1{1 sekunti} other{{seconds} sekuntia}}",
|
"timeSeconds": "{count, plural, =1{{count} sekunti} other{{count} sekuntia}}",
|
||||||
"@timeSeconds": {
|
"@timeSeconds": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"seconds": {}
|
"seconds": {}
|
||||||
|
@ -265,7 +265,7 @@
|
||||||
"@entryActionRotateCW": {},
|
"@entryActionRotateCW": {},
|
||||||
"entryActionFlip": "Käännä vaakasuorassa",
|
"entryActionFlip": "Käännä vaakasuorassa",
|
||||||
"@entryActionFlip": {},
|
"@entryActionFlip": {},
|
||||||
"timeDays": "{days, plural, =1{1 Päivä} other{{days} Päivää}}",
|
"timeDays": "{count, plural, =1{{count} Päivä} other{{count} Päivää}}",
|
||||||
"@timeDays": {
|
"@timeDays": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"days": {}
|
"days": {}
|
||||||
|
@ -279,7 +279,7 @@
|
||||||
"@entryActionEdit": {},
|
"@entryActionEdit": {},
|
||||||
"entryInfoActionEditRating": "Muokkaa luokitusta",
|
"entryInfoActionEditRating": "Muokkaa luokitusta",
|
||||||
"@entryInfoActionEditRating": {},
|
"@entryInfoActionEditRating": {},
|
||||||
"timeMinutes": "{minutes, plural, =1{1 minuutti} other{{minutes} minuuttia}}",
|
"timeMinutes": "{count, plural, =1{{count} minuutti} other{{count} minuuttia}}",
|
||||||
"@timeMinutes": {
|
"@timeMinutes": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"minutes": {}
|
"minutes": {}
|
||||||
|
@ -300,5 +300,7 @@
|
||||||
"entryActionShareImageOnly": "Jaa vain kuva",
|
"entryActionShareImageOnly": "Jaa vain kuva",
|
||||||
"@entryActionShareImageOnly": {},
|
"@entryActionShareImageOnly": {},
|
||||||
"filterNoDateLabel": "Päiväämätön",
|
"filterNoDateLabel": "Päiväämätön",
|
||||||
"@filterNoDateLabel": {}
|
"@filterNoDateLabel": {},
|
||||||
|
"chipActionShowCollection": "Näytä kokoelmassa",
|
||||||
|
"@chipActionShowCollection": {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,13 +7,13 @@
|
||||||
"@welcomeOptional": {},
|
"@welcomeOptional": {},
|
||||||
"welcomeTermsToggle": "J’accepte les conditions d’utilisation",
|
"welcomeTermsToggle": "J’accepte les conditions d’utilisation",
|
||||||
"@welcomeTermsToggle": {},
|
"@welcomeTermsToggle": {},
|
||||||
"itemCount": "{count, plural, =1{1 élément} other{{count} éléments}}",
|
"itemCount": "{count, plural, =1{{count} élément} other{{count} éléments}}",
|
||||||
"@itemCount": {},
|
"@itemCount": {},
|
||||||
"timeSeconds": "{seconds, plural, =0{0 seconde} =1{1 seconde} other{{seconds} secondes}}",
|
"timeSeconds": "{count, plural, =0{{count} seconde} =1{{count} seconde} other{{count} secondes}}",
|
||||||
"@timeSeconds": {},
|
"@timeSeconds": {},
|
||||||
"timeMinutes": "{minutes, plural, =0{0 minute} =1{1 minute} other{{minutes} minutes}}",
|
"timeMinutes": "{count, plural, =0{{count} minute} =1{{count} minute} other{{count} minutes}}",
|
||||||
"@timeMinutes": {},
|
"@timeMinutes": {},
|
||||||
"timeDays": "{days, plural, =0{0 jour} =1{1 jour} other{{days} jours}}",
|
"timeDays": "{count, plural, =0{{count} jour} =1{{count} jour} other{{count} jours}}",
|
||||||
"@timeDays": {},
|
"@timeDays": {},
|
||||||
"focalLength": "{length} mm",
|
"focalLength": "{length} mm",
|
||||||
"@focalLength": {},
|
"@focalLength": {},
|
||||||
|
@ -1185,7 +1185,7 @@
|
||||||
"@entryInfoActionRemoveLocation": {},
|
"@entryInfoActionRemoveLocation": {},
|
||||||
"keepScreenOnVideoPlayback": "Pendant la lecture de vidéos",
|
"keepScreenOnVideoPlayback": "Pendant la lecture de vidéos",
|
||||||
"@keepScreenOnVideoPlayback": {},
|
"@keepScreenOnVideoPlayback": {},
|
||||||
"columnCount": "{count, plural, =1{1 colonne} other{{count} colonnes}}",
|
"columnCount": "{count, plural, =1{{count} colonne} other{{count} colonnes}}",
|
||||||
"@columnCount": {
|
"@columnCount": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"count": {}
|
"count": {}
|
||||||
|
@ -1378,5 +1378,7 @@
|
||||||
"renameProcessorHash": "Hash",
|
"renameProcessorHash": "Hash",
|
||||||
"@renameProcessorHash": {},
|
"@renameProcessorHash": {},
|
||||||
"settingsForceWesternArabicNumeralsTile": "Toujours utiliser les chiffres arabes",
|
"settingsForceWesternArabicNumeralsTile": "Toujours utiliser les chiffres arabes",
|
||||||
"@settingsForceWesternArabicNumeralsTile": {}
|
"@settingsForceWesternArabicNumeralsTile": {},
|
||||||
|
"chipActionShowCollection": "Afficher dans Collection",
|
||||||
|
"@chipActionShowCollection": {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -177,25 +177,25 @@
|
||||||
"@appName": {},
|
"@appName": {},
|
||||||
"welcomeMessage": "Benvido a Aves",
|
"welcomeMessage": "Benvido a Aves",
|
||||||
"@welcomeMessage": {},
|
"@welcomeMessage": {},
|
||||||
"itemCount": "{count, plural, =1{1 elementos} other{{count} elementos}}",
|
"itemCount": "{count, plural, =1{{count} elementos} other{{count} elementos}}",
|
||||||
"@itemCount": {
|
"@itemCount": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"count": {}
|
"count": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"timeSeconds": "{seconds, plural, =1{1 segundo} other{{seconds} segundos}}",
|
"timeSeconds": "{count, plural, =1{{count} segundo} other{{count} segundos}}",
|
||||||
"@timeSeconds": {
|
"@timeSeconds": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"seconds": {}
|
"seconds": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"timeMinutes": "{minutes, plural, =1{1 minuto} other{{minutes} minutos}}",
|
"timeMinutes": "{count, plural, =1{{count} minuto} other{{count} minutos}}",
|
||||||
"@timeMinutes": {
|
"@timeMinutes": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"minutes": {}
|
"minutes": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"timeDays": "{days, plural, =1{1 día} other{{days} días}}",
|
"timeDays": "{count, plural, =1{{count} día} other{{count} días}}",
|
||||||
"@timeDays": {
|
"@timeDays": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"days": {}
|
"days": {}
|
||||||
|
@ -296,5 +296,7 @@
|
||||||
"mapStyleHuaweiTerrain": "Petal Maps (Terreo)",
|
"mapStyleHuaweiTerrain": "Petal Maps (Terreo)",
|
||||||
"@mapStyleHuaweiTerrain": {},
|
"@mapStyleHuaweiTerrain": {},
|
||||||
"mapStyleOsmHot": "Humanitarian OpenStreetMap Team",
|
"mapStyleOsmHot": "Humanitarian OpenStreetMap Team",
|
||||||
"@mapStyleOsmHot": {}
|
"@mapStyleOsmHot": {},
|
||||||
|
"chipActionShowCollection": "Mostrar na colección",
|
||||||
|
"@chipActionShowCollection": {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,19 +3,19 @@
|
||||||
"@welcomeOptional": {},
|
"@welcomeOptional": {},
|
||||||
"welcomeTermsToggle": "मैं नियमों और शर्तों पर सहमत हुं",
|
"welcomeTermsToggle": "मैं नियमों और शर्तों पर सहमत हुं",
|
||||||
"@welcomeTermsToggle": {},
|
"@welcomeTermsToggle": {},
|
||||||
"columnCount": "{count, plural, =1{१ कॉलम} other{{count} कॉलम}}",
|
"columnCount": "{count, plural, other{{count} कॉलम}}",
|
||||||
"@columnCount": {
|
"@columnCount": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"count": {}
|
"count": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"timeSeconds": "{seconds, plural, =1{ १ सेकंड} other{{seconds} सेकंडस}}",
|
"timeSeconds": "{count, plural, =1{{count} सेकंड} other{{count} सेकंडस}}",
|
||||||
"@timeSeconds": {
|
"@timeSeconds": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"seconds": {}
|
"seconds": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"timeDays": "{days, plural, =1{ १ दिन} other{{days} दिन}}",
|
"timeDays": "{count, plural, other{{count} दिन}}",
|
||||||
"@timeDays": {
|
"@timeDays": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"days": {}
|
"days": {}
|
||||||
|
@ -35,7 +35,7 @@
|
||||||
"@clearTooltip": {},
|
"@clearTooltip": {},
|
||||||
"actionRemove": "हटाएं",
|
"actionRemove": "हटाएं",
|
||||||
"@actionRemove": {},
|
"@actionRemove": {},
|
||||||
"itemCount": "{count, plural, =1{१ चीज} other{{count} चीजे}}",
|
"itemCount": "{count, plural, =1{{count} चीज} other{{count} चीजे}}",
|
||||||
"@itemCount": {
|
"@itemCount": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"count": {}
|
"count": {}
|
||||||
|
@ -43,7 +43,7 @@
|
||||||
},
|
},
|
||||||
"deleteButtonLabel": "डिलीट",
|
"deleteButtonLabel": "डिलीट",
|
||||||
"@deleteButtonLabel": {},
|
"@deleteButtonLabel": {},
|
||||||
"timeMinutes": "{minutes, plural, =1{ १ मिनट} other{{minutes} मिनट}}",
|
"timeMinutes": "{count, plural, other{{count} मिनट}}",
|
||||||
"@timeMinutes": {
|
"@timeMinutes": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"minutes": {}
|
"minutes": {}
|
||||||
|
|
|
@ -811,7 +811,7 @@
|
||||||
"@widgetOpenPageCollection": {},
|
"@widgetOpenPageCollection": {},
|
||||||
"renameEntrySetPageInsertTooltip": "Mező beszúrása",
|
"renameEntrySetPageInsertTooltip": "Mező beszúrása",
|
||||||
"@renameEntrySetPageInsertTooltip": {},
|
"@renameEntrySetPageInsertTooltip": {},
|
||||||
"timeDays": "{days, plural, other{{days} nap}}",
|
"timeDays": "{count, plural, other{{count} nap}}",
|
||||||
"@timeDays": {
|
"@timeDays": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"days": {}
|
"days": {}
|
||||||
|
@ -829,13 +829,13 @@
|
||||||
"count": {}
|
"count": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"timeSeconds": "{seconds, plural, other{{seconds} másodperc}}",
|
"timeSeconds": "{count, plural, other{{count} másodperc}}",
|
||||||
"@timeSeconds": {
|
"@timeSeconds": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"seconds": {}
|
"seconds": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"timeMinutes": "{minutes, plural, other{{minutes} perc}}",
|
"timeMinutes": "{count, plural, other{{count} perc}}",
|
||||||
"@timeMinutes": {
|
"@timeMinutes": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"minutes": {}
|
"minutes": {}
|
||||||
|
@ -1532,5 +1532,7 @@
|
||||||
"videoActionABRepeat": "A-B ismétlés",
|
"videoActionABRepeat": "A-B ismétlés",
|
||||||
"@videoActionABRepeat": {},
|
"@videoActionABRepeat": {},
|
||||||
"videoRepeatActionSetEnd": "Végpont beállítása",
|
"videoRepeatActionSetEnd": "Végpont beállítása",
|
||||||
"@videoRepeatActionSetEnd": {}
|
"@videoRepeatActionSetEnd": {},
|
||||||
|
"chipActionShowCollection": "Megjelenítés a gyűjteményekben",
|
||||||
|
"@chipActionShowCollection": {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,11 +9,11 @@
|
||||||
"@welcomeTermsToggle": {},
|
"@welcomeTermsToggle": {},
|
||||||
"itemCount": "{count, plural, other{{count} benda}}",
|
"itemCount": "{count, plural, other{{count} benda}}",
|
||||||
"@itemCount": {},
|
"@itemCount": {},
|
||||||
"timeSeconds": "{seconds, plural, other{{seconds} detik}}",
|
"timeSeconds": "{count, plural, other{{count} detik}}",
|
||||||
"@timeSeconds": {},
|
"@timeSeconds": {},
|
||||||
"timeMinutes": "{minutes, plural, other{{minutes} menit}}",
|
"timeMinutes": "{count, plural, other{{count} menit}}",
|
||||||
"@timeMinutes": {},
|
"@timeMinutes": {},
|
||||||
"timeDays": "{days, plural, other{{days} hari}}",
|
"timeDays": "{count, plural, other{{count} hari}}",
|
||||||
"@timeDays": {},
|
"@timeDays": {},
|
||||||
"focalLength": "{length} mm",
|
"focalLength": "{length} mm",
|
||||||
"@focalLength": {},
|
"@focalLength": {},
|
||||||
|
@ -1378,5 +1378,7 @@
|
||||||
"settingsForceWesternArabicNumeralsTile": "Paksa angka Arab",
|
"settingsForceWesternArabicNumeralsTile": "Paksa angka Arab",
|
||||||
"@settingsForceWesternArabicNumeralsTile": {},
|
"@settingsForceWesternArabicNumeralsTile": {},
|
||||||
"renameProcessorHash": "Hash",
|
"renameProcessorHash": "Hash",
|
||||||
"@renameProcessorHash": {}
|
"@renameProcessorHash": {},
|
||||||
|
"chipActionShowCollection": "Tampilkan di Koleksi",
|
||||||
|
"@chipActionShowCollection": {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -782,7 +782,7 @@
|
||||||
"@placePageTitle": {},
|
"@placePageTitle": {},
|
||||||
"filterOnThisDayLabel": "Á þessum degi",
|
"filterOnThisDayLabel": "Á þessum degi",
|
||||||
"@filterOnThisDayLabel": {},
|
"@filterOnThisDayLabel": {},
|
||||||
"columnCount": "{count, plural, =1{1 dálkur} other{{count} dálkar}}",
|
"columnCount": "{count, plural, =1{{count} dálkur} other{{count} dálkar}}",
|
||||||
"@columnCount": {
|
"@columnCount": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"count": {}
|
"count": {}
|
||||||
|
@ -840,7 +840,7 @@
|
||||||
"@albumMimeTypeMixed": {},
|
"@albumMimeTypeMixed": {},
|
||||||
"settingsViewerQuickActionEditorAvailableButtonsSectionTitle": "Tiltækir hnappar",
|
"settingsViewerQuickActionEditorAvailableButtonsSectionTitle": "Tiltækir hnappar",
|
||||||
"@settingsViewerQuickActionEditorAvailableButtonsSectionTitle": {},
|
"@settingsViewerQuickActionEditorAvailableButtonsSectionTitle": {},
|
||||||
"itemCount": "{count, plural, =1{1 atriði} other{{count} atriðum}}",
|
"itemCount": "{count, plural, =1{{count} atriði} other{{count} atriðum}}",
|
||||||
"@itemCount": {
|
"@itemCount": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"count": {}
|
"count": {}
|
||||||
|
@ -1136,7 +1136,7 @@
|
||||||
"@drawerCollectionImages": {},
|
"@drawerCollectionImages": {},
|
||||||
"sortOrderSmallestFirst": "Minnsta fyrst",
|
"sortOrderSmallestFirst": "Minnsta fyrst",
|
||||||
"@sortOrderSmallestFirst": {},
|
"@sortOrderSmallestFirst": {},
|
||||||
"timeSeconds": "{seconds, plural, =1{1 sekúnda} other{{seconds} sekúndur}}",
|
"timeSeconds": "{count, plural, =1{{count} sekúnda} other{{count} sekúndur}}",
|
||||||
"@timeSeconds": {
|
"@timeSeconds": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"seconds": {}
|
"seconds": {}
|
||||||
|
@ -1292,7 +1292,7 @@
|
||||||
"@subtitlePositionBottom": {},
|
"@subtitlePositionBottom": {},
|
||||||
"castDialogTitle": "Útvörpunartæki",
|
"castDialogTitle": "Útvörpunartæki",
|
||||||
"@castDialogTitle": {},
|
"@castDialogTitle": {},
|
||||||
"timeDays": "{days, plural, =1{1 dagur} other{{days} dagar}}",
|
"timeDays": "{count, plural, =1{{count} dagur} other{{count} dagar}}",
|
||||||
"@timeDays": {
|
"@timeDays": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"days": {}
|
"days": {}
|
||||||
|
@ -1322,7 +1322,7 @@
|
||||||
"@entryActionEdit": {},
|
"@entryActionEdit": {},
|
||||||
"entryInfoActionEditRating": "Breyta einkunn",
|
"entryInfoActionEditRating": "Breyta einkunn",
|
||||||
"@entryInfoActionEditRating": {},
|
"@entryInfoActionEditRating": {},
|
||||||
"timeMinutes": "{minutes, plural, =1{1 mínúta} other{{minutes} mínútur}}",
|
"timeMinutes": "{count, plural, =1{{count} mínúta} other{{count} mínútur}}",
|
||||||
"@timeMinutes": {
|
"@timeMinutes": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"minutes": {}
|
"minutes": {}
|
||||||
|
@ -1536,5 +1536,7 @@
|
||||||
"videoActionABRepeat": "Endurtekning A-B",
|
"videoActionABRepeat": "Endurtekning A-B",
|
||||||
"@videoActionABRepeat": {},
|
"@videoActionABRepeat": {},
|
||||||
"videoRepeatActionSetEnd": "Stilla endi",
|
"videoRepeatActionSetEnd": "Stilla endi",
|
||||||
"@videoRepeatActionSetEnd": {}
|
"@videoRepeatActionSetEnd": {},
|
||||||
|
"chipActionShowCollection": "Sýna í safni",
|
||||||
|
"@chipActionShowCollection": {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,13 +7,13 @@
|
||||||
"@welcomeOptional": {},
|
"@welcomeOptional": {},
|
||||||
"welcomeTermsToggle": "Accetto i termini e le condizioni",
|
"welcomeTermsToggle": "Accetto i termini e le condizioni",
|
||||||
"@welcomeTermsToggle": {},
|
"@welcomeTermsToggle": {},
|
||||||
"itemCount": "{count, plural, =1{1 elemento} other{{count} elementi}}",
|
"itemCount": "{count, plural, =1{{count} elemento} other{{count} elementi}}",
|
||||||
"@itemCount": {},
|
"@itemCount": {},
|
||||||
"timeSeconds": "{seconds, plural, =1{1 secondo} other{{seconds} secondi}}",
|
"timeSeconds": "{count, plural, =1{{count} secondo} other{{count} secondi}}",
|
||||||
"@timeSeconds": {},
|
"@timeSeconds": {},
|
||||||
"timeMinutes": "{minutes, plural, =1{1 minuto} other{{minutes} minuti}}",
|
"timeMinutes": "{count, plural, =1{{count} minuto} other{{count} minuti}}",
|
||||||
"@timeMinutes": {},
|
"@timeMinutes": {},
|
||||||
"timeDays": "{days, plural, =1{1 giorno} other{{days} giorni}}",
|
"timeDays": "{count, plural, =1{{count} giorno} other{{count} giorni}}",
|
||||||
"@timeDays": {},
|
"@timeDays": {},
|
||||||
"focalLength": "{length} mm",
|
"focalLength": "{length} mm",
|
||||||
"@focalLength": {},
|
"@focalLength": {},
|
||||||
|
@ -1171,7 +1171,7 @@
|
||||||
"@settingsWidgetDisplayedItem": {},
|
"@settingsWidgetDisplayedItem": {},
|
||||||
"settingsViewerShowRatingTags": "Mostra valutazione & etichette",
|
"settingsViewerShowRatingTags": "Mostra valutazione & etichette",
|
||||||
"@settingsViewerShowRatingTags": {},
|
"@settingsViewerShowRatingTags": {},
|
||||||
"columnCount": "{count, plural, =1{1 colonna} other{{count} colonne}}",
|
"columnCount": "{count, plural, =1{{count} colonna} other{{count} colonne}}",
|
||||||
"@columnCount": {
|
"@columnCount": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"count": {}
|
"count": {}
|
||||||
|
@ -1374,5 +1374,11 @@
|
||||||
"collectionActionSetHome": "Imposta come pagina iniziale",
|
"collectionActionSetHome": "Imposta come pagina iniziale",
|
||||||
"@collectionActionSetHome": {},
|
"@collectionActionSetHome": {},
|
||||||
"setHomeCustomCollection": "Collezione personalizzata",
|
"setHomeCustomCollection": "Collezione personalizzata",
|
||||||
"@setHomeCustomCollection": {}
|
"@setHomeCustomCollection": {},
|
||||||
|
"chipActionShowCollection": "Mostra nella Collezione",
|
||||||
|
"@chipActionShowCollection": {},
|
||||||
|
"renameProcessorHash": "Hash",
|
||||||
|
"@renameProcessorHash": {},
|
||||||
|
"settingsForceWesternArabicNumeralsTile": "Forza numeri arabi",
|
||||||
|
"@settingsForceWesternArabicNumeralsTile": {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,11 +9,11 @@
|
||||||
"@welcomeTermsToggle": {},
|
"@welcomeTermsToggle": {},
|
||||||
"itemCount": "{count, plural, other{{count} 件のアイテム}}",
|
"itemCount": "{count, plural, other{{count} 件のアイテム}}",
|
||||||
"@itemCount": {},
|
"@itemCount": {},
|
||||||
"timeSeconds": "{seconds, plural, other{{seconds} 秒}}",
|
"timeSeconds": "{count, plural, other{{count} 秒}}",
|
||||||
"@timeSeconds": {},
|
"@timeSeconds": {},
|
||||||
"timeMinutes": "{minutes, plural, other{{minutes} 分}}",
|
"timeMinutes": "{count, plural, other{{count} 分}}",
|
||||||
"@timeMinutes": {},
|
"@timeMinutes": {},
|
||||||
"timeDays": "{days, plural, other{{days} 日}}",
|
"timeDays": "{count, plural, other{{count} 日}}",
|
||||||
"@timeDays": {},
|
"@timeDays": {},
|
||||||
"focalLength": "{length} mm",
|
"focalLength": "{length} mm",
|
||||||
"@focalLength": {},
|
"@focalLength": {},
|
||||||
|
@ -1264,5 +1264,117 @@
|
||||||
"settingsVideoBackgroundModeDialogTitle": "バックグラウンド再生",
|
"settingsVideoBackgroundModeDialogTitle": "バックグラウンド再生",
|
||||||
"@settingsVideoBackgroundModeDialogTitle": {},
|
"@settingsVideoBackgroundModeDialogTitle": {},
|
||||||
"maxBrightnessAlways": "常時有効",
|
"maxBrightnessAlways": "常時有効",
|
||||||
"@maxBrightnessAlways": {}
|
"@maxBrightnessAlways": {},
|
||||||
|
"chipActionShowCollection": "コレクションで表示",
|
||||||
|
"@chipActionShowCollection": {},
|
||||||
|
"aboutDataUsageData": "データ",
|
||||||
|
"@aboutDataUsageData": {},
|
||||||
|
"searchStatesSectionTitle": "地域",
|
||||||
|
"@searchStatesSectionTitle": {},
|
||||||
|
"settingsViewerShowDescription": "説明を表示",
|
||||||
|
"@settingsViewerShowDescription": {},
|
||||||
|
"chipActionConfigureVault": "保管庫を設定",
|
||||||
|
"@chipActionConfigureVault": {},
|
||||||
|
"videoActionABRepeat": "A-B リピート",
|
||||||
|
"@videoActionABRepeat": {},
|
||||||
|
"videoRepeatActionSetStart": "開始点を設定",
|
||||||
|
"@videoRepeatActionSetStart": {},
|
||||||
|
"videoRepeatActionSetEnd": "終点を設定",
|
||||||
|
"@videoRepeatActionSetEnd": {},
|
||||||
|
"cropAspectRatioSquare": "正方形",
|
||||||
|
"@cropAspectRatioSquare": {},
|
||||||
|
"filterTaggedLabel": "タグ付き",
|
||||||
|
"@filterTaggedLabel": {},
|
||||||
|
"albumTierVaults": "保管庫",
|
||||||
|
"@albumTierVaults": {},
|
||||||
|
"overlayHistogramRGB": "RGB",
|
||||||
|
"@overlayHistogramRGB": {},
|
||||||
|
"subtitlePositionBottom": "下",
|
||||||
|
"@subtitlePositionBottom": {},
|
||||||
|
"statsTopStatesSectionTitle": "トップ地域",
|
||||||
|
"@statsTopStatesSectionTitle": {},
|
||||||
|
"applyTooltip": "適用する",
|
||||||
|
"@applyTooltip": {},
|
||||||
|
"viewerActionUnlock": "ビューをアンロック",
|
||||||
|
"@viewerActionUnlock": {},
|
||||||
|
"editorActionTransform": "変換",
|
||||||
|
"@editorActionTransform": {},
|
||||||
|
"settingsVideoPlaybackPageTitle": "再生",
|
||||||
|
"@settingsVideoPlaybackPageTitle": {},
|
||||||
|
"editorTransformCrop": "切り取り",
|
||||||
|
"@editorTransformCrop": {},
|
||||||
|
"exportEntryDialogWriteMetadata": "メタデータを書き込む",
|
||||||
|
"@exportEntryDialogWriteMetadata": {},
|
||||||
|
"videoResumptionModeNever": "無効",
|
||||||
|
"@videoResumptionModeNever": {},
|
||||||
|
"aboutDataUsageSectionTitle": "データ使用量",
|
||||||
|
"@aboutDataUsageSectionTitle": {},
|
||||||
|
"videoResumptionModeAlways": "常にオン",
|
||||||
|
"@videoResumptionModeAlways": {},
|
||||||
|
"settingsCollectionBurstPatternsTile": "バーストパターン",
|
||||||
|
"@settingsCollectionBurstPatternsTile": {},
|
||||||
|
"settingsDisplayUseTvInterface": "Android TV インターフェイス",
|
||||||
|
"@settingsDisplayUseTvInterface": {},
|
||||||
|
"tagEditorDiscardDialogMessage": "変更を破棄しますか?",
|
||||||
|
"@tagEditorDiscardDialogMessage": {},
|
||||||
|
"widgetTapUpdateWidget": "ウィジェットを更新",
|
||||||
|
"@widgetTapUpdateWidget": {},
|
||||||
|
"vaultBinUsageDialogMessage": "ゴミ箱を使用している保管庫があります。",
|
||||||
|
"@vaultBinUsageDialogMessage": {},
|
||||||
|
"settingsConfirmationVaultDataLoss": "保管庫のデータ損失警告を表示する",
|
||||||
|
"@settingsConfirmationVaultDataLoss": {},
|
||||||
|
"settingsWidgetDisplayedItem": "表示アイテム",
|
||||||
|
"@settingsWidgetDisplayedItem": {},
|
||||||
|
"renameProcessorHash": "ハッシュ",
|
||||||
|
"@renameProcessorHash": {},
|
||||||
|
"exportEntryDialogQuality": "画質",
|
||||||
|
"@exportEntryDialogQuality": {},
|
||||||
|
"castDialogTitle": "キャストデバイス",
|
||||||
|
"@castDialogTitle": {},
|
||||||
|
"aboutDataUsageCache": "キャッシュ",
|
||||||
|
"@aboutDataUsageCache": {},
|
||||||
|
"aboutDataUsageMisc": "その他",
|
||||||
|
"@aboutDataUsageMisc": {},
|
||||||
|
"aboutDataUsageInternal": "内部ストレージ",
|
||||||
|
"@aboutDataUsageInternal": {},
|
||||||
|
"aboutDataUsageDatabase": "データベース",
|
||||||
|
"@aboutDataUsageDatabase": {},
|
||||||
|
"aboutDataUsageExternal": "外部ストレージ",
|
||||||
|
"@aboutDataUsageExternal": {},
|
||||||
|
"collectionActionSetHome": "ホームに設定",
|
||||||
|
"@collectionActionSetHome": {},
|
||||||
|
"placeEmpty": "場所なし",
|
||||||
|
"@placeEmpty": {},
|
||||||
|
"settingsThumbnailShowHdrIcon": "HDRアイコンを表示",
|
||||||
|
"@settingsThumbnailShowHdrIcon": {},
|
||||||
|
"settingsCollectionBurstPatternsNone": "なし",
|
||||||
|
"@settingsCollectionBurstPatternsNone": {},
|
||||||
|
"settingsVideoPlaybackTile": "再生",
|
||||||
|
"@settingsVideoPlaybackTile": {},
|
||||||
|
"settingsDisablingBinWarningDialogMessage": "ごみ箱の中のアイテムは永久に削除されます。",
|
||||||
|
"@settingsDisablingBinWarningDialogMessage": {},
|
||||||
|
"settingsForceWesternArabicNumeralsTile": "アラビア数字を強制する",
|
||||||
|
"@settingsForceWesternArabicNumeralsTile": {},
|
||||||
|
"overlayHistogramNone": "なし",
|
||||||
|
"@overlayHistogramNone": {},
|
||||||
|
"overlayHistogramLuminance": "明るさ",
|
||||||
|
"@overlayHistogramLuminance": {},
|
||||||
|
"settingsModificationWarningDialogMessage": "他の設定は変更されます。",
|
||||||
|
"@settingsModificationWarningDialogMessage": {},
|
||||||
|
"setHomeCustomCollection": "カスタムコレクション",
|
||||||
|
"@setHomeCustomCollection": {},
|
||||||
|
"settingsAccessibilityShowPinchGestureAlternatives": "マルチタッチジェスチャーの選択肢を表示する",
|
||||||
|
"@settingsAccessibilityShowPinchGestureAlternatives": {},
|
||||||
|
"chipActionCreateVault": "保管庫を作成",
|
||||||
|
"@chipActionCreateVault": {},
|
||||||
|
"aboutDataUsageClearCache": "キャッシュを削除",
|
||||||
|
"@aboutDataUsageClearCache": {},
|
||||||
|
"viewerActionLock": "ビューをロック",
|
||||||
|
"@viewerActionLock": {},
|
||||||
|
"cropAspectRatioFree": "フリー",
|
||||||
|
"@cropAspectRatioFree": {},
|
||||||
|
"cropAspectRatioOriginal": "オリジナル",
|
||||||
|
"@cropAspectRatioOriginal": {},
|
||||||
|
"stopTooltip": "停止",
|
||||||
|
"@stopTooltip": {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,11 +9,11 @@
|
||||||
"@welcomeTermsToggle": {},
|
"@welcomeTermsToggle": {},
|
||||||
"itemCount": "{count, plural, other{{count}개}}",
|
"itemCount": "{count, plural, other{{count}개}}",
|
||||||
"@itemCount": {},
|
"@itemCount": {},
|
||||||
"timeSeconds": "{seconds, plural, other{{seconds}초}}",
|
"timeSeconds": "{count, plural, other{{count}초}}",
|
||||||
"@timeSeconds": {},
|
"@timeSeconds": {},
|
||||||
"timeMinutes": "{minutes, plural, other{{minutes}분}}",
|
"timeMinutes": "{count, plural, other{{count}분}}",
|
||||||
"@timeMinutes": {},
|
"@timeMinutes": {},
|
||||||
"timeDays": "{days, plural, other{{days}일}}",
|
"timeDays": "{count, plural, other{{count}일}}",
|
||||||
"@timeDays": {},
|
"@timeDays": {},
|
||||||
"focalLength": "{length} mm",
|
"focalLength": "{length} mm",
|
||||||
"@focalLength": {},
|
"@focalLength": {},
|
||||||
|
@ -1378,5 +1378,7 @@
|
||||||
"renameProcessorHash": "해시",
|
"renameProcessorHash": "해시",
|
||||||
"@renameProcessorHash": {},
|
"@renameProcessorHash": {},
|
||||||
"settingsForceWesternArabicNumeralsTile": "아라비아 숫자 항상 사용",
|
"settingsForceWesternArabicNumeralsTile": "아라비아 숫자 항상 사용",
|
||||||
"@settingsForceWesternArabicNumeralsTile": {}
|
"@settingsForceWesternArabicNumeralsTile": {},
|
||||||
|
"chipActionShowCollection": "미디어 페이지에서 보기",
|
||||||
|
"@chipActionShowCollection": {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,13 +13,13 @@
|
||||||
"@welcomeOptional": {},
|
"@welcomeOptional": {},
|
||||||
"welcomeTermsToggle": "Sutinku su taisyklėmis ir sąlygomis",
|
"welcomeTermsToggle": "Sutinku su taisyklėmis ir sąlygomis",
|
||||||
"@welcomeTermsToggle": {},
|
"@welcomeTermsToggle": {},
|
||||||
"timeSeconds": "{seconds, plural, =1{1 sekundė} few{{seconds} sekundės} other{{seconds} sekundžių}}",
|
"timeSeconds": "{count, plural, =1{{count} sekundė} few{{count} sekundės} other{{count} sekundžių}}",
|
||||||
"@timeSeconds": {
|
"@timeSeconds": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"seconds": {}
|
"seconds": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"timeDays": "{days, plural, =1{1 diena} few{{days} dienos} other{{days} dienų}}",
|
"timeDays": "{count, plural, =1{{count} diena} few{{count} dienos} other{{count} dienų}}",
|
||||||
"@timeDays": {
|
"@timeDays": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"days": {}
|
"days": {}
|
||||||
|
@ -285,13 +285,13 @@
|
||||||
"@collectionActionEdit": {},
|
"@collectionActionEdit": {},
|
||||||
"welcomeMessage": "Sveiki atvykę į Aves",
|
"welcomeMessage": "Sveiki atvykę į Aves",
|
||||||
"@welcomeMessage": {},
|
"@welcomeMessage": {},
|
||||||
"itemCount": "{count, plural, =1{1 elementas} few{{count} elementai} other{{count} elementų}}",
|
"itemCount": "{count, plural, =1{{count} elementas} few{{count} elementai} other{{count} elementų}}",
|
||||||
"@itemCount": {
|
"@itemCount": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"count": {}
|
"count": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"timeMinutes": "{minutes, plural, =1{1 minutė} few{{minutes} minutės} other{{minutes} minučių}}",
|
"timeMinutes": "{count, plural, =1{{count} minutė} few{{count} minutės} other{{count} minučių}}",
|
||||||
"@timeMinutes": {
|
"@timeMinutes": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"minutes": {}
|
"minutes": {}
|
||||||
|
@ -1340,5 +1340,7 @@
|
||||||
"entryActionShareImageOnly": "Bendrinti tik paveikslėlį",
|
"entryActionShareImageOnly": "Bendrinti tik paveikslėlį",
|
||||||
"@entryActionShareImageOnly": {},
|
"@entryActionShareImageOnly": {},
|
||||||
"entryInfoActionRemoveLocation": "Pašalinti vietą",
|
"entryInfoActionRemoveLocation": "Pašalinti vietą",
|
||||||
"@entryInfoActionRemoveLocation": {}
|
"@entryInfoActionRemoveLocation": {},
|
||||||
|
"chipActionShowCollection": "Rodyti kolekcijoje",
|
||||||
|
"@chipActionShowCollection": {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,19 +23,19 @@
|
||||||
"count": {}
|
"count": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"timeSeconds": "{seconds, plural, other{{seconds} စက္ကန့်}}",
|
"timeSeconds": "{count, plural, other{{count} စက္ကန့်}}",
|
||||||
"@timeSeconds": {
|
"@timeSeconds": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"seconds": {}
|
"seconds": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"timeMinutes": "{minutes, plural, other{{minutes} မိနစ်}}",
|
"timeMinutes": "{count, plural, other{{count} မိနစ်}}",
|
||||||
"@timeMinutes": {
|
"@timeMinutes": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"minutes": {}
|
"minutes": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"timeDays": "{days, plural, other{{days} ရက်}}",
|
"timeDays": "{count, plural, other{{count} ရက်}}",
|
||||||
"@timeDays": {
|
"@timeDays": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"days": {}
|
"days": {}
|
||||||
|
@ -1296,5 +1296,7 @@
|
||||||
"settingsViewerShowHistogram": "Histogram ကို ပြရန်",
|
"settingsViewerShowHistogram": "Histogram ကို ပြရန်",
|
||||||
"@settingsViewerShowHistogram": {},
|
"@settingsViewerShowHistogram": {},
|
||||||
"settingsVideoPlaybackTile": "ဖွင့်ကြည့်ခြင်း",
|
"settingsVideoPlaybackTile": "ဖွင့်ကြည့်ခြင်း",
|
||||||
"@settingsVideoPlaybackTile": {}
|
"@settingsVideoPlaybackTile": {},
|
||||||
|
"chipActionShowCollection": "စုစည်းမှုထဲမှာ ပြရန်",
|
||||||
|
"@chipActionShowCollection": {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -751,25 +751,25 @@
|
||||||
"@settingsConfirmationTile": {},
|
"@settingsConfirmationTile": {},
|
||||||
"settingsThumbnailSectionTitle": "Miniatyrbilder",
|
"settingsThumbnailSectionTitle": "Miniatyrbilder",
|
||||||
"@settingsThumbnailSectionTitle": {},
|
"@settingsThumbnailSectionTitle": {},
|
||||||
"timeMinutes": "{minutes, plural, =1{1 minutt} other{{minutes} minutter}}",
|
"timeMinutes": "{count, plural, =1{{count} minutt} other{{count} minutter}}",
|
||||||
"@timeMinutes": {
|
"@timeMinutes": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"minutes": {}
|
"minutes": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"timeDays": "{days, plural, =1{1 dag} other{{days} dager}}",
|
"timeDays": "{count, plural, =1{{count} dag} other{{count} dager}}",
|
||||||
"@timeDays": {
|
"@timeDays": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"days": {}
|
"days": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"itemCount": "{count, plural, =1{1 element} other{{count} elementer}}",
|
"itemCount": "{count, plural, =1{{count} element} other{{count} elementer}}",
|
||||||
"@itemCount": {
|
"@itemCount": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"count": {}
|
"count": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"timeSeconds": "{seconds, plural, =1{1 sekund} other{{seconds} sekunder}}",
|
"timeSeconds": "{count, plural, =1{{count} sekund} other{{count} sekunder}}",
|
||||||
"@timeSeconds": {
|
"@timeSeconds": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"seconds": {}
|
"seconds": {}
|
||||||
|
@ -1343,7 +1343,7 @@
|
||||||
"@settingsDisplayUseTvInterface": {},
|
"@settingsDisplayUseTvInterface": {},
|
||||||
"settingsAccessibilityShowPinchGestureAlternatives": "Vis multi-trykkhåndvendingsalternativer",
|
"settingsAccessibilityShowPinchGestureAlternatives": "Vis multi-trykkhåndvendingsalternativer",
|
||||||
"@settingsAccessibilityShowPinchGestureAlternatives": {},
|
"@settingsAccessibilityShowPinchGestureAlternatives": {},
|
||||||
"columnCount": "{count, plural, =1{1 kolonne} other{{count} kolonner}}",
|
"columnCount": "{count, plural, =1{{count} kolonne} other{{count} kolonner}}",
|
||||||
"@columnCount": {
|
"@columnCount": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"count": {}
|
"count": {}
|
||||||
|
@ -1478,5 +1478,7 @@
|
||||||
"searchStatesSectionTitle": "Tilstander",
|
"searchStatesSectionTitle": "Tilstander",
|
||||||
"@searchStatesSectionTitle": {},
|
"@searchStatesSectionTitle": {},
|
||||||
"vaultLockTypePattern": "Mønster",
|
"vaultLockTypePattern": "Mønster",
|
||||||
"@vaultLockTypePattern": {}
|
"@vaultLockTypePattern": {},
|
||||||
|
"chipActionShowCollection": "Vis i samling",
|
||||||
|
"@chipActionShowCollection": {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,13 +7,13 @@
|
||||||
"@welcomeOptional": {},
|
"@welcomeOptional": {},
|
||||||
"welcomeTermsToggle": "Ik ga akkoord met de voorwaarden",
|
"welcomeTermsToggle": "Ik ga akkoord met de voorwaarden",
|
||||||
"@welcomeTermsToggle": {},
|
"@welcomeTermsToggle": {},
|
||||||
"itemCount": "{count, plural, =1{1 item} other{{count} items}}",
|
"itemCount": "{count, plural, =1{{count} item} other{{count} items}}",
|
||||||
"@itemCount": {},
|
"@itemCount": {},
|
||||||
"timeSeconds": "{seconds, plural, =1{1 seconde} other{{seconds} seconden}}",
|
"timeSeconds": "{count, plural, =1{{count} seconde} other{{count} seconden}}",
|
||||||
"@timeSeconds": {},
|
"@timeSeconds": {},
|
||||||
"timeMinutes": "{minutes, plural, =1{1 minuut} other{{minutes} minuten}}",
|
"timeMinutes": "{count, plural, =1{{count} minuut} other{{count} minuten}}",
|
||||||
"@timeMinutes": {},
|
"@timeMinutes": {},
|
||||||
"timeDays": "{days, plural, =1{1 dag} other{{days} dagen}}",
|
"timeDays": "{count, plural, =1{{count} dag} other{{count} dagen}}",
|
||||||
"@timeDays": {},
|
"@timeDays": {},
|
||||||
"focalLength": "{length} mm",
|
"focalLength": "{length} mm",
|
||||||
"@focalLength": {},
|
"@focalLength": {},
|
||||||
|
@ -387,7 +387,7 @@
|
||||||
"@renameProcessorName": {},
|
"@renameProcessorName": {},
|
||||||
"deleteSingleAlbumConfirmationDialogMessage": "{count, plural, =1{Verwijder dit album en het item binnen dit album?} other{Verwijder dit album en de {count} items binnen dit album?}}",
|
"deleteSingleAlbumConfirmationDialogMessage": "{count, plural, =1{Verwijder dit album en het item binnen dit album?} other{Verwijder dit album en de {count} items binnen dit album?}}",
|
||||||
"@deleteSingleAlbumConfirmationDialogMessage": {},
|
"@deleteSingleAlbumConfirmationDialogMessage": {},
|
||||||
"deleteMultiAlbumConfirmationDialogMessage": "{count, plural, =1{Verwijder deze albums en het item binnen deze albums?} other{Verwijder dit album en de {count} items binnen deze albums?}}",
|
"deleteMultiAlbumConfirmationDialogMessage": "{count, plural, =1{Verwijder deze albums en het item binnen deze albums?} other{Verwijder deze albums en de {count} items binnen deze albums?}}",
|
||||||
"@deleteMultiAlbumConfirmationDialogMessage": {},
|
"@deleteMultiAlbumConfirmationDialogMessage": {},
|
||||||
"exportEntryDialogFormat": "Formaat:",
|
"exportEntryDialogFormat": "Formaat:",
|
||||||
"@exportEntryDialogFormat": {},
|
"@exportEntryDialogFormat": {},
|
||||||
|
@ -1190,5 +1190,91 @@
|
||||||
"applyTooltip": "Toepassen",
|
"applyTooltip": "Toepassen",
|
||||||
"@applyTooltip": {},
|
"@applyTooltip": {},
|
||||||
"tagPlaceholderState": "Staat",
|
"tagPlaceholderState": "Staat",
|
||||||
"@tagPlaceholderState": {}
|
"@tagPlaceholderState": {},
|
||||||
|
"stopTooltip": "Stop",
|
||||||
|
"@stopTooltip": {},
|
||||||
|
"chipActionLock": "Vergrendel",
|
||||||
|
"@chipActionLock": {},
|
||||||
|
"chipActionShowCountryStates": "Status laten xien",
|
||||||
|
"@chipActionShowCountryStates": {},
|
||||||
|
"chipActionGoToPlacePage": "Laat zien in plaatsen",
|
||||||
|
"@chipActionGoToPlacePage": {},
|
||||||
|
"subtitlePositionTop": "Boven",
|
||||||
|
"@subtitlePositionTop": {},
|
||||||
|
"subtitlePositionBottom": "Onder",
|
||||||
|
"@subtitlePositionBottom": {},
|
||||||
|
"settingsThumbnailShowHdrIcon": "HDR icoon zichtbaar",
|
||||||
|
"@settingsThumbnailShowHdrIcon": {},
|
||||||
|
"editorTransformCrop": "Bijsnijden",
|
||||||
|
"@editorTransformCrop": {},
|
||||||
|
"patternDialogConfirm": "Bevestig patroon",
|
||||||
|
"@patternDialogConfirm": {},
|
||||||
|
"pinDialogEnter": "Voer PIN in",
|
||||||
|
"@pinDialogEnter": {},
|
||||||
|
"settingsAskEverytime": "Vraag elke keer",
|
||||||
|
"@settingsAskEverytime": {},
|
||||||
|
"aboutDataUsageExternal": "Extern",
|
||||||
|
"@aboutDataUsageExternal": {},
|
||||||
|
"tooManyItemsErrorDialogMessage": "Probeer opnieuw met minder items.",
|
||||||
|
"@tooManyItemsErrorDialogMessage": {},
|
||||||
|
"maxBrightnessAlways": "Altijd",
|
||||||
|
"@maxBrightnessAlways": {},
|
||||||
|
"patternDialogEnter": "Voer patroon in",
|
||||||
|
"@patternDialogEnter": {},
|
||||||
|
"settingsViewerShowDescription": "Laat beschrijving zien",
|
||||||
|
"@settingsViewerShowDescription": {},
|
||||||
|
"exportEntryDialogQuality": "Kwaliteit",
|
||||||
|
"@exportEntryDialogQuality": {},
|
||||||
|
"aboutDataUsageDatabase": "Database",
|
||||||
|
"@aboutDataUsageDatabase": {},
|
||||||
|
"aboutDataUsageMisc": "Overig",
|
||||||
|
"@aboutDataUsageMisc": {},
|
||||||
|
"settingsModificationWarningDialogMessage": "Andere instellingen zullen worden aangepast.",
|
||||||
|
"@settingsModificationWarningDialogMessage": {},
|
||||||
|
"vaultDialogLockModeWhenScreenOff": "Vergrendel als scherm uitgaat",
|
||||||
|
"@vaultDialogLockModeWhenScreenOff": {},
|
||||||
|
"aboutDataUsageData": "Data",
|
||||||
|
"@aboutDataUsageData": {},
|
||||||
|
"aboutDataUsageCache": "Cache",
|
||||||
|
"@aboutDataUsageCache": {},
|
||||||
|
"aboutDataUsageInternal": "Intern",
|
||||||
|
"@aboutDataUsageInternal": {},
|
||||||
|
"overlayHistogramRGB": "RGB",
|
||||||
|
"@overlayHistogramRGB": {},
|
||||||
|
"overlayHistogramLuminance": "Helderheid",
|
||||||
|
"@overlayHistogramLuminance": {},
|
||||||
|
"videoResumptionModeNever": "Nooit",
|
||||||
|
"@videoResumptionModeNever": {},
|
||||||
|
"pinDialogConfirm": "Bevestig PIN",
|
||||||
|
"@pinDialogConfirm": {},
|
||||||
|
"passwordDialogEnter": "Voer wachtwoord in",
|
||||||
|
"@passwordDialogEnter": {},
|
||||||
|
"passwordDialogConfirm": "Bevestig wachtwoord",
|
||||||
|
"@passwordDialogConfirm": {},
|
||||||
|
"settingsViewerShowHistogram": "Laat histogram zien",
|
||||||
|
"@settingsViewerShowHistogram": {},
|
||||||
|
"settingsVideoGestureVerticalDragBrightnessVolume": "Veeg omhoog of naar beneden om helderheid/volume aan te passen",
|
||||||
|
"@settingsVideoGestureVerticalDragBrightnessVolume": {},
|
||||||
|
"settingsSubtitleThemeTextPositionTile": "Tekstpositie",
|
||||||
|
"@settingsSubtitleThemeTextPositionTile": {},
|
||||||
|
"settingsSubtitleThemeTextPositionDialogTitle": "Tekstpositie",
|
||||||
|
"@settingsSubtitleThemeTextPositionDialogTitle": {},
|
||||||
|
"vaultLockTypePattern": "Patroon",
|
||||||
|
"@vaultLockTypePattern": {},
|
||||||
|
"entryActionShareImageOnly": "Enkel afbeelding delen",
|
||||||
|
"@entryActionShareImageOnly": {},
|
||||||
|
"entryActionShareVideoOnly": "Enkel video delen",
|
||||||
|
"@entryActionShareVideoOnly": {},
|
||||||
|
"cropAspectRatioOriginal": "Origineel",
|
||||||
|
"@cropAspectRatioOriginal": {},
|
||||||
|
"cropAspectRatioSquare": "Vierkant",
|
||||||
|
"@cropAspectRatioSquare": {},
|
||||||
|
"maxBrightnessNever": "Nooit",
|
||||||
|
"@maxBrightnessNever": {},
|
||||||
|
"videoResumptionModeAlways": "Altijd",
|
||||||
|
"@videoResumptionModeAlways": {},
|
||||||
|
"exportEntryDialogWriteMetadata": "Schrijf metadata",
|
||||||
|
"@exportEntryDialogWriteMetadata": {},
|
||||||
|
"chipActionShowCollection": "Tonen in Collectie",
|
||||||
|
"@chipActionShowCollection": {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"timeSeconds": "{seconds, plural, other{{seconds} sekund}}",
|
"timeSeconds": "{count, plural, other{{count} sekund}}",
|
||||||
"@timeSeconds": {
|
"@timeSeconds": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"seconds": {}
|
"seconds": {}
|
||||||
|
@ -9,19 +9,19 @@
|
||||||
"@welcomeOptional": {},
|
"@welcomeOptional": {},
|
||||||
"welcomeTermsToggle": "Eg samtykkjer til krava og føresetnadane",
|
"welcomeTermsToggle": "Eg samtykkjer til krava og føresetnadane",
|
||||||
"@welcomeTermsToggle": {},
|
"@welcomeTermsToggle": {},
|
||||||
"itemCount": "{count, plural, =1{1 er vald} other{{count} er valde}}",
|
"itemCount": "{count, plural, =1{{count} er vald} other{{count} er valde}}",
|
||||||
"@itemCount": {
|
"@itemCount": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"count": {}
|
"count": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"timeMinutes": "{minutes, plural, other{{minutes} minutt}}",
|
"timeMinutes": "{count, plural, other{{count} minutt}}",
|
||||||
"@timeMinutes": {
|
"@timeMinutes": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"minutes": {}
|
"minutes": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"timeDays": "{days, plural, =1{1 dag} other{{days} dagar}}",
|
"timeDays": "{count, plural, =1{{count} dag} other{{count} dagar}}",
|
||||||
"@timeDays": {
|
"@timeDays": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"days": {}
|
"days": {}
|
||||||
|
@ -1421,7 +1421,7 @@
|
||||||
"@mapAttributionOsmHot": {},
|
"@mapAttributionOsmHot": {},
|
||||||
"mapAttributionStamen": "Kartdata © [OpenStreetMap](https://www.openstreetmap.org/copyright)-medverkarar • Fliser av [Stamen Design](https://stamen.com), [CC BY 3.0](https://creativecommons.org/licenses/by/3.0)",
|
"mapAttributionStamen": "Kartdata © [OpenStreetMap](https://www.openstreetmap.org/copyright)-medverkarar • Fliser av [Stamen Design](https://stamen.com), [CC BY 3.0](https://creativecommons.org/licenses/by/3.0)",
|
||||||
"@mapAttributionStamen": {},
|
"@mapAttributionStamen": {},
|
||||||
"columnCount": "{count, plural, =1{1 kolonne} other{{count} kolonnar}}",
|
"columnCount": "{count, plural, =1{{count} kolonne} other{{count} kolonnar}}",
|
||||||
"@columnCount": {
|
"@columnCount": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"count": {}
|
"count": {}
|
||||||
|
@ -1444,5 +1444,7 @@
|
||||||
"filterNoLocationLabel": "Ustadsette",
|
"filterNoLocationLabel": "Ustadsette",
|
||||||
"@filterNoLocationLabel": {},
|
"@filterNoLocationLabel": {},
|
||||||
"settingsNavigationSectionTitle": "Finn fram",
|
"settingsNavigationSectionTitle": "Finn fram",
|
||||||
"@settingsNavigationSectionTitle": {}
|
"@settingsNavigationSectionTitle": {},
|
||||||
|
"chipActionShowCollection": "Vis i Samling",
|
||||||
|
"@chipActionShowCollection": {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -233,31 +233,31 @@
|
||||||
"@displayRefreshRatePreferLowest": {},
|
"@displayRefreshRatePreferLowest": {},
|
||||||
"videoPlaybackMuted": "Odtwarzaj bez dźwięku",
|
"videoPlaybackMuted": "Odtwarzaj bez dźwięku",
|
||||||
"@videoPlaybackMuted": {},
|
"@videoPlaybackMuted": {},
|
||||||
"itemCount": "{count, plural, =1{1 element} few{{count} elementy} other{{count} elelmentów}}",
|
"itemCount": "{count, plural, =1{{count} element} few{{count} elementy} other{{count} elelmentów}}",
|
||||||
"@itemCount": {
|
"@itemCount": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"count": {}
|
"count": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"columnCount": "{count, plural, =1{1 rząd} few{{count} rzędy} other{{count} rzędów}}",
|
"columnCount": "{count, plural, =1{{count} rząd} few{{count} rzędy} other{{count} rzędów}}",
|
||||||
"@columnCount": {
|
"@columnCount": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"count": {}
|
"count": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"timeSeconds": "{seconds, plural, =1{1 sekunda} few{{seconds} sekundy} other{{seconds} sekund}}",
|
"timeSeconds": "{count, plural, =1{{count} sekunda} few{{count} sekundy} other{{count} sekund}}",
|
||||||
"@timeSeconds": {
|
"@timeSeconds": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"seconds": {}
|
"seconds": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"timeMinutes": "{minutes, plural, =1{1 minuta} few{{minutes} minuty} other{{minutes} minut}}",
|
"timeMinutes": "{count, plural, =1{{count} minuta} few{{count} minuty} other{{count} minut}}",
|
||||||
"@timeMinutes": {
|
"@timeMinutes": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"minutes": {}
|
"minutes": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"timeDays": "{days, plural, =1{1 dzień} few{{days} dni} other{{days} dni}}",
|
"timeDays": "{count, plural, =1{{count} dzień} few{{count} dni} other{{count} dni}}",
|
||||||
"@timeDays": {
|
"@timeDays": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"days": {}
|
"days": {}
|
||||||
|
@ -1536,5 +1536,7 @@
|
||||||
"settingsForceWesternArabicNumeralsTile": "Wymuszaj cyfry arabskie",
|
"settingsForceWesternArabicNumeralsTile": "Wymuszaj cyfry arabskie",
|
||||||
"@settingsForceWesternArabicNumeralsTile": {},
|
"@settingsForceWesternArabicNumeralsTile": {},
|
||||||
"renameProcessorHash": "Skrót",
|
"renameProcessorHash": "Skrót",
|
||||||
"@renameProcessorHash": {}
|
"@renameProcessorHash": {},
|
||||||
|
"chipActionShowCollection": "Pokaż w Kolekcji",
|
||||||
|
"@chipActionShowCollection": {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,13 +7,13 @@
|
||||||
"@welcomeOptional": {},
|
"@welcomeOptional": {},
|
||||||
"welcomeTermsToggle": "Eu concordo com os Termos e Condições",
|
"welcomeTermsToggle": "Eu concordo com os Termos e Condições",
|
||||||
"@welcomeTermsToggle": {},
|
"@welcomeTermsToggle": {},
|
||||||
"itemCount": "{count, plural, =1{1 item} other{{count} itens}}",
|
"itemCount": "{count, plural, =1{{count} item} other{{count} itens}}",
|
||||||
"@itemCount": {},
|
"@itemCount": {},
|
||||||
"timeSeconds": "{seconds, plural, =1{1 segundo} other{{seconds} segundos}}",
|
"timeSeconds": "{count, plural, =1{{count} segundo} other{{count} segundos}}",
|
||||||
"@timeSeconds": {},
|
"@timeSeconds": {},
|
||||||
"timeMinutes": "{minutes, plural, =1{1 minuto} other{{minutes} minutos}}",
|
"timeMinutes": "{count, plural, =1{{count} minuto} other{{count} minutos}}",
|
||||||
"@timeMinutes": {},
|
"@timeMinutes": {},
|
||||||
"timeDays": "{days, plural, =1{1 dia} other{{days} dias}}",
|
"timeDays": "{count, plural, =1{{count} dia} other{{count} dias}}",
|
||||||
"@timeDays": {},
|
"@timeDays": {},
|
||||||
"focalLength": "{length} mm",
|
"focalLength": "{length} mm",
|
||||||
"@focalLength": {},
|
"@focalLength": {},
|
||||||
|
@ -1215,7 +1215,7 @@
|
||||||
"@pinDialogConfirm": {},
|
"@pinDialogConfirm": {},
|
||||||
"passwordDialogEnter": "Digite a senha",
|
"passwordDialogEnter": "Digite a senha",
|
||||||
"@passwordDialogEnter": {},
|
"@passwordDialogEnter": {},
|
||||||
"columnCount": "{count, plural, =1{1 coluna} other{{count} colunas}}",
|
"columnCount": "{count, plural, =1{{count} coluna} other{{count} colunas}}",
|
||||||
"@columnCount": {
|
"@columnCount": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"count": {}
|
"count": {}
|
||||||
|
@ -1374,5 +1374,7 @@
|
||||||
"stopTooltip": "Parar",
|
"stopTooltip": "Parar",
|
||||||
"@stopTooltip": {},
|
"@stopTooltip": {},
|
||||||
"videoRepeatActionSetStart": "Definir início",
|
"videoRepeatActionSetStart": "Definir início",
|
||||||
"@videoRepeatActionSetStart": {}
|
"@videoRepeatActionSetStart": {},
|
||||||
|
"chipActionShowCollection": "Mostrar na Coleção",
|
||||||
|
"@chipActionShowCollection": {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,19 +5,19 @@
|
||||||
"@welcomeOptional": {},
|
"@welcomeOptional": {},
|
||||||
"welcomeTermsToggle": "Sunt de acord cu Termenii și condițiile",
|
"welcomeTermsToggle": "Sunt de acord cu Termenii și condițiile",
|
||||||
"@welcomeTermsToggle": {},
|
"@welcomeTermsToggle": {},
|
||||||
"timeSeconds": "{seconds, plural, =1{1 secundă} other{{seconds} secunde}}",
|
"timeSeconds": "{count, plural, =1{{count} secundă} other{{count} secunde}}",
|
||||||
"@timeSeconds": {
|
"@timeSeconds": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"seconds": {}
|
"seconds": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"timeMinutes": "{minutes, plural, =1{1 minut} other{{minutes} minute}}",
|
"timeMinutes": "{count, plural, =1{{count} minut} other{{count} minute}}",
|
||||||
"@timeMinutes": {
|
"@timeMinutes": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"minutes": {}
|
"minutes": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"timeDays": "{days, plural, =1{1 zi} other{{days} zile}}",
|
"timeDays": "{count, plural, =1{{count} zi} other{{count} zile}}",
|
||||||
"@timeDays": {
|
"@timeDays": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"days": {}
|
"days": {}
|
||||||
|
@ -444,9 +444,9 @@
|
||||||
},
|
},
|
||||||
"exportEntryDialogFormat": "Format:",
|
"exportEntryDialogFormat": "Format:",
|
||||||
"@exportEntryDialogFormat": {},
|
"@exportEntryDialogFormat": {},
|
||||||
"exportEntryDialogWidth": "Lăţime",
|
"exportEntryDialogWidth": "Lățime",
|
||||||
"@exportEntryDialogWidth": {},
|
"@exportEntryDialogWidth": {},
|
||||||
"exportEntryDialogHeight": "Înălţime",
|
"exportEntryDialogHeight": "Înălțime",
|
||||||
"@exportEntryDialogHeight": {},
|
"@exportEntryDialogHeight": {},
|
||||||
"renameEntryDialogLabel": "Nume nou",
|
"renameEntryDialogLabel": "Nume nou",
|
||||||
"@renameEntryDialogLabel": {},
|
"@renameEntryDialogLabel": {},
|
||||||
|
@ -648,7 +648,7 @@
|
||||||
},
|
},
|
||||||
"appName": "Aves",
|
"appName": "Aves",
|
||||||
"@appName": {},
|
"@appName": {},
|
||||||
"itemCount": "{count, plural, =1{1 element} other{{count} elemente}}",
|
"itemCount": "{count, plural, =1{{count} element} other{{count} elemente}}",
|
||||||
"@itemCount": {
|
"@itemCount": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"count": {}
|
"count": {}
|
||||||
|
@ -1329,7 +1329,7 @@
|
||||||
"@statsTopCountriesSectionTitle": {},
|
"@statsTopCountriesSectionTitle": {},
|
||||||
"settingsAccessibilityShowPinchGestureAlternatives": "Afișare alternative de gesturi atingeri-multiple",
|
"settingsAccessibilityShowPinchGestureAlternatives": "Afișare alternative de gesturi atingeri-multiple",
|
||||||
"@settingsAccessibilityShowPinchGestureAlternatives": {},
|
"@settingsAccessibilityShowPinchGestureAlternatives": {},
|
||||||
"columnCount": "{count, plural, =1{1 coloană} other{{count} coloane}}",
|
"columnCount": "{count, plural, =1{{count} coloană} other{{count} coloane}}",
|
||||||
"@columnCount": {
|
"@columnCount": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"count": {}
|
"count": {}
|
||||||
|
@ -1524,5 +1524,19 @@
|
||||||
"maxBrightnessNever": "Niciodată",
|
"maxBrightnessNever": "Niciodată",
|
||||||
"@maxBrightnessNever": {},
|
"@maxBrightnessNever": {},
|
||||||
"maxBrightnessAlways": "Mereu",
|
"maxBrightnessAlways": "Mereu",
|
||||||
"@maxBrightnessAlways": {}
|
"@maxBrightnessAlways": {},
|
||||||
|
"renameProcessorHash": "Hash",
|
||||||
|
"@renameProcessorHash": {},
|
||||||
|
"settingsForceWesternArabicNumeralsTile": "Cifre arabe forțat",
|
||||||
|
"@settingsForceWesternArabicNumeralsTile": {},
|
||||||
|
"stopTooltip": "Oprește",
|
||||||
|
"@stopTooltip": {},
|
||||||
|
"videoActionABRepeat": "Repetă de la A la B",
|
||||||
|
"@videoActionABRepeat": {},
|
||||||
|
"videoRepeatActionSetStart": "Setează începutul",
|
||||||
|
"@videoRepeatActionSetStart": {},
|
||||||
|
"videoRepeatActionSetEnd": "Setează sfârșitul",
|
||||||
|
"@videoRepeatActionSetEnd": {},
|
||||||
|
"chipActionShowCollection": "Afișați în colecție",
|
||||||
|
"@chipActionShowCollection": {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,13 +7,13 @@
|
||||||
"@welcomeOptional": {},
|
"@welcomeOptional": {},
|
||||||
"welcomeTermsToggle": "Я согласен с условиями и положениями",
|
"welcomeTermsToggle": "Я согласен с условиями и положениями",
|
||||||
"@welcomeTermsToggle": {},
|
"@welcomeTermsToggle": {},
|
||||||
"itemCount": "{count, plural, =1{1 объект} few{{count} объекта} other{{count} объектов}}",
|
"itemCount": "{count, plural, =1{{count} объект} few{{count} объекта} other{{count} объектов}}",
|
||||||
"@itemCount": {},
|
"@itemCount": {},
|
||||||
"timeSeconds": "{seconds, plural, =1{1 секунда} few{{seconds} секунды} other{{seconds} секунд}}",
|
"timeSeconds": "{count, plural, =1{{count} секунда} few{{count} секунды} other{{count} секунд}}",
|
||||||
"@timeSeconds": {},
|
"@timeSeconds": {},
|
||||||
"timeMinutes": "{minutes, plural, =1{1 минута} few{{minutes} минуты} other{{minutes} минут}}",
|
"timeMinutes": "{count, plural, =1{{count} минута} few{{count} минуты} other{{count} минут}}",
|
||||||
"@timeMinutes": {},
|
"@timeMinutes": {},
|
||||||
"timeDays": "{days, plural, =1{1 день} few{{days} дня} other{{days} дней}}",
|
"timeDays": "{count, plural, =1{{count} день} few{{count} дня} other{{count} дней}}",
|
||||||
"@timeDays": {},
|
"@timeDays": {},
|
||||||
"focalLength": "{length} mm",
|
"focalLength": "{length} mm",
|
||||||
"@focalLength": {},
|
"@focalLength": {},
|
||||||
|
@ -1177,7 +1177,7 @@
|
||||||
"@filterAspectRatioPortraitLabel": {},
|
"@filterAspectRatioPortraitLabel": {},
|
||||||
"settingsViewerShowRatingTags": "Показать рейтинг и теги",
|
"settingsViewerShowRatingTags": "Показать рейтинг и теги",
|
||||||
"@settingsViewerShowRatingTags": {},
|
"@settingsViewerShowRatingTags": {},
|
||||||
"columnCount": "{count, plural, =1{1 столбец} few{{count} столбца} other{{count} столбцов}}",
|
"columnCount": "{count, plural, =1{{count} столбец} few{{count} столбца} other{{count} столбцов}}",
|
||||||
"@columnCount": {
|
"@columnCount": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"count": {}
|
"count": {}
|
||||||
|
@ -1378,5 +1378,7 @@
|
||||||
"renameProcessorHash": "Хэш",
|
"renameProcessorHash": "Хэш",
|
||||||
"@renameProcessorHash": {},
|
"@renameProcessorHash": {},
|
||||||
"settingsForceWesternArabicNumeralsTile": "Принудительные арабские цифры",
|
"settingsForceWesternArabicNumeralsTile": "Принудительные арабские цифры",
|
||||||
"@settingsForceWesternArabicNumeralsTile": {}
|
"@settingsForceWesternArabicNumeralsTile": {},
|
||||||
|
"chipActionShowCollection": "Показать в Коллекции",
|
||||||
|
"@chipActionShowCollection": {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
"@chipActionDelete": {},
|
"@chipActionDelete": {},
|
||||||
"welcomeTermsToggle": "Súhlasím s pravidlami a podmienkami",
|
"welcomeTermsToggle": "Súhlasím s pravidlami a podmienkami",
|
||||||
"@welcomeTermsToggle": {},
|
"@welcomeTermsToggle": {},
|
||||||
"timeDays": "{days, plural, other{{days} dni}}",
|
"timeDays": "{count, plural, other{{count} dni}}",
|
||||||
"@timeDays": {
|
"@timeDays": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"days": {}
|
"days": {}
|
||||||
|
@ -50,7 +50,7 @@
|
||||||
"@doubleBackExitMessage": {},
|
"@doubleBackExitMessage": {},
|
||||||
"welcomeOptional": "Voliteľné",
|
"welcomeOptional": "Voliteľné",
|
||||||
"@welcomeOptional": {},
|
"@welcomeOptional": {},
|
||||||
"timeMinutes": "{minutes, plural, =1{1 minúta} few{{minutes} minúty} other{{minutes} minút}}",
|
"timeMinutes": "{count, plural, =1{{count} minúta} few{{count} minúty} other{{count} minút}}",
|
||||||
"@timeMinutes": {
|
"@timeMinutes": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"minutes": {}
|
"minutes": {}
|
||||||
|
@ -638,19 +638,19 @@
|
||||||
"@filePickerOpenFrom": {},
|
"@filePickerOpenFrom": {},
|
||||||
"filePickerUseThisFolder": "Použiť tento priečinok",
|
"filePickerUseThisFolder": "Použiť tento priečinok",
|
||||||
"@filePickerUseThisFolder": {},
|
"@filePickerUseThisFolder": {},
|
||||||
"itemCount": "{count, plural, =1{1 položka} other{{count} položiek}}",
|
"itemCount": "{count, plural, =1{{count} položka} other{{count} položiek}}",
|
||||||
"@itemCount": {
|
"@itemCount": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"count": {}
|
"count": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"columnCount": "{count, plural, =1{1 stĺpec} other{{count} stĺpcov}}",
|
"columnCount": "{count, plural, =1{{count} stĺpec} other{{count} stĺpcov}}",
|
||||||
"@columnCount": {
|
"@columnCount": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"count": {}
|
"count": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"timeSeconds": "{seconds, plural, =1{1 sekunda} other{{seconds} sekúnd}}",
|
"timeSeconds": "{count, plural, =1{{count} sekunda} other{{count} sekúnd}}",
|
||||||
"@timeSeconds": {
|
"@timeSeconds": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"seconds": {}
|
"seconds": {}
|
||||||
|
@ -1524,5 +1524,7 @@
|
||||||
"setHomeCustomCollection": "Kolekcia na mieru",
|
"setHomeCustomCollection": "Kolekcia na mieru",
|
||||||
"@setHomeCustomCollection": {},
|
"@setHomeCustomCollection": {},
|
||||||
"settingsThumbnailShowHdrIcon": "Zobraziť ikonu HDR",
|
"settingsThumbnailShowHdrIcon": "Zobraziť ikonu HDR",
|
||||||
"@settingsThumbnailShowHdrIcon": {}
|
"@settingsThumbnailShowHdrIcon": {},
|
||||||
|
"chipActionShowCollection": "Zobraziť v kolekcií",
|
||||||
|
"@chipActionShowCollection": {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -106,25 +106,25 @@
|
||||||
"count": {}
|
"count": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"columnCount": "{count, plural, =1{1 kolumn} other{{count} kolumner}}",
|
"columnCount": "{count, plural, =1{{count} kolumn} other{{count} kolumner}}",
|
||||||
"@columnCount": {
|
"@columnCount": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"count": {}
|
"count": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"timeSeconds": "{seconds, plural, =1{1 sekund} other{{seconds} sekunder}}",
|
"timeSeconds": "{count, plural, =1{{count} sekund} other{{count} sekunder}}",
|
||||||
"@timeSeconds": {
|
"@timeSeconds": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"seconds": {}
|
"seconds": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"timeMinutes": "{minutes, plural, =1{1 minut} other{{minutes} minuter}}",
|
"timeMinutes": "{count, plural, =1{{count} minut} other{{count} minuter}}",
|
||||||
"@timeMinutes": {
|
"@timeMinutes": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"minutes": {}
|
"minutes": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"timeDays": "{days, plural, =1{1 dag} other{{days} dagar}}",
|
"timeDays": "{count, plural, =1{{count} dag} other{{count} dagar}}",
|
||||||
"@timeDays": {
|
"@timeDays": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"days": {}
|
"days": {}
|
||||||
|
@ -835,5 +835,7 @@
|
||||||
"filePickerUseThisFolder": "Använd den har mappen",
|
"filePickerUseThisFolder": "Använd den har mappen",
|
||||||
"@filePickerUseThisFolder": {},
|
"@filePickerUseThisFolder": {},
|
||||||
"chipActionUnpin": "Släpp från fästet",
|
"chipActionUnpin": "Släpp från fästet",
|
||||||
"@chipActionUnpin": {}
|
"@chipActionUnpin": {},
|
||||||
|
"chipActionShowCollection": "Visa i samling",
|
||||||
|
"@chipActionShowCollection": {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -649,5 +649,7 @@
|
||||||
"description": "a list of unsupported types"
|
"description": "a list of unsupported types"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
"chipActionShowCollection": "แสดงคอลเลกชัน",
|
||||||
|
"@chipActionShowCollection": {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,13 +7,13 @@
|
||||||
"@welcomeOptional": {},
|
"@welcomeOptional": {},
|
||||||
"welcomeTermsToggle": "Hüküm ve koşulları kabul ediyorum",
|
"welcomeTermsToggle": "Hüküm ve koşulları kabul ediyorum",
|
||||||
"@welcomeTermsToggle": {},
|
"@welcomeTermsToggle": {},
|
||||||
"itemCount": "{count, plural, =1{1 öğe} other{{count} öğe}}",
|
"itemCount": "{count, plural, other{{count} öğe}}",
|
||||||
"@itemCount": {},
|
"@itemCount": {},
|
||||||
"timeSeconds": "{seconds, plural, =1{1 saniye} other{{seconds} saniye}}",
|
"timeSeconds": "{count, plural, other{{count} saniye}}",
|
||||||
"@timeSeconds": {},
|
"@timeSeconds": {},
|
||||||
"timeMinutes": "{minutes, plural, =1{1 dakika} other{{minutes} dakika}}",
|
"timeMinutes": "{count, plural, other{{count} dakika}}",
|
||||||
"@timeMinutes": {},
|
"@timeMinutes": {},
|
||||||
"timeDays": "{days, plural, =1{1 gün} other{{days} gün}}",
|
"timeDays": "{count, plural, other{{count} gün}}",
|
||||||
"@timeDays": {},
|
"@timeDays": {},
|
||||||
"focalLength": "{length} mm",
|
"focalLength": "{length} mm",
|
||||||
"@focalLength": {},
|
"@focalLength": {},
|
||||||
|
@ -1378,5 +1378,7 @@
|
||||||
"settingsForceWesternArabicNumeralsTile": "Arap rakamlarını zorla",
|
"settingsForceWesternArabicNumeralsTile": "Arap rakamlarını zorla",
|
||||||
"@settingsForceWesternArabicNumeralsTile": {},
|
"@settingsForceWesternArabicNumeralsTile": {},
|
||||||
"renameProcessorHash": "Sağlama",
|
"renameProcessorHash": "Sağlama",
|
||||||
"@renameProcessorHash": {}
|
"@renameProcessorHash": {},
|
||||||
|
"chipActionShowCollection": "Koleksiyonda göster",
|
||||||
|
"@chipActionShowCollection": {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
"@welcomeOptional": {},
|
"@welcomeOptional": {},
|
||||||
"welcomeTermsToggle": "Я погоджуюсь з умовами та положеннями",
|
"welcomeTermsToggle": "Я погоджуюсь з умовами та положеннями",
|
||||||
"@welcomeTermsToggle": {},
|
"@welcomeTermsToggle": {},
|
||||||
"timeDays": "{days, plural, =1{1 день} few{{days} дні} other{{days} днів}}",
|
"timeDays": "{count, plural, =1{{count} день} few{{count} дні} other{{count} днів}}",
|
||||||
"@timeDays": {
|
"@timeDays": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"days": {}
|
"days": {}
|
||||||
|
@ -637,19 +637,19 @@
|
||||||
"@entryActionShareVideoOnly": {},
|
"@entryActionShareVideoOnly": {},
|
||||||
"continueButtonLabel": "ПРОДОВЖИТИ",
|
"continueButtonLabel": "ПРОДОВЖИТИ",
|
||||||
"@continueButtonLabel": {},
|
"@continueButtonLabel": {},
|
||||||
"itemCount": "{count, plural, =1{1 елемент} few{{count} елементи} other{{count} елементів}}",
|
"itemCount": "{count, plural, =1{{count} елемент} few{{count} елементи} other{{count} елементів}}",
|
||||||
"@itemCount": {
|
"@itemCount": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"count": {}
|
"count": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"timeSeconds": "{seconds, plural, =1{1 секунда} few{{seconds} секунди} other{{seconds} секунд}}",
|
"timeSeconds": "{count, plural, =1{{count} секунда} few{{count} секунди} other{{count} секунд}}",
|
||||||
"@timeSeconds": {
|
"@timeSeconds": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"seconds": {}
|
"seconds": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"timeMinutes": "{minutes, plural, =1{1 хвилина} few{{minutes} хвилини} other{{minutes} хвилин}}",
|
"timeMinutes": "{count, plural, =1{{count} хвилина} few{{count} хвилини} other{{count} хвилин}}",
|
||||||
"@timeMinutes": {
|
"@timeMinutes": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"minutes": {}
|
"minutes": {}
|
||||||
|
@ -1345,7 +1345,7 @@
|
||||||
"@mapAttributionOsmHot": {},
|
"@mapAttributionOsmHot": {},
|
||||||
"settingsAccessibilityShowPinchGestureAlternatives": "Показувати альтернативи мультисенсорним жестам",
|
"settingsAccessibilityShowPinchGestureAlternatives": "Показувати альтернативи мультисенсорним жестам",
|
||||||
"@settingsAccessibilityShowPinchGestureAlternatives": {},
|
"@settingsAccessibilityShowPinchGestureAlternatives": {},
|
||||||
"columnCount": "{count, plural, =1{1 стовпець} few{{count} стовпці} other{{count} стовпців}}",
|
"columnCount": "{count, plural, =1{{count} стовпець} few{{count} стовпці} other{{count} стовпців}}",
|
||||||
"@columnCount": {
|
"@columnCount": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"count": {}
|
"count": {}
|
||||||
|
@ -1532,5 +1532,11 @@
|
||||||
"stopTooltip": "Зупинити",
|
"stopTooltip": "Зупинити",
|
||||||
"@stopTooltip": {},
|
"@stopTooltip": {},
|
||||||
"videoActionABRepeat": "Повторити від А до Б",
|
"videoActionABRepeat": "Повторити від А до Б",
|
||||||
"@videoActionABRepeat": {}
|
"@videoActionABRepeat": {},
|
||||||
|
"renameProcessorHash": "Хеш",
|
||||||
|
"@renameProcessorHash": {},
|
||||||
|
"settingsForceWesternArabicNumeralsTile": "Примусові арабські цифри",
|
||||||
|
"@settingsForceWesternArabicNumeralsTile": {},
|
||||||
|
"chipActionShowCollection": "Показати у Колекції",
|
||||||
|
"@chipActionShowCollection": {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -951,7 +951,7 @@
|
||||||
"@placePageTitle": {},
|
"@placePageTitle": {},
|
||||||
"filterOnThisDayLabel": "Vào ngày này",
|
"filterOnThisDayLabel": "Vào ngày này",
|
||||||
"@filterOnThisDayLabel": {},
|
"@filterOnThisDayLabel": {},
|
||||||
"columnCount": "{count, plural, =1{1 cột} other{{count} cột}}",
|
"columnCount": "{count, plural, other{{count} cột}}",
|
||||||
"@columnCount": {
|
"@columnCount": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"count": {}
|
"count": {}
|
||||||
|
@ -1007,7 +1007,7 @@
|
||||||
"@albumMimeTypeMixed": {},
|
"@albumMimeTypeMixed": {},
|
||||||
"settingsViewerQuickActionEditorAvailableButtonsSectionTitle": "Các nút có sẵn",
|
"settingsViewerQuickActionEditorAvailableButtonsSectionTitle": "Các nút có sẵn",
|
||||||
"@settingsViewerQuickActionEditorAvailableButtonsSectionTitle": {},
|
"@settingsViewerQuickActionEditorAvailableButtonsSectionTitle": {},
|
||||||
"itemCount": "{count, plural, =1{1 mục} other{{count} mục}}",
|
"itemCount": "{count, plural, other{{count} mục}}",
|
||||||
"@itemCount": {
|
"@itemCount": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"count": {}
|
"count": {}
|
||||||
|
@ -1271,7 +1271,7 @@
|
||||||
"@drawerCollectionImages": {},
|
"@drawerCollectionImages": {},
|
||||||
"sortOrderSmallestFirst": "Nhỏ trước",
|
"sortOrderSmallestFirst": "Nhỏ trước",
|
||||||
"@sortOrderSmallestFirst": {},
|
"@sortOrderSmallestFirst": {},
|
||||||
"timeSeconds": "{seconds, plural, =1{1 giây} other{{seconds} giây}}",
|
"timeSeconds": "{count, plural, other{{count} giây}}",
|
||||||
"@timeSeconds": {
|
"@timeSeconds": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"seconds": {}
|
"seconds": {}
|
||||||
|
@ -1405,7 +1405,7 @@
|
||||||
"@settingsNavigationDrawerTabAlbums": {},
|
"@settingsNavigationDrawerTabAlbums": {},
|
||||||
"subtitlePositionBottom": "Dưới",
|
"subtitlePositionBottom": "Dưới",
|
||||||
"@subtitlePositionBottom": {},
|
"@subtitlePositionBottom": {},
|
||||||
"timeDays": "{days, plural, =1{1 ngày} other{{days} ngày}}",
|
"timeDays": "{count, plural, other{{count} ngày}}",
|
||||||
"@timeDays": {
|
"@timeDays": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"days": {}
|
"days": {}
|
||||||
|
@ -1429,7 +1429,7 @@
|
||||||
"@settingsViewerQuickActionsTile": {},
|
"@settingsViewerQuickActionsTile": {},
|
||||||
"newVaultDialogTitle": "Két sắt mới",
|
"newVaultDialogTitle": "Két sắt mới",
|
||||||
"@newVaultDialogTitle": {},
|
"@newVaultDialogTitle": {},
|
||||||
"timeMinutes": "{minutes, plural, =1{1 phút} other{{minutes} phút}}",
|
"timeMinutes": "{count, plural, other{{count} phút}}",
|
||||||
"@timeMinutes": {
|
"@timeMinutes": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"minutes": {}
|
"minutes": {}
|
||||||
|
@ -1536,5 +1536,7 @@
|
||||||
"renameProcessorHash": "Băm",
|
"renameProcessorHash": "Băm",
|
||||||
"@renameProcessorHash": {},
|
"@renameProcessorHash": {},
|
||||||
"settingsForceWesternArabicNumeralsTile": "Buộc chữ số Ả Rập",
|
"settingsForceWesternArabicNumeralsTile": "Buộc chữ số Ả Rập",
|
||||||
"@settingsForceWesternArabicNumeralsTile": {}
|
"@settingsForceWesternArabicNumeralsTile": {},
|
||||||
|
"chipActionShowCollection": "Hiển thị trong Bộ sưu tập",
|
||||||
|
"@chipActionShowCollection": {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,11 +9,11 @@
|
||||||
"@welcomeTermsToggle": {},
|
"@welcomeTermsToggle": {},
|
||||||
"itemCount": "{count, plural, other{{count} 项}}",
|
"itemCount": "{count, plural, other{{count} 项}}",
|
||||||
"@itemCount": {},
|
"@itemCount": {},
|
||||||
"timeSeconds": "{seconds, plural, other{{seconds} 秒}}",
|
"timeSeconds": "{count, plural, other{{count} 秒}}",
|
||||||
"@timeSeconds": {},
|
"@timeSeconds": {},
|
||||||
"timeMinutes": "{minutes, plural, other{{minutes} 分}}",
|
"timeMinutes": "{count, plural, other{{count} 分}}",
|
||||||
"@timeMinutes": {},
|
"@timeMinutes": {},
|
||||||
"timeDays": "{days, plural, other{{days} 天}}",
|
"timeDays": "{count, plural, other{{count} 天}}",
|
||||||
"@timeDays": {},
|
"@timeDays": {},
|
||||||
"focalLength": "{length} mm",
|
"focalLength": "{length} mm",
|
||||||
"@focalLength": {},
|
"@focalLength": {},
|
||||||
|
@ -723,7 +723,7 @@
|
||||||
"@searchMetadataSectionTitle": {},
|
"@searchMetadataSectionTitle": {},
|
||||||
"settingsPageTitle": "设置",
|
"settingsPageTitle": "设置",
|
||||||
"@settingsPageTitle": {},
|
"@settingsPageTitle": {},
|
||||||
"settingsSystemDefault": "系统",
|
"settingsSystemDefault": "系统默认",
|
||||||
"@settingsSystemDefault": {},
|
"@settingsSystemDefault": {},
|
||||||
"settingsDefault": "默认",
|
"settingsDefault": "默认",
|
||||||
"@settingsDefault": {},
|
"@settingsDefault": {},
|
||||||
|
@ -1377,6 +1377,8 @@
|
||||||
"@videoRepeatActionSetEnd": {},
|
"@videoRepeatActionSetEnd": {},
|
||||||
"renameProcessorHash": "哈希",
|
"renameProcessorHash": "哈希",
|
||||||
"@renameProcessorHash": {},
|
"@renameProcessorHash": {},
|
||||||
"settingsForceWesternArabicNumeralsTile": "强制阿拉伯数数字",
|
"settingsForceWesternArabicNumeralsTile": "强制使用阿拉伯数字",
|
||||||
"@settingsForceWesternArabicNumeralsTile": {}
|
"@settingsForceWesternArabicNumeralsTile": {},
|
||||||
|
"chipActionShowCollection": "在媒体集中显示",
|
||||||
|
"@chipActionShowCollection": {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
"count": {}
|
"count": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"timeDays": "{days, plural, other{{days} 天}}",
|
"timeDays": "{count, plural, other{{count} 天}}",
|
||||||
"@timeDays": {
|
"@timeDays": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"days": {}
|
"days": {}
|
||||||
|
@ -919,13 +919,13 @@
|
||||||
"@mapZoomOutTooltip": {},
|
"@mapZoomOutTooltip": {},
|
||||||
"mapPointNorthUpTooltip": "北方向上",
|
"mapPointNorthUpTooltip": "北方向上",
|
||||||
"@mapPointNorthUpTooltip": {},
|
"@mapPointNorthUpTooltip": {},
|
||||||
"timeSeconds": "{seconds, plural, other{{seconds} 秒}}",
|
"timeSeconds": "{count, plural, other{{count} 秒}}",
|
||||||
"@timeSeconds": {
|
"@timeSeconds": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"seconds": {}
|
"seconds": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"timeMinutes": "{minutes, plural, other{{minutes} 分}}",
|
"timeMinutes": "{count, plural, other{{count} 分}}",
|
||||||
"@timeMinutes": {
|
"@timeMinutes": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"minutes": {}
|
"minutes": {}
|
||||||
|
@ -1419,7 +1419,7 @@
|
||||||
"@settingsVideoResumptionModeDialogTitle": {},
|
"@settingsVideoResumptionModeDialogTitle": {},
|
||||||
"tagEditorDiscardDialogMessage": "是否要放棄更改?",
|
"tagEditorDiscardDialogMessage": "是否要放棄更改?",
|
||||||
"@tagEditorDiscardDialogMessage": {},
|
"@tagEditorDiscardDialogMessage": {},
|
||||||
"columnCount": "{count, plural, =1{1 列} other{{count} 列}}",
|
"columnCount": "{count, plural, other{{count} 列}}",
|
||||||
"@columnCount": {
|
"@columnCount": {
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"count": {}
|
"count": {}
|
||||||
|
@ -1532,5 +1532,11 @@
|
||||||
"videoRepeatActionSetStart": "設置起點",
|
"videoRepeatActionSetStart": "設置起點",
|
||||||
"@videoRepeatActionSetStart": {},
|
"@videoRepeatActionSetStart": {},
|
||||||
"videoRepeatActionSetEnd": "設置終點",
|
"videoRepeatActionSetEnd": "設置終點",
|
||||||
"@videoRepeatActionSetEnd": {}
|
"@videoRepeatActionSetEnd": {},
|
||||||
|
"renameProcessorHash": "雜湊",
|
||||||
|
"@renameProcessorHash": {},
|
||||||
|
"settingsForceWesternArabicNumeralsTile": "強制使用阿拉伯數字",
|
||||||
|
"@settingsForceWesternArabicNumeralsTile": {},
|
||||||
|
"chipActionShowCollection": "在收藏品中顯示",
|
||||||
|
"@chipActionShowCollection": {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,6 +87,10 @@ class Contributors {
|
||||||
Contributor('slasb37', 'p84haghi@gmail.com'),
|
Contributor('slasb37', 'p84haghi@gmail.com'),
|
||||||
Contributor('mimvahedi', 'vahedi0vahedi@gmail.com'),
|
Contributor('mimvahedi', 'vahedi0vahedi@gmail.com'),
|
||||||
Contributor('Alireza Rashidi', 'alirezarashidigoorabi@gmail.com'),
|
Contributor('Alireza Rashidi', 'alirezarashidigoorabi@gmail.com'),
|
||||||
|
Contributor('何意挽秋風', '94283631+RejectVanity@users.noreply.github.com'),
|
||||||
|
Contributor('cheese', 'deanlemans5646@gmail.com'),
|
||||||
|
Contributor('Owen Elderbroek', 'o.elderbroek@gmail.com'),
|
||||||
|
Contributor('Maxi', 'maxitendo01@proton.me'),
|
||||||
// Contributor('Alvi Khan', 'aveenalvi@gmail.com'), // Bengali
|
// Contributor('Alvi Khan', 'aveenalvi@gmail.com'), // Bengali
|
||||||
// Contributor('Htet Oo Hlaing', 'htetoh2006@outlook.com'), // Burmese
|
// Contributor('Htet Oo Hlaing', 'htetoh2006@outlook.com'), // Burmese
|
||||||
// Contributor('Khant', 'khant@users.noreply.hosted.weblate.org'), // Burmese
|
// Contributor('Khant', 'khant@users.noreply.hosted.weblate.org'), // Burmese
|
||||||
|
|
|
@ -23,6 +23,9 @@ import 'package:latlong2/latlong.dart';
|
||||||
import 'package:xml/xml.dart';
|
import 'package:xml/xml.dart';
|
||||||
|
|
||||||
extension ExtraAvesEntryMetadataEdition on AvesEntry {
|
extension ExtraAvesEntryMetadataEdition on AvesEntry {
|
||||||
|
static final _iso6709LatitudeFormatter = NumberFormat('00.0000', asciiLocale);
|
||||||
|
static final _iso6709LongitudeFormatter = NumberFormat('000.0000', asciiLocale);
|
||||||
|
|
||||||
Future<Set<EntryDataType>> editDate(DateModifier userModifier) async {
|
Future<Set<EntryDataType>> editDate(DateModifier userModifier) async {
|
||||||
final dataTypes = <EntryDataType>{};
|
final dataTypes = <EntryDataType>{};
|
||||||
|
|
||||||
|
@ -59,7 +62,7 @@ extension ExtraAvesEntryMetadataEdition on AvesEntry {
|
||||||
final date = DateTime.tryParse(xmpDate);
|
final date = DateTime.tryParse(xmpDate);
|
||||||
if (date != null) {
|
if (date != null) {
|
||||||
// TODO TLAD [date] DateTime.tryParse converts to UTC time, losing the time zone offset
|
// TODO TLAD [date] DateTime.tryParse converts to UTC time, losing the time zone offset
|
||||||
final shiftedDate = date.add(Duration(minutes: appliedModifier.shiftMinutes!));
|
final shiftedDate = date.add(Duration(seconds: appliedModifier.shiftSeconds!));
|
||||||
editCreateDateXmp(descriptions, shiftedDate);
|
editCreateDateXmp(descriptions, shiftedDate);
|
||||||
} else {
|
} else {
|
||||||
reportService.recordError('failed to parse XMP date=$xmpDate', null);
|
reportService.recordError('failed to parse XMP date=$xmpDate', null);
|
||||||
|
@ -122,9 +125,8 @@ extension ExtraAvesEntryMetadataEdition on AvesEntry {
|
||||||
if (latLng != null && latLng != removalLocation) {
|
if (latLng != null && latLng != removalLocation) {
|
||||||
final latitude = latLng.latitude;
|
final latitude = latLng.latitude;
|
||||||
final longitude = latLng.longitude;
|
final longitude = latLng.longitude;
|
||||||
const locale = asciiLocale;
|
final isoLat = '${latitude >= 0 ? '+' : '-'}${_iso6709LatitudeFormatter.format(latitude.abs())}';
|
||||||
final isoLat = '${latitude >= 0 ? '+' : '-'}${NumberFormat('00.0000', locale).format(latitude.abs())}';
|
final isoLon = '${longitude >= 0 ? '+' : '-'}${_iso6709LongitudeFormatter.format(longitude.abs())}';
|
||||||
final isoLon = '${longitude >= 0 ? '+' : '-'}${NumberFormat('000.0000', locale).format(longitude.abs())}';
|
|
||||||
iso6709String = '$isoLat$isoLon/';
|
iso6709String = '$isoLat$isoLon/';
|
||||||
}
|
}
|
||||||
mp4Fields[MetadataField.mp4GpsCoordinates] = iso6709String;
|
mp4Fields[MetadataField.mp4GpsCoordinates] = iso6709String;
|
||||||
|
|
|
@ -11,6 +11,7 @@ import 'package:aves/services/common/services.dart';
|
||||||
import 'package:aves/theme/text.dart';
|
import 'package:aves/theme/text.dart';
|
||||||
import 'package:aves/utils/android_file_utils.dart';
|
import 'package:aves/utils/android_file_utils.dart';
|
||||||
import 'package:aves/utils/time_utils.dart';
|
import 'package:aves/utils/time_utils.dart';
|
||||||
|
import 'package:intl/intl.dart';
|
||||||
|
|
||||||
extension ExtraAvesEntryProps on AvesEntry {
|
extension ExtraAvesEntryProps on AvesEntry {
|
||||||
bool get isValid => !isMissingAtPath && sizeBytes != 0 && width > 0 && height > 0;
|
bool get isValid => !isMissingAtPath && sizeBytes != 0 && width > 0 && height > 0;
|
||||||
|
@ -51,9 +52,10 @@ extension ExtraAvesEntryProps on AvesEntry {
|
||||||
|
|
||||||
// text
|
// text
|
||||||
|
|
||||||
String get resolutionText {
|
String getResolutionText(String locale) {
|
||||||
final ws = width;
|
final dimensionFormatter = NumberFormat('0', locale);
|
||||||
final hs = height;
|
final ws = dimensionFormatter.format(width);
|
||||||
|
final hs = dimensionFormatter.format(height);
|
||||||
return isRotated ? '$hs${AText.resolutionSeparator}$ws' : '$ws${AText.resolutionSeparator}$hs';
|
return isRotated ? '$hs${AText.resolutionSeparator}$ws' : '$ws${AText.resolutionSeparator}$hs';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -68,9 +68,7 @@ class AspectRatioFilter extends CollectionFilter {
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget iconBuilder(BuildContext context, double size, {bool showGenericIcon = true}) {
|
Widget? iconBuilder(BuildContext context, double size, {bool showGenericIcon = true}) => Icon(AIcons.aspectRatio, size: size);
|
||||||
return Icon(AIcons.aspectRatio, size: size);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get category => type;
|
String get category => type;
|
||||||
|
|
|
@ -69,7 +69,7 @@ class CoordinateFilter extends CollectionFilter {
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget iconBuilder(BuildContext context, double size, {bool showGenericIcon = true}) => Icon(AIcons.geoBounds, size: size);
|
Widget? iconBuilder(BuildContext context, double size, {bool showGenericIcon = true}) => Icon(AIcons.geoBounds, size: size);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get category => type;
|
String get category => type;
|
||||||
|
|
|
@ -100,8 +100,7 @@ class DateFilter extends CollectionFilter {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String getLabel(BuildContext context) {
|
String getLabel(BuildContext context) {
|
||||||
final l10n = context.l10n;
|
final locale = context.locale;
|
||||||
final locale = l10n.localeName;
|
|
||||||
switch (level) {
|
switch (level) {
|
||||||
case DateLevel.y:
|
case DateLevel.y:
|
||||||
return DateFormat.y(locale).format(_effectiveDate);
|
return DateFormat.y(locale).format(_effectiveDate);
|
||||||
|
@ -113,7 +112,7 @@ class DateFilter extends CollectionFilter {
|
||||||
if (date != null) {
|
if (date != null) {
|
||||||
return DateFormat.MMMd(locale).format(_effectiveDate);
|
return DateFormat.MMMd(locale).format(_effectiveDate);
|
||||||
} else {
|
} else {
|
||||||
return l10n.filterOnThisDayLabel;
|
return context.l10n.filterOnThisDayLabel;
|
||||||
}
|
}
|
||||||
case DateLevel.m:
|
case DateLevel.m:
|
||||||
return DateFormat.MMMM(locale).format(_effectiveDate);
|
return DateFormat.MMMM(locale).format(_effectiveDate);
|
||||||
|
@ -123,9 +122,7 @@ class DateFilter extends CollectionFilter {
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget iconBuilder(BuildContext context, double size, {bool showGenericIcon = true}) {
|
Widget? iconBuilder(BuildContext context, double size, {bool showGenericIcon = true}) => Icon(AIcons.date, size: size);
|
||||||
return Icon(AIcons.date, size: size);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get category => type;
|
String get category => type;
|
||||||
|
|
|
@ -45,7 +45,7 @@ class FavouriteFilter extends CollectionFilter {
|
||||||
String getLabel(BuildContext context) => context.l10n.filterFavouriteLabel;
|
String getLabel(BuildContext context) => context.l10n.filterFavouriteLabel;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget iconBuilder(BuildContext context, double size, {bool showGenericIcon = true}) => Icon(AIcons.favourite, size: size);
|
Widget? iconBuilder(BuildContext context, double size, {bool showGenericIcon = true}) => Icon(AIcons.favourite, size: size);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<Color> color(BuildContext context) {
|
Future<Color> color(BuildContext context) {
|
||||||
|
|