Merge branch 'develop'

This commit is contained in:
Thibault Deckers 2023-12-24 16:51:18 +01:00
commit 7cd170baf9
21 changed files with 178 additions and 132 deletions

View file

@ -4,6 +4,16 @@ 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.10.2"></a>[v1.10.2] - 2023-12-24
### Changed
- Viewer: keep controls in the lower right corner even with RTL locales
### Fixed
- crash when loading SVG defined with large dimensions
## <a id="v1.10.1"></a>[v1.10.1] - 2023-12-21 ## <a id="v1.10.1"></a>[v1.10.1] - 2023-12-21
- Cataloguing: detect/filter `Ultra HDR` - Cataloguing: detect/filter `Ultra HDR`

View file

@ -89,6 +89,7 @@ class MediaFetchBytesHandler(private val context: Context) : MethodCallHandler {
MimeTypes.SVG -> SvgRegionFetcher(context).fetch( MimeTypes.SVG -> SvgRegionFetcher(context).fetch(
uri = uri, uri = uri,
sizeBytes = sizeBytes, sizeBytes = sizeBytes,
scale = sampleSize,
regionRect = regionRect, regionRect = regionRect,
imageWidth = imageWidth, imageWidth = imageWidth,
imageHeight = imageHeight, imageHeight = imageHeight,

View file

@ -25,6 +25,7 @@ class SvgRegionFetcher internal constructor(
suspend fun fetch( suspend fun fetch(
uri: Uri, uri: Uri,
sizeBytes: Long?, sizeBytes: Long?,
scale: Int,
regionRect: Rect, regionRect: Rect,
imageWidth: Int, imageWidth: Int,
imageHeight: Int, imageHeight: Int,
@ -32,7 +33,7 @@ class SvgRegionFetcher internal constructor(
) { ) {
if (!MemoryUtils.canAllocate(sizeBytes)) { if (!MemoryUtils.canAllocate(sizeBytes)) {
// opening an SVG that large would yield an OOM during parsing from `com.caverock.androidsvg.SVGParser` // opening an SVG that large would yield an OOM during parsing from `com.caverock.androidsvg.SVGParser`
result.error("fetch-read-large", "SVG too large at $sizeBytes bytes, for uri=$uri regionRect=$regionRect", null) result.error("fetch-read-large-file", "SVG too large at $sizeBytes bytes, for uri=$uri regionRect=$regionRect", null)
return return
} }
@ -67,8 +68,8 @@ class SvgRegionFetcher internal constructor(
val viewBox = svg.documentViewBox val viewBox = svg.documentViewBox
val svgWidth = viewBox.width() val svgWidth = viewBox.width()
val svgHeight = viewBox.height() val svgHeight = viewBox.height()
val xf = imageWidth / ceil(svgWidth) val xf = imageWidth / scale / ceil(svgWidth)
val yf = imageHeight / ceil(svgHeight) val yf = imageHeight / scale / ceil(svgHeight)
// some SVG paths do not respect the rendering viewbox and do not reach its edges // some SVG paths do not respect the rendering viewbox and do not reach its edges
// so we render to a slightly larger bitmap, using a slightly larger viewbox, // so we render to a slightly larger bitmap, using a slightly larger viewbox,
// and crop that bitmap to the target region size // and crop that bitmap to the target region size
@ -87,6 +88,15 @@ class SvgRegionFetcher internal constructor(
val targetBitmapWidth = regionRect.width() val targetBitmapWidth = regionRect.width()
val targetBitmapHeight = regionRect.height() val targetBitmapHeight = regionRect.height()
// use `Long` as rect size could be unexpectedly large and go beyond `Int` max
val targetBitmapSizeBytes: Long = ARGB_8888_BYTE_SIZE.toLong() * targetBitmapWidth * targetBitmapHeight
if (!MemoryUtils.canAllocate(targetBitmapSizeBytes)) {
// decoding a region that large would yield an OOM when creating the bitmap
result.error("fetch-read-large-region", "SVG region too large for uri=$uri regionRect=$regionRect", null)
return
}
var bitmap = Bitmap.createBitmap( var bitmap = Bitmap.createBitmap(
targetBitmapWidth + bleedX * 2, targetBitmapWidth + bleedX * 2,
targetBitmapHeight + bleedY * 2, targetBitmapHeight + bleedY * 2,
@ -106,4 +116,8 @@ class SvgRegionFetcher internal constructor(
val uri: Uri, val uri: Uri,
val svg: SVG, val svg: SVG,
) )
companion object {
const val ARGB_8888_BYTE_SIZE = 4
}
} }

View file

@ -92,7 +92,7 @@ object MimeTypes {
// as of `metadata-extractor` v2.14.0 // as of `metadata-extractor` v2.14.0
fun canReadWithMetadataExtractor(mimeType: String) = when (mimeType) { fun canReadWithMetadataExtractor(mimeType: String) = when (mimeType) {
DJVU, WBMP -> false DJVU, SVG, WBMP -> false
MKV, MP2T, MP2TS, OGV, WEBM -> false MKV, MP2T, MP2TS, OGV, WEBM -> false
else -> true else -> true
} }

View file

@ -1,5 +1,5 @@
<i>أيفيس</i> يمكنه التعامل مع جميع أنواع الصور ومقاطع الفيديو ، بما في ذلك ملفات JPEG و MP4 النموذجية ، ولكن أيضًا أشياء أكثر غرابة مثل <b>ملفات TIFF و SVG و AVI القديمة متعددة الصفحات والمزيد</b>! يقوم بمسح مجموعة الوسائط الخاصة بك لتحديد <b> الصور المتحركة</b>, <b>الإستعراضات</b> (المعروف أيضًا باسم الصور البانورامية), <b>360 درجة مقاطع الفيديو</b>, إلى جانب <b>GeoTIFF</b> الملفات. <i>Aves</i> يمكنه التعامل مع جميع أنواع الصور ومقاطع الفيديو ، بما في ذلك ملفات JPEG و MP4 النموذجية ، ولكن أيضًا أشياء أكثر غرابة مثل <b>ملفات TIFF و SVG و AVI القديمة متعددة الصفحات والمزيد</b>! يقوم بمسح مجموعة الوسائط الخاصة بك لتحديد <b> الصور المتحركة</b>, <b>الإستعراضات</b> (المعروف أيضًا باسم الصور البانورامية), <b>360 درجة مقاطع الفيديو</b>, إلى جانب <b>GeoTIFF</b> الملفات.
<b>الملاحة والبحث</b> جزء مهم من <i>Aves</i>الهدف هو أن يكون بإمكان المستخدمين التنقل بسهولة من الألبومات إلى الصور إلى الوسوم إلى الخرائط، وما إلى ذلك.. <b>الملاحة والبحث</b> جزء مهم من <i>Aves</i>الهدف هو أن يكون بإمكان المستخدمين التنقل بسهولة من الألبومات إلى الصور إلى الوسوم إلى الخرائط، وما إلى ذلك..
<i>Aves</i>تتكامل مع نظام Android (من KitKat إلى Android 14، بما في ذلك Android TV) مع ميزات مثلs <b>الودجتس</b>, <b>اختصارات التطبيق</b>, <b>حافظة الشاشة</b> و<b>البحث العالمي</b> التعامل معه. كما أنه يعمل كـ <b>عارض واختار لوسائط (ملفات الوسائط)</b>. <i>Aves</i>تتكامل مع نظام Android (من KitKat إلى Android 14، بما في ذلك Android TV) مع ميزات مثلs <b>الودجتس</b>, <b>اختصارات التطبيق</b>, <b>حافظة الشاشة</b> و<b>البحث العالمي</b> التعامل معه. كما أنه يعمل كـ <b>عارض الوسائط ومنتقيها</b>.

View file

@ -0,0 +1,4 @@
In v1.10.2:
- JPEG MPF support
- enjoy the app in Arabic & Belarusian
Full changelog available on GitHub

View file

@ -0,0 +1,4 @@
In v1.10.2:
- JPEG MPF support
- enjoy the app in Arabic & Belarusian
Full changelog available on GitHub

View file

@ -51,7 +51,7 @@
"@cancelTooltip": {}, "@cancelTooltip": {},
"previousTooltip": "السابق", "previousTooltip": "السابق",
"@previousTooltip": {}, "@previousTooltip": {},
"welcomeMessage": "مرحبا بكم في أيفيس", "welcomeMessage": "مرحبا بكم في Aves",
"@welcomeMessage": {}, "@welcomeMessage": {},
"applyButtonLabel": "تقديم", "applyButtonLabel": "تقديم",
"@applyButtonLabel": {}, "@applyButtonLabel": {},
@ -77,11 +77,11 @@
"@saveCopyButtonLabel": {}, "@saveCopyButtonLabel": {},
"chipActionFilterOut": "تصفية أو استبعاد", "chipActionFilterOut": "تصفية أو استبعاد",
"@chipActionFilterOut": {}, "@chipActionFilterOut": {},
"chipActionHide": "يخفي", "chipActionHide": "إخفاء",
"@chipActionHide": {}, "@chipActionHide": {},
"sourceStateCataloguing": "تصنيف", "sourceStateCataloguing": "تصنيف",
"@sourceStateCataloguing": {}, "@sourceStateCataloguing": {},
"chipActionDelete": "يمسح", "chipActionDelete": "حَذف",
"@chipActionDelete": {}, "@chipActionDelete": {},
"sourceStateLoading": "تحميل", "sourceStateLoading": "تحميل",
"@sourceStateLoading": {}, "@sourceStateLoading": {},
@ -103,9 +103,9 @@
"@pickTooltip": {}, "@pickTooltip": {},
"chipActionGoToCountryPage": "عرض في الدول", "chipActionGoToCountryPage": "عرض في الدول",
"@chipActionGoToCountryPage": {}, "@chipActionGoToCountryPage": {},
"applyTooltip": "يتقدم", "applyTooltip": "تقدم",
"@applyTooltip": {}, "@applyTooltip": {},
"chipActionUnpin": "إلغاء تثبيت من الأعلى", "chipActionUnpin": "إلغاء التثبيت في الأعلى",
"@chipActionUnpin": {}, "@chipActionUnpin": {},
"chipActionGoToTagPage": "عرض في الوسوم", "chipActionGoToTagPage": "عرض في الوسوم",
"@chipActionGoToTagPage": {}, "@chipActionGoToTagPage": {},
@ -121,7 +121,7 @@
}, },
"settingsNavigationDrawerAddAlbum": "إضافة ألبوم", "settingsNavigationDrawerAddAlbum": "إضافة ألبوم",
"@settingsNavigationDrawerAddAlbum": {}, "@settingsNavigationDrawerAddAlbum": {},
"settingsPrivacySectionTitle": "خصوصية", "settingsPrivacySectionTitle": "الخصوصية",
"@settingsPrivacySectionTitle": {}, "@settingsPrivacySectionTitle": {},
"settingsEnableBinSubtitle": "الاحتفاظ بالعناصر المحذوفة لمدة 30 يومًا", "settingsEnableBinSubtitle": "الاحتفاظ بالعناصر المحذوفة لمدة 30 يومًا",
"@settingsEnableBinSubtitle": {}, "@settingsEnableBinSubtitle": {},
@ -141,7 +141,7 @@
"@entryInfoActionExportMetadata": {}, "@entryInfoActionExportMetadata": {},
"aboutDataUsageMisc": "منوعات", "aboutDataUsageMisc": "منوعات",
"@aboutDataUsageMisc": {}, "@aboutDataUsageMisc": {},
"editorActionTransform": "تحول", "editorActionTransform": "تحويل",
"@editorActionTransform": {}, "@editorActionTransform": {},
"collectionExportFailureFeedback": "{count, plural, =1{فشل تصدير صفحة واحدة} other{فشل التصدير {count} pages}}", "collectionExportFailureFeedback": "{count, plural, =1{فشل تصدير صفحة واحدة} other{فشل التصدير {count} pages}}",
"@collectionExportFailureFeedback": { "@collectionExportFailureFeedback": {
@ -199,7 +199,7 @@
"@tooManyItemsErrorDialogMessage": {}, "@tooManyItemsErrorDialogMessage": {},
"collectionActionEdit": "تحرير", "collectionActionEdit": "تحرير",
"@collectionActionEdit": {}, "@collectionActionEdit": {},
"viewerInfoSearchSuggestionResolution": "دقة", "viewerInfoSearchSuggestionResolution": "الدقة",
"@viewerInfoSearchSuggestionResolution": {}, "@viewerInfoSearchSuggestionResolution": {},
"viewerTransitionSlide": "الإنزلاق", "viewerTransitionSlide": "الإنزلاق",
"@viewerTransitionSlide": {}, "@viewerTransitionSlide": {},
@ -207,7 +207,7 @@
"@sortOrderLargestFirst": {}, "@sortOrderLargestFirst": {},
"viewerTransitionParallax": "تأثير الشبكية", "viewerTransitionParallax": "تأثير الشبكية",
"@viewerTransitionParallax": {}, "@viewerTransitionParallax": {},
"settingsViewerSectionTitle": "عارض", "settingsViewerSectionTitle": "المعرض",
"@settingsViewerSectionTitle": {}, "@settingsViewerSectionTitle": {},
"mapStyleStamenWatercolor": "ستايمن بالألوان المائية", "mapStyleStamenWatercolor": "ستايمن بالألوان المائية",
"@mapStyleStamenWatercolor": {}, "@mapStyleStamenWatercolor": {},
@ -241,7 +241,7 @@
"@coordinateDmsNorth": {}, "@coordinateDmsNorth": {},
"dateYesterday": "أمس", "dateYesterday": "أمس",
"@dateYesterday": {}, "@dateYesterday": {},
"viewerInfoLabelDate": "تاريخ", "viewerInfoLabelDate": "التاريخ",
"@viewerInfoLabelDate": {}, "@viewerInfoLabelDate": {},
"nameConflictStrategyReplace": "إستبدال", "nameConflictStrategyReplace": "إستبدال",
"@nameConflictStrategyReplace": {}, "@nameConflictStrategyReplace": {},
@ -263,7 +263,7 @@
"@settingsSubtitleThemeTextColor": {}, "@settingsSubtitleThemeTextColor": {},
"collectionDeselectSectionTooltip": "قم بإلغاء تحديد القسم", "collectionDeselectSectionTooltip": "قم بإلغاء تحديد القسم",
"@collectionDeselectSectionTooltip": {}, "@collectionDeselectSectionTooltip": {},
"settingsKeepScreenOnTile": "إبقاء شاشة قيد التشغيل", "settingsKeepScreenOnTile": "إبقاء الشاشة قيد التشغيل",
"@settingsKeepScreenOnTile": {}, "@settingsKeepScreenOnTile": {},
"tileLayoutGrid": "شبكة", "tileLayoutGrid": "شبكة",
"@tileLayoutGrid": {}, "@tileLayoutGrid": {},
@ -275,7 +275,7 @@
"@aboutCreditsWorldAtlas1": {}, "@aboutCreditsWorldAtlas1": {},
"nameConflictDialogMultipleSourceMessage": "بعض الملفات لها نفس الاسم.", "nameConflictDialogMultipleSourceMessage": "بعض الملفات لها نفس الاسم.",
"@nameConflictDialogMultipleSourceMessage": {}, "@nameConflictDialogMultipleSourceMessage": {},
"settingsVideoSectionTitle": "فيديو", "settingsVideoSectionTitle": "الفيديو",
"@settingsVideoSectionTitle": {}, "@settingsVideoSectionTitle": {},
"appExportCovers": "أغلفة", "appExportCovers": "أغلفة",
"@appExportCovers": {}, "@appExportCovers": {},
@ -295,7 +295,7 @@
"@settingsThumbnailOverlayTile": {}, "@settingsThumbnailOverlayTile": {},
"settingsNavigationDrawerTabPages": "الصفحات", "settingsNavigationDrawerTabPages": "الصفحات",
"@settingsNavigationDrawerTabPages": {}, "@settingsNavigationDrawerTabPages": {},
"settingsConfirmationDialogTitle": "نوافذ التأكيد الحوار", "settingsConfirmationDialogTitle": "نوافذ تأكيد الحوار",
"@settingsConfirmationDialogTitle": {}, "@settingsConfirmationDialogTitle": {},
"videoStreamSelectionDialogText": "ترجمات", "videoStreamSelectionDialogText": "ترجمات",
"@videoStreamSelectionDialogText": {}, "@videoStreamSelectionDialogText": {},
@ -303,7 +303,7 @@
"@settingsVideoAutoPlay": {}, "@settingsVideoAutoPlay": {},
"settingsVideoEnableHardwareAcceleration": "تسريع الأجهزة", "settingsVideoEnableHardwareAcceleration": "تسريع الأجهزة",
"@settingsVideoEnableHardwareAcceleration": {}, "@settingsVideoEnableHardwareAcceleration": {},
"editEntryDateDialogShift": "يحول", "editEntryDateDialogShift": "تغيير",
"@editEntryDateDialogShift": {}, "@editEntryDateDialogShift": {},
"viewerInfoLabelCoordinates": "الإحداثيات", "viewerInfoLabelCoordinates": "الإحداثيات",
"@viewerInfoLabelCoordinates": {}, "@viewerInfoLabelCoordinates": {},
@ -421,7 +421,7 @@
"@settingsVideoGestureVerticalDragBrightnessVolume": {}, "@settingsVideoGestureVerticalDragBrightnessVolume": {},
"settingsAccessibilitySectionTitle": "إمكانية الوصول", "settingsAccessibilitySectionTitle": "إمكانية الوصول",
"@settingsAccessibilitySectionTitle": {}, "@settingsAccessibilitySectionTitle": {},
"settingsActionExport": "يصدّر", "settingsActionExport": "تصدير",
"@settingsActionExport": {}, "@settingsActionExport": {},
"aboutBugCopyInfoInstruction": "نسخ معلومات النظام", "aboutBugCopyInfoInstruction": "نسخ معلومات النظام",
"@aboutBugCopyInfoInstruction": {}, "@aboutBugCopyInfoInstruction": {},
@ -477,9 +477,9 @@
"@drawerAlbumPage": {}, "@drawerAlbumPage": {},
"statsTopCountriesSectionTitle": "أهم الدول", "statsTopCountriesSectionTitle": "أهم الدول",
"@statsTopCountriesSectionTitle": {}, "@statsTopCountriesSectionTitle": {},
"settingsActionImport": "يستورد", "settingsActionImport": "إستيراد",
"@settingsActionImport": {}, "@settingsActionImport": {},
"viewerInfoLabelSize": "مقاس", "viewerInfoLabelSize": "المقاس",
"@viewerInfoLabelSize": {}, "@viewerInfoLabelSize": {},
"locationPickerUseThisLocationButton": "استخدم هذا الموقع", "locationPickerUseThisLocationButton": "استخدم هذا الموقع",
"@locationPickerUseThisLocationButton": {}, "@locationPickerUseThisLocationButton": {},
@ -559,7 +559,7 @@
}, },
"viewerTransitionZoomIn": "تكبير", "viewerTransitionZoomIn": "تكبير",
"@viewerTransitionZoomIn": {}, "@viewerTransitionZoomIn": {},
"drawerCollectionAll": "كل جمع", "drawerCollectionAll": "كافة الوسائط",
"@drawerCollectionAll": {}, "@drawerCollectionAll": {},
"collectionMoveSuccessFeedback": "{count, plural, =1{تم نقل عنصر واحد} other{نقل {count} عناصر}}", "collectionMoveSuccessFeedback": "{count, plural, =1{تم نقل عنصر واحد} other{نقل {count} عناصر}}",
"@collectionMoveSuccessFeedback": { "@collectionMoveSuccessFeedback": {
@ -595,7 +595,7 @@
"@menuActionMap": {}, "@menuActionMap": {},
"entryInfoActionRemoveMetadata": "إزالة البيانات الوصفية", "entryInfoActionRemoveMetadata": "إزالة البيانات الوصفية",
"@entryInfoActionRemoveMetadata": {}, "@entryInfoActionRemoveMetadata": {},
"collectionActionMove": "الانتقال إلى الألبوم", "collectionActionMove": "نقل إلى الألبوم",
"@collectionActionMove": {}, "@collectionActionMove": {},
"searchAlbumsSectionTitle": "الألبومات", "searchAlbumsSectionTitle": "الألبومات",
"@searchAlbumsSectionTitle": {}, "@searchAlbumsSectionTitle": {},
@ -665,7 +665,7 @@
"@viewerInfoSearchSuggestionDate": {}, "@viewerInfoSearchSuggestionDate": {},
"videoPlaybackWithSound": "تشغيل بالصوت", "videoPlaybackWithSound": "تشغيل بالصوت",
"@videoPlaybackWithSound": {}, "@videoPlaybackWithSound": {},
"viewerInfoLabelTitle": "عنوان", "viewerInfoLabelTitle": "العنوان",
"@viewerInfoLabelTitle": {}, "@viewerInfoLabelTitle": {},
"searchCollectionFieldHint": "البحث في المجموعة", "searchCollectionFieldHint": "البحث في المجموعة",
"@searchCollectionFieldHint": {}, "@searchCollectionFieldHint": {},
@ -851,7 +851,7 @@
"@albumTierPinned": {}, "@albumTierPinned": {},
"mapStyleDialogTitle": "نمط الخريطة", "mapStyleDialogTitle": "نمط الخريطة",
"@mapStyleDialogTitle": {}, "@mapStyleDialogTitle": {},
"entryActionRotateCCW": "تدوير باتجاه عقارب الساعة", "entryActionRotateCCW": "تدوير عكس عقارب الساعة",
"@entryActionRotateCCW": {}, "@entryActionRotateCCW": {},
"settingsVideoBackgroundMode": "وضع الخلفية", "settingsVideoBackgroundMode": "وضع الخلفية",
"@settingsVideoBackgroundMode": {}, "@settingsVideoBackgroundMode": {},
@ -869,7 +869,7 @@
"@entryActionShowGeoTiffOnMap": {}, "@entryActionShowGeoTiffOnMap": {},
"viewDialogReverseSortOrder": "عكس ترتيب الفرز", "viewDialogReverseSortOrder": "عكس ترتيب الفرز",
"@viewDialogReverseSortOrder": {}, "@viewDialogReverseSortOrder": {},
"menuActionConfigureView": "رؤية", "menuActionConfigureView": "العرض",
"@menuActionConfigureView": {}, "@menuActionConfigureView": {},
"aboutLicensesDartPackagesSectionTitle": "حزم البرمجة", "aboutLicensesDartPackagesSectionTitle": "حزم البرمجة",
"@aboutLicensesDartPackagesSectionTitle": {}, "@aboutLicensesDartPackagesSectionTitle": {},
@ -933,7 +933,7 @@
"@settingsThumbnailShowVideoDuration": {}, "@settingsThumbnailShowVideoDuration": {},
"passwordDialogConfirm": "تأكيد كلمة السر", "passwordDialogConfirm": "تأكيد كلمة السر",
"@passwordDialogConfirm": {}, "@passwordDialogConfirm": {},
"videoActionReplay10": "تقدم الخلفي لمدة 10 ثوانٍ", "videoActionReplay10": "الرجوع للخلف لمدة 10 ثوانٍ",
"@videoActionReplay10": {}, "@videoActionReplay10": {},
"settingsCollectionBurstPatternsNone": "لا شيء", "settingsCollectionBurstPatternsNone": "لا شيء",
"@settingsCollectionBurstPatternsNone": {}, "@settingsCollectionBurstPatternsNone": {},
@ -989,7 +989,7 @@
"@entryActionOpen": {}, "@entryActionOpen": {},
"settingsCoordinateFormatTile": "تنسيق الإحداثيات", "settingsCoordinateFormatTile": "تنسيق الإحداثيات",
"@settingsCoordinateFormatTile": {}, "@settingsCoordinateFormatTile": {},
"newVaultWarningDialogMessage": "العناصر الموجودة في الخزائن متاحة فقط لهذا التطبيق وليس للتطبيقات الأخرى.\n\nإذا قمت بإلغاء تثبيت هذا التطبيق، أو قمت بمسح بيانات هذا التطبيق، فسوف تفقد كل هذه العناصر.", "newVaultWarningDialogMessage": "العناصر الموجودة في الخزائن متاحة فقط لهذا التطبيق وليس للتطبيقات الأخرى.\n\nإذا قمت بإلغاء تثبيت هذا التطبيق، أو قمت بحذف بيانات هذا التطبيق، فسوف تفقد كل هذه العناصر.",
"@newVaultWarningDialogMessage": {}, "@newVaultWarningDialogMessage": {},
"settingsViewerQuickActionEditorBanner": "المس مع الاستمرار لتحريك الأزرار وتحديد الإجراءات التي سيتم عرضها في العارض.", "settingsViewerQuickActionEditorBanner": "المس مع الاستمرار لتحريك الأزرار وتحديد الإجراءات التي سيتم عرضها في العارض.",
"@settingsViewerQuickActionEditorBanner": {}, "@settingsViewerQuickActionEditorBanner": {},
@ -1139,11 +1139,11 @@
"@settingsStorageAccessEmpty": {}, "@settingsStorageAccessEmpty": {},
"settingsRemoveAnimationsTile": "إزالة الرسوم المتحركة", "settingsRemoveAnimationsTile": "إزالة الرسوم المتحركة",
"@settingsRemoveAnimationsTile": {}, "@settingsRemoveAnimationsTile": {},
"settingsStorageAccessBanner": "تتطلب بعض الدلائل منح وصول صريح لتعديل الملفات الموجودة فيها. يمكنك هنا مراجعة الدلائل التي منحتها حق الوصول إليها مسبقًا.", "settingsStorageAccessBanner": "تتطلب بعض المسارات منح وصول صريح لتعديل الملفات الموجودة فيها. يمكنك هنا مراجعة المسارات التي منحتها حق الوصول إليها مسبقًا.",
"@settingsStorageAccessBanner": {}, "@settingsStorageAccessBanner": {},
"authenticateToConfigureVault": "قم بالمصادقة لتكوين المخزن", "authenticateToConfigureVault": "قم بالمصادقة لتكوين الخزنة",
"@authenticateToConfigureVault": {}, "@authenticateToConfigureVault": {},
"settingsActionExportDialogTitle": "يصدّر", "settingsActionExportDialogTitle": "تصدير",
"@settingsActionExportDialogTitle": {}, "@settingsActionExportDialogTitle": {},
"genericDangerWarningDialogMessage": "هل أنت متأكد؟", "genericDangerWarningDialogMessage": "هل أنت متأكد؟",
"@genericDangerWarningDialogMessage": {}, "@genericDangerWarningDialogMessage": {},
@ -1197,13 +1197,13 @@
"@settingsViewerShowMinimap": {}, "@settingsViewerShowMinimap": {},
"settingsCollectionBurstPatternsTile": "أنماط الانفجار", "settingsCollectionBurstPatternsTile": "أنماط الانفجار",
"@settingsCollectionBurstPatternsTile": {}, "@settingsCollectionBurstPatternsTile": {},
"viewerInfoLabelPath": "الطريق", "viewerInfoLabelPath": "المسار",
"@viewerInfoLabelPath": {}, "@viewerInfoLabelPath": {},
"albumGroupVolume": "حسب حجم التخزين", "albumGroupVolume": "حسب حجم التخزين",
"@albumGroupVolume": {}, "@albumGroupVolume": {},
"collectionGroupMonth": "حسب الشهر", "collectionGroupMonth": "حسب الشهر",
"@collectionGroupMonth": {}, "@collectionGroupMonth": {},
"viewerInfoLabelResolution": "دقة", "viewerInfoLabelResolution": "الدقة",
"@viewerInfoLabelResolution": {}, "@viewerInfoLabelResolution": {},
"renameProcessorCounter": "عداد", "renameProcessorCounter": "عداد",
"@renameProcessorCounter": {}, "@renameProcessorCounter": {},
@ -1217,7 +1217,7 @@
"@sortByDate": {}, "@sortByDate": {},
"statsTopAlbumsSectionTitle": "أهم الألبومات", "statsTopAlbumsSectionTitle": "أهم الألبومات",
"@statsTopAlbumsSectionTitle": {}, "@statsTopAlbumsSectionTitle": {},
"configureVaultDialogTitle": "تكوين قبو", "configureVaultDialogTitle": "تكوين خزنة",
"@configureVaultDialogTitle": {}, "@configureVaultDialogTitle": {},
"entryActionRename": "إعادة تسمية", "entryActionRename": "إعادة تسمية",
"@entryActionRename": {}, "@entryActionRename": {},
@ -1229,7 +1229,7 @@
"@keepScreenOnNever": {}, "@keepScreenOnNever": {},
"statsPageTitle": "احصائيات", "statsPageTitle": "احصائيات",
"@statsPageTitle": {}, "@statsPageTitle": {},
"viewerInfoSearchSuggestionDimensions": "أبعاد", "viewerInfoSearchSuggestionDimensions": "الأبعاد",
"@viewerInfoSearchSuggestionDimensions": {}, "@viewerInfoSearchSuggestionDimensions": {},
"mapStyleOsmHot": "خرائط OSM", "mapStyleOsmHot": "خرائط OSM",
"@mapStyleOsmHot": {}, "@mapStyleOsmHot": {},
@ -1255,7 +1255,7 @@
}, },
"sortBySize": "حسب الحجم", "sortBySize": "حسب الحجم",
"@sortBySize": {}, "@sortBySize": {},
"viewerInfoSearchSuggestionDescription": "وصف", "viewerInfoSearchSuggestionDescription": "الوصف",
"@viewerInfoSearchSuggestionDescription": {}, "@viewerInfoSearchSuggestionDescription": {},
"settingsViewerShowOverlayThumbnails": "عرض الصور المصغرة", "settingsViewerShowOverlayThumbnails": "عرض الصور المصغرة",
"@settingsViewerShowOverlayThumbnails": {}, "@settingsViewerShowOverlayThumbnails": {},
@ -1347,7 +1347,7 @@
"@settingsSubtitleThemeBackgroundOpacity": {}, "@settingsSubtitleThemeBackgroundOpacity": {},
"settingsStorageAccessTile": "الوصول إلى التخزين", "settingsStorageAccessTile": "الوصول إلى التخزين",
"@settingsStorageAccessTile": {}, "@settingsStorageAccessTile": {},
"entryActionDelete": "مسح", "entryActionDelete": "حذف",
"@entryActionDelete": {}, "@entryActionDelete": {},
"settingsThemeBrightnessTile": "السمَة", "settingsThemeBrightnessTile": "السمَة",
"@settingsThemeBrightnessTile": {}, "@settingsThemeBrightnessTile": {},
@ -1401,7 +1401,7 @@
}, },
"videoResumeButtonLabel": "إستئناف", "videoResumeButtonLabel": "إستئناف",
"@videoResumeButtonLabel": {}, "@videoResumeButtonLabel": {},
"entryActionExport": "تصدير", "entryActionExport": "المزيد",
"@entryActionExport": {}, "@entryActionExport": {},
"mapEmptyRegion": "لا توجد صور في هذه المنطقة", "mapEmptyRegion": "لا توجد صور في هذه المنطقة",
"@mapEmptyRegion": {}, "@mapEmptyRegion": {},
@ -1421,7 +1421,7 @@
"@entryActionAddFavourite": {}, "@entryActionAddFavourite": {},
"entryActionEdit": "تحرير", "entryActionEdit": "تحرير",
"@entryActionEdit": {}, "@entryActionEdit": {},
"newVaultDialogTitle": "قبو جديد", "newVaultDialogTitle": "خزنة جديدة",
"@newVaultDialogTitle": {}, "@newVaultDialogTitle": {},
"entryInfoActionEditRating": "تحرير التقييم", "entryInfoActionEditRating": "تحرير التقييم",
"@entryInfoActionEditRating": {}, "@entryInfoActionEditRating": {},
@ -1447,7 +1447,7 @@
"@settingsVideoBackgroundModeDialogTitle": {}, "@settingsVideoBackgroundModeDialogTitle": {},
"binPageTitle": "سلة المحذوفات", "binPageTitle": "سلة المحذوفات",
"@binPageTitle": {}, "@binPageTitle": {},
"tagPlaceholderState": "ولاية", "tagPlaceholderState": "الولاية",
"@tagPlaceholderState": {}, "@tagPlaceholderState": {},
"sortByAlbumFileName": "حسب الألبوم واسم الملف", "sortByAlbumFileName": "حسب الألبوم واسم الملف",
"@sortByAlbumFileName": {}, "@sortByAlbumFileName": {},
@ -1481,7 +1481,7 @@
"@appPickDialogTitle": {}, "@appPickDialogTitle": {},
"settingsHiddenItemsTabPaths": "المسارات المخفية", "settingsHiddenItemsTabPaths": "المسارات المخفية",
"@settingsHiddenItemsTabPaths": {}, "@settingsHiddenItemsTabPaths": {},
"viewerInfoSearchSuggestionRights": "حقوق", "viewerInfoSearchSuggestionRights": "الحقوق",
"@viewerInfoSearchSuggestionRights": {}, "@viewerInfoSearchSuggestionRights": {},
"mapPointNorthUpTooltip": "نقطة الشمال لأعلى", "mapPointNorthUpTooltip": "نقطة الشمال لأعلى",
"@mapPointNorthUpTooltip": {}, "@mapPointNorthUpTooltip": {},
@ -1497,7 +1497,7 @@
"@entryActionShareImageOnly": {}, "@entryActionShareImageOnly": {},
"settingsVideoButtonsTile": "أزرار", "settingsVideoButtonsTile": "أزرار",
"@settingsVideoButtonsTile": {}, "@settingsVideoButtonsTile": {},
"settingsSubtitleThemeSample": "هذه عينة.", "settingsSubtitleThemeSample": "هذه عينة بسيطة.",
"@settingsSubtitleThemeSample": {}, "@settingsSubtitleThemeSample": {},
"albumPickPageTitleMove": "انتقل إلى الألبوم", "albumPickPageTitleMove": "انتقل إلى الألبوم",
"@albumPickPageTitleMove": {}, "@albumPickPageTitleMove": {},

View file

@ -222,7 +222,7 @@
"@filterRecentlyAddedLabel": {}, "@filterRecentlyAddedLabel": {},
"filterTypeAnimatedLabel": "Аніміраваныя", "filterTypeAnimatedLabel": "Аніміраваныя",
"@filterTypeAnimatedLabel": {}, "@filterTypeAnimatedLabel": {},
"filterTypeRawLabel": "Без апрацоўкі", "filterTypeRawLabel": "Raw",
"@filterTypeRawLabel": {}, "@filterTypeRawLabel": {},
"filterTypeSphericalVideoLabel": "Відэа 360°", "filterTypeSphericalVideoLabel": "Відэа 360°",
"@filterTypeSphericalVideoLabel": {}, "@filterTypeSphericalVideoLabel": {},
@ -257,7 +257,7 @@
"@coordinateFormatDecimal": {}, "@coordinateFormatDecimal": {},
"subtitlePositionBottom": "Ніз", "subtitlePositionBottom": "Ніз",
"@subtitlePositionBottom": {}, "@subtitlePositionBottom": {},
"videoControlsPlaySeek": "Прайграванне і перамотка назад/уперад", "videoControlsPlaySeek": "Прайграванне і пераход на пазіцыю",
"@videoControlsPlaySeek": {}, "@videoControlsPlaySeek": {},
"nameConflictStrategyReplace": "Замяніць", "nameConflictStrategyReplace": "Замяніць",
"@nameConflictStrategyReplace": {}, "@nameConflictStrategyReplace": {},
@ -351,9 +351,9 @@
"@themeBrightnessDark": {}, "@themeBrightnessDark": {},
"themeBrightnessBlack": "Чорная", "themeBrightnessBlack": "Чорная",
"@themeBrightnessBlack": {}, "@themeBrightnessBlack": {},
"unitSystemMetric": "Метрычныя адзінкі вымярэння", "unitSystemMetric": "Метрычныя",
"@unitSystemMetric": {}, "@unitSystemMetric": {},
"unitSystemImperial": "Імперская", "unitSystemImperial": "Англійскія",
"@unitSystemImperial": {}, "@unitSystemImperial": {},
"vaultLockTypePattern": "Шаблон", "vaultLockTypePattern": "Шаблон",
"@vaultLockTypePattern": {}, "@vaultLockTypePattern": {},
@ -365,7 +365,7 @@
"@settingsVideoEnablePip": {}, "@settingsVideoEnablePip": {},
"videoControlsPlayOutside": "Адкрыць у іншым прайгравальніку", "videoControlsPlayOutside": "Адкрыць у іншым прайгравальніку",
"@videoControlsPlayOutside": {}, "@videoControlsPlayOutside": {},
"videoControlsPlay": "Прайграць", "videoControlsPlay": "Прайграванне",
"@videoControlsPlay": {}, "@videoControlsPlay": {},
"videoLoopModeNever": "Ніколі", "videoLoopModeNever": "Ніколі",
"@videoLoopModeNever": {}, "@videoLoopModeNever": {},
@ -373,9 +373,9 @@
"@videoLoopModeShortOnly": {}, "@videoLoopModeShortOnly": {},
"videoPlaybackSkip": "Прапусціць", "videoPlaybackSkip": "Прапусціць",
"@videoPlaybackSkip": {}, "@videoPlaybackSkip": {},
"videoPlaybackMuted": "Гуляць без гука", "videoPlaybackMuted": "Прайграваць без гуку",
"@videoPlaybackMuted": {}, "@videoPlaybackMuted": {},
"videoPlaybackWithSound": "Гуляць з гукам", "videoPlaybackWithSound": "Прайграваць з гукам",
"@videoPlaybackWithSound": {}, "@videoPlaybackWithSound": {},
"videoResumptionModeNever": "Ніколі", "videoResumptionModeNever": "Ніколі",
"@videoResumptionModeNever": {}, "@videoResumptionModeNever": {},
@ -597,7 +597,7 @@
"@viewerInfoSearchSuggestionResolution": {}, "@viewerInfoSearchSuggestionResolution": {},
"viewerInfoSearchSuggestionDimensions": "Памеры", "viewerInfoSearchSuggestionDimensions": "Памеры",
"@viewerInfoSearchSuggestionDimensions": {}, "@viewerInfoSearchSuggestionDimensions": {},
"videoControlsNone": "Без", "videoControlsNone": "Нічога",
"@videoControlsNone": {}, "@videoControlsNone": {},
"viewerErrorUnknown": "Ой!", "viewerErrorUnknown": "Ой!",
"@viewerErrorUnknown": {}, "@viewerErrorUnknown": {},

View file

@ -1021,7 +1021,7 @@
"@settingsScreenSaverPageTitle": {}, "@settingsScreenSaverPageTitle": {},
"settingsWidgetPageTitle": "Bilderrahmen", "settingsWidgetPageTitle": "Bilderrahmen",
"@settingsWidgetPageTitle": {}, "@settingsWidgetPageTitle": {},
"settingsWidgetShowOutline": "Gliederung", "settingsWidgetShowOutline": "Umrandung",
"@settingsWidgetShowOutline": {}, "@settingsWidgetShowOutline": {},
"settingsWidgetOpenPage": "Beim Tippen auf das Widget", "settingsWidgetOpenPage": "Beim Tippen auf das Widget",
"@settingsWidgetOpenPage": {}, "@settingsWidgetOpenPage": {},
@ -1331,7 +1331,7 @@
"@cropAspectRatioOriginal": {}, "@cropAspectRatioOriginal": {},
"cropAspectRatioSquare": "Quadrat", "cropAspectRatioSquare": "Quadrat",
"@cropAspectRatioSquare": {}, "@cropAspectRatioSquare": {},
"widgetTapUpdateWidget": "Widget öffnen", "widgetTapUpdateWidget": "Widget aktualisieren",
"@widgetTapUpdateWidget": {}, "@widgetTapUpdateWidget": {},
"aboutDataUsageSectionTitle": "Datennutzung", "aboutDataUsageSectionTitle": "Datennutzung",
"@aboutDataUsageSectionTitle": {}, "@aboutDataUsageSectionTitle": {},

View file

@ -601,7 +601,7 @@
"@collectionEmptyFavourites": {}, "@collectionEmptyFavourites": {},
"collectionEmptyVideos": "Nenhum video", "collectionEmptyVideos": "Nenhum video",
"@collectionEmptyVideos": {}, "@collectionEmptyVideos": {},
"collectionEmptyImages": "Nenhuma image", "collectionEmptyImages": "Nenhuma imagem",
"@collectionEmptyImages": {}, "@collectionEmptyImages": {},
"collectionEmptyGrantAccessButtonLabel": "Garantir acesso", "collectionEmptyGrantAccessButtonLabel": "Garantir acesso",
"@collectionEmptyGrantAccessButtonLabel": {}, "@collectionEmptyGrantAccessButtonLabel": {},
@ -1356,5 +1356,9 @@
"settingsViewerShowHistogram": "Mostrar histograma", "settingsViewerShowHistogram": "Mostrar histograma",
"@settingsViewerShowHistogram": {}, "@settingsViewerShowHistogram": {},
"aboutDataUsageClearCache": "Limpar o cache", "aboutDataUsageClearCache": "Limpar o cache",
"@aboutDataUsageClearCache": {} "@aboutDataUsageClearCache": {},
"entryActionCast": "Transmitir",
"@entryActionCast": {},
"castDialogTitle": "Dispositivos para Transmitir",
"@castDialogTitle": {}
} }

View file

@ -249,7 +249,7 @@
"@subtitlePositionBottom": {}, "@subtitlePositionBottom": {},
"videoPlaybackSkip": "Пропустити", "videoPlaybackSkip": "Пропустити",
"@videoPlaybackSkip": {}, "@videoPlaybackSkip": {},
"videoPlaybackMuted": "Відтворити з вимкненим звуком", "videoPlaybackMuted": "Відтворити без звуку",
"@videoPlaybackMuted": {}, "@videoPlaybackMuted": {},
"videoPlaybackWithSound": "Відтворити зі звуком", "videoPlaybackWithSound": "Відтворити зі звуком",
"@videoPlaybackWithSound": {}, "@videoPlaybackWithSound": {},

View file

@ -3,7 +3,9 @@ import 'dart:ui';
int highestPowerOf2(num x) => x < 1 ? 0 : pow(2, (log(x) / ln2).floor()).toInt(); int highestPowerOf2(num x) => x < 1 ? 0 : pow(2, (log(x) / ln2).floor()).toInt();
int smallestPowerOf2(num x) => x < 1 ? 1 : pow(2, (log(x) / ln2).ceil()).toInt(); num smallestPowerOf2(num x, {bool allowNegativePower = false}) {
return x < 1 && !allowNegativePower ? 1 : pow(2, (log(x) / ln2).ceil());
}
double roundToPrecision(final double value, {required final int decimals}) => (value * pow(10, decimals)).round() / pow(10, decimals); double roundToPrecision(final double value, {required final int decimals}) => (value * pow(10, decimals)).round() / pow(10, decimals);

View file

@ -439,7 +439,7 @@ class _GeoMapState extends State<GeoMap> {
if (points.length != geoEntry.pointsSize) { if (points.length != geoEntry.pointsSize) {
// `Fluster.points()` method does not always return all the points contained in a cluster // `Fluster.points()` method does not always return all the points contained in a cluster
// the higher `nodeSize` is, the higher the chance to get all the points (i.e. as many as the cluster `pointsSize`) // the higher `nodeSize` is, the higher the chance to get all the points (i.e. as many as the cluster `pointsSize`)
_slowMarkerCluster ??= _buildFluster(nodeSize: smallestPowerOf2(entries.length)); _slowMarkerCluster ??= _buildFluster(nodeSize: smallestPowerOf2(entries.length).toInt());
points = _slowMarkerCluster!.points(clusterId); points = _slowMarkerCluster!.points(clusterId);
assert(points.length == geoEntry.pointsSize, 'got ${points.length}/${geoEntry.pointsSize} for geoEntry=$geoEntry'); assert(points.length == geoEntry.pointsSize, 'got ${points.length}/${geoEntry.pointsSize} for geoEntry=$geoEntry');
} }

View file

@ -186,7 +186,10 @@ class _BottomOverlayContentState extends State<_BottomOverlayContent> {
builder: (context, child) { builder: (context, child) {
final viewInsetsPadding = (widget.viewInsets ?? EdgeInsets.zero) + (widget.viewPadding ?? EdgeInsets.zero); final viewInsetsPadding = (widget.viewInsets ?? EdgeInsets.zero) + (widget.viewPadding ?? EdgeInsets.zero);
final selection = context.read<Selection<AvesEntry>?>(); final selection = context.read<Selection<AvesEntry>?>();
final viewerButtonRow = (selection?.isSelecting ?? false) final viewerButtonRow = Directionality(
// always keep action buttons in the lower right corner, even with RTL locales
textDirection: TextDirection.ltr,
child: (selection?.isSelecting ?? false)
? SelectionButton( ? SelectionButton(
mainEntry: mainEntry, mainEntry: mainEntry,
scale: _buttonScale, scale: _buttonScale,
@ -220,6 +223,7 @@ class _BottomOverlayContentState extends State<_BottomOverlayContent> {
scale: _buttonScale, scale: _buttonScale,
), ),
), ),
),
); );
final showMultiPageOverlay = mainEntry.isMultiPage && multiPageController != null; final showMultiPageOverlay = mainEntry.isMultiPage && multiPageController != null;
@ -247,6 +251,8 @@ class _BottomOverlayContentState extends State<_BottomOverlayContent> {
(showMultiPageOverlay && collapsedPageScroller) (showMultiPageOverlay && collapsedPageScroller)
? Row( ? Row(
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
// always keep action buttons in the lower right corner, even with RTL locales
textDirection: TextDirection.ltr,
children: [ children: [
SafeArea( SafeArea(
top: false, top: false,

View file

@ -40,7 +40,10 @@ class _VideoControlOverlayState extends State<VideoControlOverlay> with SingleTi
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return StreamBuilder<VideoStatus>( return Directionality(
// always keep action buttons in the lower right corner, even with RTL locales
textDirection: TextDirection.ltr,
child: StreamBuilder<VideoStatus>(
stream: statusStream, stream: statusStream,
builder: (context, snapshot) { builder: (context, snapshot) {
// do not use stream snapshot because it is obsolete when switching between videos // do not use stream snapshot because it is obsolete when switching between videos
@ -78,6 +81,7 @@ class _VideoControlOverlayState extends State<VideoControlOverlay> with SingleTi
], ],
); );
}, },
),
); );
} }
} }

View file

@ -286,7 +286,7 @@ class _VectorImageViewState extends State<VectorImageView> {
required double scale, required double scale,
required double devicePixelRatio, required double devicePixelRatio,
}) => }) =>
smallestPowerOf2(scale * devicePixelRatio).toDouble(); smallestPowerOf2(scale * devicePixelRatio, allowNegativePower: true).toDouble();
} }
typedef _BackgroundFrameBuilder = Widget Function(Widget child, int? frame, Rect tileRect); typedef _BackgroundFrameBuilder = Widget Function(Widget child, int? frame, Rect tileRect);

