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="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
- Cataloguing: detect/filter `Ultra HDR`

View file

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

View file

@ -25,6 +25,7 @@ class SvgRegionFetcher internal constructor(
suspend fun fetch(
uri: Uri,
sizeBytes: Long?,
scale: Int,
regionRect: Rect,
imageWidth: Int,
imageHeight: Int,
@ -32,7 +33,7 @@ class SvgRegionFetcher internal constructor(
) {
if (!MemoryUtils.canAllocate(sizeBytes)) {
// 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
}
@ -67,8 +68,8 @@ class SvgRegionFetcher internal constructor(
val viewBox = svg.documentViewBox
val svgWidth = viewBox.width()
val svgHeight = viewBox.height()
val xf = imageWidth / ceil(svgWidth)
val yf = imageHeight / ceil(svgHeight)
val xf = imageWidth / scale / ceil(svgWidth)
val yf = imageHeight / scale / ceil(svgHeight)
// 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,
// and crop that bitmap to the target region size
@ -87,6 +88,15 @@ class SvgRegionFetcher internal constructor(
val targetBitmapWidth = regionRect.width()
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(
targetBitmapWidth + bleedX * 2,
targetBitmapHeight + bleedY * 2,
@ -106,4 +116,8 @@ class SvgRegionFetcher internal constructor(
val uri: Uri,
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
fun canReadWithMetadataExtractor(mimeType: String) = when (mimeType) {
DJVU, WBMP -> false
DJVU, SVG, WBMP -> false
MKV, MP2T, MP2TS, OGV, WEBM -> false
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>الهدف هو أن يكون بإمكان المستخدمين التنقل بسهولة من الألبومات إلى الصور إلى الوسوم إلى الخرائط، وما إلى ذلك..
<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": {},
"previousTooltip": "السابق",
"@previousTooltip": {},
"welcomeMessage": "مرحبا بكم في أيفيس",
"welcomeMessage": "مرحبا بكم في Aves",
"@welcomeMessage": {},
"applyButtonLabel": "تقديم",
"@applyButtonLabel": {},
@ -77,11 +77,11 @@
"@saveCopyButtonLabel": {},
"chipActionFilterOut": "تصفية أو استبعاد",
"@chipActionFilterOut": {},
"chipActionHide": "يخفي",
"chipActionHide": "إخفاء",
"@chipActionHide": {},
"sourceStateCataloguing": "تصنيف",
"@sourceStateCataloguing": {},
"chipActionDelete": "يمسح",
"chipActionDelete": "حَذف",
"@chipActionDelete": {},
"sourceStateLoading": "تحميل",
"@sourceStateLoading": {},
@ -103,9 +103,9 @@
"@pickTooltip": {},
"chipActionGoToCountryPage": "عرض في الدول",
"@chipActionGoToCountryPage": {},
"applyTooltip": "يتقدم",
"applyTooltip": "تقدم",
"@applyTooltip": {},
"chipActionUnpin": "إلغاء تثبيت من الأعلى",
"chipActionUnpin": "إلغاء التثبيت في الأعلى",
"@chipActionUnpin": {},
"chipActionGoToTagPage": "عرض في الوسوم",
"@chipActionGoToTagPage": {},
@ -121,7 +121,7 @@
},
"settingsNavigationDrawerAddAlbum": "إضافة ألبوم",
"@settingsNavigationDrawerAddAlbum": {},
"settingsPrivacySectionTitle": "خصوصية",
"settingsPrivacySectionTitle": "الخصوصية",
"@settingsPrivacySectionTitle": {},
"settingsEnableBinSubtitle": "الاحتفاظ بالعناصر المحذوفة لمدة 30 يومًا",
"@settingsEnableBinSubtitle": {},
@ -141,7 +141,7 @@
"@entryInfoActionExportMetadata": {},
"aboutDataUsageMisc": "منوعات",
"@aboutDataUsageMisc": {},
"editorActionTransform": "تحول",
"editorActionTransform": "تحويل",
"@editorActionTransform": {},
"collectionExportFailureFeedback": "{count, plural, =1{فشل تصدير صفحة واحدة} other{فشل التصدير {count} pages}}",
"@collectionExportFailureFeedback": {
@ -199,7 +199,7 @@
"@tooManyItemsErrorDialogMessage": {},
"collectionActionEdit": "تحرير",
"@collectionActionEdit": {},
"viewerInfoSearchSuggestionResolution": "دقة",
"viewerInfoSearchSuggestionResolution": "الدقة",
"@viewerInfoSearchSuggestionResolution": {},
"viewerTransitionSlide": "الإنزلاق",
"@viewerTransitionSlide": {},
@ -207,7 +207,7 @@
"@sortOrderLargestFirst": {},
"viewerTransitionParallax": "تأثير الشبكية",
"@viewerTransitionParallax": {},
"settingsViewerSectionTitle": "عارض",
"settingsViewerSectionTitle": "المعرض",
"@settingsViewerSectionTitle": {},
"mapStyleStamenWatercolor": "ستايمن بالألوان المائية",
"@mapStyleStamenWatercolor": {},
@ -241,7 +241,7 @@
"@coordinateDmsNorth": {},
"dateYesterday": "أمس",
"@dateYesterday": {},
"viewerInfoLabelDate": "تاريخ",
"viewerInfoLabelDate": "التاريخ",
"@viewerInfoLabelDate": {},
"nameConflictStrategyReplace": "إستبدال",
"@nameConflictStrategyReplace": {},
@ -263,7 +263,7 @@
"@settingsSubtitleThemeTextColor": {},
"collectionDeselectSectionTooltip": "قم بإلغاء تحديد القسم",
"@collectionDeselectSectionTooltip": {},
"settingsKeepScreenOnTile": "إبقاء شاشة قيد التشغيل",
"settingsKeepScreenOnTile": "إبقاء الشاشة قيد التشغيل",
"@settingsKeepScreenOnTile": {},
"tileLayoutGrid": "شبكة",
"@tileLayoutGrid": {},
@ -275,7 +275,7 @@
"@aboutCreditsWorldAtlas1": {},
"nameConflictDialogMultipleSourceMessage": "بعض الملفات لها نفس الاسم.",
"@nameConflictDialogMultipleSourceMessage": {},
"settingsVideoSectionTitle": "فيديو",
"settingsVideoSectionTitle": "الفيديو",
"@settingsVideoSectionTitle": {},
"appExportCovers": "أغلفة",
"@appExportCovers": {},
@ -295,7 +295,7 @@
"@settingsThumbnailOverlayTile": {},
"settingsNavigationDrawerTabPages": "الصفحات",
"@settingsNavigationDrawerTabPages": {},
"settingsConfirmationDialogTitle": "نوافذ التأكيد الحوار",
"settingsConfirmationDialogTitle": "نوافذ تأكيد الحوار",
"@settingsConfirmationDialogTitle": {},
"videoStreamSelectionDialogText": "ترجمات",
"@videoStreamSelectionDialogText": {},
@ -303,7 +303,7 @@
"@settingsVideoAutoPlay": {},
"settingsVideoEnableHardwareAcceleration": "تسريع الأجهزة",
"@settingsVideoEnableHardwareAcceleration": {},
"editEntryDateDialogShift": "يحول",
"editEntryDateDialogShift": "تغيير",
"@editEntryDateDialogShift": {},
"viewerInfoLabelCoordinates": "الإحداثيات",
"@viewerInfoLabelCoordinates": {},
@ -421,7 +421,7 @@
"@settingsVideoGestureVerticalDragBrightnessVolume": {},
"settingsAccessibilitySectionTitle": "إمكانية الوصول",
"@settingsAccessibilitySectionTitle": {},
"settingsActionExport": "يصدّر",
"settingsActionExport": "تصدير",
"@settingsActionExport": {},
"aboutBugCopyInfoInstruction": "نسخ معلومات النظام",
"@aboutBugCopyInfoInstruction": {},
@ -477,9 +477,9 @@
"@drawerAlbumPage": {},
"statsTopCountriesSectionTitle": "أهم الدول",
"@statsTopCountriesSectionTitle": {},
"settingsActionImport": "يستورد",
"settingsActionImport": "إستيراد",
"@settingsActionImport": {},
"viewerInfoLabelSize": "مقاس",
"viewerInfoLabelSize": "المقاس",
"@viewerInfoLabelSize": {},
"locationPickerUseThisLocationButton": "استخدم هذا الموقع",
"@locationPickerUseThisLocationButton": {},
@ -559,7 +559,7 @@
},
"viewerTransitionZoomIn": "تكبير",
"@viewerTransitionZoomIn": {},
"drawerCollectionAll": "كل جمع",
"drawerCollectionAll": "كافة الوسائط",
"@drawerCollectionAll": {},
"collectionMoveSuccessFeedback": "{count, plural, =1{تم نقل عنصر واحد} other{نقل {count} عناصر}}",
"@collectionMoveSuccessFeedback": {
@ -595,7 +595,7 @@
"@menuActionMap": {},
"entryInfoActionRemoveMetadata": "إزالة البيانات الوصفية",
"@entryInfoActionRemoveMetadata": {},
"collectionActionMove": "الانتقال إلى الألبوم",
"collectionActionMove": "نقل إلى الألبوم",
"@collectionActionMove": {},
"searchAlbumsSectionTitle": "الألبومات",
"@searchAlbumsSectionTitle": {},
@ -665,7 +665,7 @@
"@viewerInfoSearchSuggestionDate": {},
"videoPlaybackWithSound": "تشغيل بالصوت",
"@videoPlaybackWithSound": {},
"viewerInfoLabelTitle": "عنوان",
"viewerInfoLabelTitle": "العنوان",
"@viewerInfoLabelTitle": {},
"searchCollectionFieldHint": "البحث في المجموعة",
"@searchCollectionFieldHint": {},
@ -851,7 +851,7 @@
"@albumTierPinned": {},
"mapStyleDialogTitle": "نمط الخريطة",
"@mapStyleDialogTitle": {},
"entryActionRotateCCW": "تدوير باتجاه عقارب الساعة",
"entryActionRotateCCW": "تدوير عكس عقارب الساعة",
"@entryActionRotateCCW": {},
"settingsVideoBackgroundMode": "وضع الخلفية",
"@settingsVideoBackgroundMode": {},
@ -869,7 +869,7 @@
"@entryActionShowGeoTiffOnMap": {},
"viewDialogReverseSortOrder": "عكس ترتيب الفرز",
"@viewDialogReverseSortOrder": {},
"menuActionConfigureView": "رؤية",
"menuActionConfigureView": "العرض",
"@menuActionConfigureView": {},
"aboutLicensesDartPackagesSectionTitle": "حزم البرمجة",
"@aboutLicensesDartPackagesSectionTitle": {},
@ -933,7 +933,7 @@
"@settingsThumbnailShowVideoDuration": {},
"passwordDialogConfirm": "تأكيد كلمة السر",
"@passwordDialogConfirm": {},
"videoActionReplay10": "تقدم الخلفي لمدة 10 ثوانٍ",
"videoActionReplay10": "الرجوع للخلف لمدة 10 ثوانٍ",
"@videoActionReplay10": {},
"settingsCollectionBurstPatternsNone": "لا شيء",
"@settingsCollectionBurstPatternsNone": {},
@ -989,7 +989,7 @@
"@entryActionOpen": {},
"settingsCoordinateFormatTile": "تنسيق الإحداثيات",
"@settingsCoordinateFormatTile": {},
"newVaultWarningDialogMessage": "العناصر الموجودة في الخزائن متاحة فقط لهذا التطبيق وليس للتطبيقات الأخرى.\n\nإذا قمت بإلغاء تثبيت هذا التطبيق، أو قمت بمسح بيانات هذا التطبيق، فسوف تفقد كل هذه العناصر.",
"newVaultWarningDialogMessage": "العناصر الموجودة في الخزائن متاحة فقط لهذا التطبيق وليس للتطبيقات الأخرى.\n\nإذا قمت بإلغاء تثبيت هذا التطبيق، أو قمت بحذف بيانات هذا التطبيق، فسوف تفقد كل هذه العناصر.",
"@newVaultWarningDialogMessage": {},
"settingsViewerQuickActionEditorBanner": "المس مع الاستمرار لتحريك الأزرار وتحديد الإجراءات التي سيتم عرضها في العارض.",
"@settingsViewerQuickActionEditorBanner": {},
@ -1139,11 +1139,11 @@
"@settingsStorageAccessEmpty": {},
"settingsRemoveAnimationsTile": "إزالة الرسوم المتحركة",
"@settingsRemoveAnimationsTile": {},
"settingsStorageAccessBanner": "تتطلب بعض الدلائل منح وصول صريح لتعديل الملفات الموجودة فيها. يمكنك هنا مراجعة الدلائل التي منحتها حق الوصول إليها مسبقًا.",
"settingsStorageAccessBanner": "تتطلب بعض المسارات منح وصول صريح لتعديل الملفات الموجودة فيها. يمكنك هنا مراجعة المسارات التي منحتها حق الوصول إليها مسبقًا.",
"@settingsStorageAccessBanner": {},
"authenticateToConfigureVault": "قم بالمصادقة لتكوين المخزن",
"authenticateToConfigureVault": "قم بالمصادقة لتكوين الخزنة",
"@authenticateToConfigureVault": {},
"settingsActionExportDialogTitle": "يصدّر",
"settingsActionExportDialogTitle": "تصدير",
"@settingsActionExportDialogTitle": {},
"genericDangerWarningDialogMessage": "هل أنت متأكد؟",
"@genericDangerWarningDialogMessage": {},
@ -1197,13 +1197,13 @@
"@settingsViewerShowMinimap": {},
"settingsCollectionBurstPatternsTile": "أنماط الانفجار",
"@settingsCollectionBurstPatternsTile": {},
"viewerInfoLabelPath": "الطريق",
"viewerInfoLabelPath": "المسار",
"@viewerInfoLabelPath": {},
"albumGroupVolume": "حسب حجم التخزين",
"@albumGroupVolume": {},
"collectionGroupMonth": "حسب الشهر",
"@collectionGroupMonth": {},
"viewerInfoLabelResolution": "دقة",
"viewerInfoLabelResolution": "الدقة",
"@viewerInfoLabelResolution": {},
"renameProcessorCounter": "عداد",
"@renameProcessorCounter": {},
@ -1217,7 +1217,7 @@
"@sortByDate": {},
"statsTopAlbumsSectionTitle": "أهم الألبومات",
"@statsTopAlbumsSectionTitle": {},
"configureVaultDialogTitle": "تكوين قبو",
"configureVaultDialogTitle": "تكوين خزنة",
"@configureVaultDialogTitle": {},
"entryActionRename": "إعادة تسمية",
"@entryActionRename": {},
@ -1229,7 +1229,7 @@
"@keepScreenOnNever": {},
"statsPageTitle": "احصائيات",
"@statsPageTitle": {},
"viewerInfoSearchSuggestionDimensions": "أبعاد",
"viewerInfoSearchSuggestionDimensions": "الأبعاد",
"@viewerInfoSearchSuggestionDimensions": {},
"mapStyleOsmHot": "خرائط OSM",
"@mapStyleOsmHot": {},
@ -1255,7 +1255,7 @@
},
"sortBySize": "حسب الحجم",
"@sortBySize": {},
"viewerInfoSearchSuggestionDescription": "وصف",
"viewerInfoSearchSuggestionDescription": "الوصف",
"@viewerInfoSearchSuggestionDescription": {},
"settingsViewerShowOverlayThumbnails": "عرض الصور المصغرة",
"@settingsViewerShowOverlayThumbnails": {},
@ -1347,7 +1347,7 @@
"@settingsSubtitleThemeBackgroundOpacity": {},
"settingsStorageAccessTile": "الوصول إلى التخزين",
"@settingsStorageAccessTile": {},
"entryActionDelete": "مسح",
"entryActionDelete": "حذف",
"@entryActionDelete": {},
"settingsThemeBrightnessTile": "السمَة",
"@settingsThemeBrightnessTile": {},
@ -1401,7 +1401,7 @@
},
"videoResumeButtonLabel": "إستئناف",
"@videoResumeButtonLabel": {},
"entryActionExport": "تصدير",
"entryActionExport": "المزيد",
"@entryActionExport": {},
"mapEmptyRegion": "لا توجد صور في هذه المنطقة",
"@mapEmptyRegion": {},
@ -1421,7 +1421,7 @@
"@entryActionAddFavourite": {},
"entryActionEdit": "تحرير",
"@entryActionEdit": {},
"newVaultDialogTitle": "قبو جديد",
"newVaultDialogTitle": "خزنة جديدة",
"@newVaultDialogTitle": {},
"entryInfoActionEditRating": "تحرير التقييم",
"@entryInfoActionEditRating": {},
@ -1447,7 +1447,7 @@
"@settingsVideoBackgroundModeDialogTitle": {},
"binPageTitle": "سلة المحذوفات",
"@binPageTitle": {},
"tagPlaceholderState": "ولاية",
"tagPlaceholderState": "الولاية",
"@tagPlaceholderState": {},
"sortByAlbumFileName": "حسب الألبوم واسم الملف",
"@sortByAlbumFileName": {},
@ -1481,7 +1481,7 @@
"@appPickDialogTitle": {},
"settingsHiddenItemsTabPaths": "المسارات المخفية",
"@settingsHiddenItemsTabPaths": {},
"viewerInfoSearchSuggestionRights": "حقوق",
"viewerInfoSearchSuggestionRights": "الحقوق",
"@viewerInfoSearchSuggestionRights": {},
"mapPointNorthUpTooltip": "نقطة الشمال لأعلى",
"@mapPointNorthUpTooltip": {},
@ -1497,7 +1497,7 @@
"@entryActionShareImageOnly": {},
"settingsVideoButtonsTile": "أزرار",
"@settingsVideoButtonsTile": {},
"settingsSubtitleThemeSample": "هذه عينة.",
"settingsSubtitleThemeSample": "هذه عينة بسيطة.",
"@settingsSubtitleThemeSample": {},
"albumPickPageTitleMove": "انتقل إلى الألبوم",
"@albumPickPageTitleMove": {},

View file

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

View file

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

View file

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

View file

@ -249,7 +249,7 @@
"@subtitlePositionBottom": {},
"videoPlaybackSkip": "Пропустити",
"@videoPlaybackSkip": {},
"videoPlaybackMuted": "Відтворити з вимкненим звуком",
"videoPlaybackMuted": "Відтворити без звуку",
"@videoPlaybackMuted": {},
"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 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);

View file

@ -439,7 +439,7 @@ class _GeoMapState extends State<GeoMap> {
if (points.length != geoEntry.pointsSize) {
// `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`)
_slowMarkerCluster ??= _buildFluster(nodeSize: smallestPowerOf2(entries.length));
_slowMarkerCluster ??= _buildFluster(nodeSize: smallestPowerOf2(entries.length).toInt());
points = _slowMarkerCluster!.points(clusterId);
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) {
final viewInsetsPadding = (widget.viewInsets ?? EdgeInsets.zero) + (widget.viewPadding ?? EdgeInsets.zero);
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(
mainEntry: mainEntry,
scale: _buttonScale,
@ -220,6 +223,7 @@ class _BottomOverlayContentState extends State<_BottomOverlayContent> {
scale: _buttonScale,
),
),
),
);
final showMultiPageOverlay = mainEntry.isMultiPage && multiPageController != null;
@ -247,6 +251,8 @@ class _BottomOverlayContentState extends State<_BottomOverlayContent> {
(showMultiPageOverlay && collapsedPageScroller)
? Row(
crossAxisAlignment: CrossAxisAlignment.center,
// always keep action buttons in the lower right corner, even with RTL locales
textDirection: TextDirection.ltr,
children: [
SafeArea(
top: false,

View file

@ -40,7 +40,10 @@ class _VideoControlOverlayState extends State<VideoControlOverlay> with SingleTi
@override
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,
builder: (context, snapshot) {
// 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 devicePixelRatio,
}) =>
smallestPowerOf2(scale * devicePixelRatio).toDouble();
smallestPowerOf2(scale * devicePixelRatio, allowNegativePower: true).toDouble();
}
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
# - izzy changelog: /fastlane/metadata/android/en-US/changelogs/XXX01.txt
# - libre changelog: /fastlane/metadata/android/en-US/changelogs/XXX.txt
version: 1.10.1+110
version: 1.10.2+111
publish_to: none
environment:

View file

@ -20,6 +20,8 @@ void main() {
expect(smallestPowerOf2(-42), 1);
expect(smallestPowerOf2(.5), 1);
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', () {

View file

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

View file

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