View file

@ -7,7 +7,7 @@ repository: https://github.com/deckerst/aves
# - play changelog: /whatsnew/whatsnew-en-US # - play changelog: /whatsnew/whatsnew-en-US
# - izzy changelog: /fastlane/metadata/android/en-US/changelogs/XXX01.txt # - izzy changelog: /fastlane/metadata/android/en-US/changelogs/XXX01.txt
# - libre changelog: /fastlane/metadata/android/en-US/changelogs/XXX.txt # - libre changelog: /fastlane/metadata/android/en-US/changelogs/XXX.txt
version: 1.10.1+110 version: 1.10.2+111
publish_to: none publish_to: none
environment: environment:

View file

@ -20,6 +20,8 @@ void main() {
expect(smallestPowerOf2(-42), 1); expect(smallestPowerOf2(-42), 1);
expect(smallestPowerOf2(.5), 1); expect(smallestPowerOf2(.5), 1);
expect(smallestPowerOf2(1.5), 2); expect(smallestPowerOf2(1.5), 2);
expect(smallestPowerOf2(0.5, allowNegativePower: true), 0.5);
expect(smallestPowerOf2(0.1, allowNegativePower: true), 0.125);
}); });
test('rounding to a given precision after the decimal', () { test('rounding to a given precision after the decimal', () {

View file

@ -6457,11 +6457,6 @@
"filePickerUseThisFolder" "filePickerUseThisFolder"
], ],
"pt": [
"entryActionCast",
"castDialogTitle"
],
"ro": [ "ro": [
"saveCopyButtonLabel", "saveCopyButtonLabel",
"applyTooltip", "applyTooltip",

View file

@ -1,4 +1,4 @@
In v1.10.1: In v1.10.2:
- JPEG MPF support - JPEG MPF support
- enjoy the app in Arabic & Belarusian - enjoy the app in Arabic & Belarusian
Full changelog available on GitHub Full changelog available on GitHub