moved region decoding responsibility to platform side
This commit is contained in:
parent
426264d186
commit
82e4a6b22a
7 changed files with 70 additions and 23 deletions
|
@ -12,6 +12,7 @@ import androidx.core.content.pm.ShortcutManagerCompat
|
|||
import com.google.android.material.color.DynamicColors
|
||||
import deckers.thibault.aves.channel.calls.Coresult.Companion.safe
|
||||
import deckers.thibault.aves.model.FieldMap
|
||||
import deckers.thibault.aves.utils.MimeTypes
|
||||
import io.flutter.plugin.common.MethodCall
|
||||
import io.flutter.plugin.common.MethodChannel
|
||||
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
|
||||
|
@ -55,6 +56,7 @@ class DeviceHandler(private val context: Context) : MethodCallHandler {
|
|||
"canUseCrypto" to (sdkInt >= Build.VERSION_CODES.LOLLIPOP),
|
||||
"hasGeocoder" to Geocoder.isPresent(),
|
||||
"isDynamicColorAvailable" to DynamicColors.isDynamicColorAvailable(),
|
||||
"regionDecodableMimeTypes" to MimeTypes.supportedByBitmapRegionDecoder,
|
||||
"showPinShortcutFeedback" to (sdkInt >= Build.VERSION_CODES.O),
|
||||
"supportEdgeToEdgeUIMode" to (sdkInt >= Build.VERSION_CODES.Q),
|
||||
)
|
||||
|
|
|
@ -163,4 +163,13 @@ object MimeTypes {
|
|||
}
|
||||
|
||||
val TIFF_EXTENSION_PATTERN = Regex(".*\\.tiff?", RegexOption.IGNORE_CASE)
|
||||
|
||||
val supportedByBitmapRegionDecoder: List<String> = listOf(
|
||||
// Android's `BitmapRegionDecoder` documentation states that "only the JPEG and PNG formats are supported"
|
||||
// but in practice (tested on API 25, 27, 29), it successfully decodes the formats listed below,
|
||||
// and it actually fails to decode GIF, DNG and animated WEBP. Other formats were not tested.
|
||||
HEIC, HEIF, JPEG, PNG, WEBP, ARW, CR2, NEF, NRW, ORF, PEF, RAF, RW2, SRW,
|
||||
// custom support
|
||||
TIFF,
|
||||
)
|
||||
}
|
||||
|
|
|
@ -20,28 +20,6 @@ class AppSupport {
|
|||
|
||||
static bool canDecode(String mimeType) => !undecodableImages.contains(mimeType);
|
||||
|
||||
// Android's `BitmapRegionDecoder` documentation states that "only the JPEG and PNG formats are supported"
|
||||
// but in practice (tested on API 25, 27, 29), it successfully decodes the formats listed below,
|
||||
// and it actually fails to decode GIF, DNG and animated WEBP. Other formats were not tested.
|
||||
static bool _supportedByBitmapRegionDecoder(String mimeType) => [
|
||||
MimeTypes.heic,
|
||||
MimeTypes.heif,
|
||||
MimeTypes.jpeg,
|
||||
MimeTypes.png,
|
||||
MimeTypes.webp,
|
||||
MimeTypes.arw,
|
||||
MimeTypes.cr2,
|
||||
MimeTypes.nef,
|
||||
MimeTypes.nrw,
|
||||
MimeTypes.orf,
|
||||
MimeTypes.pef,
|
||||
MimeTypes.raf,
|
||||
MimeTypes.rw2,
|
||||
MimeTypes.srw,
|
||||
].contains(mimeType);
|
||||
|
||||
static bool canDecodeRegion(String mimeType) => _supportedByBitmapRegionDecoder(mimeType) || mimeType == MimeTypes.tiff;
|
||||
|
||||
// `exifinterface` v1.3.3 declared support for DNG, but it strips non-standard Exif tags when saving attributes,
|
||||
// and DNG requires DNG-specific tags saved along standard Exif. So it was actually breaking DNG files.
|
||||
static bool canEditExif(String mimeType) {
|
||||
|
|
|
@ -12,6 +12,7 @@ class Device {
|
|||
late final bool _canAuthenticateUser, _canGrantDirectoryAccess, _canPinShortcut;
|
||||
late final bool _canRenderFlagEmojis, _canRenderSubdivisionFlagEmojis, _canRequestManageMedia, _canSetLockScreenWallpaper, _canUseCrypto;
|
||||
late final bool _hasGeocoder, _isDynamicColorAvailable, _isTelevision, _showPinShortcutFeedback, _supportEdgeToEdgeUIMode, _supportPictureInPicture;
|
||||
late final List<String> _regionDecodableMimeTypes;
|
||||
|
||||
String get packageName => _packageName;
|
||||
|
||||
|
@ -49,6 +50,8 @@ class Device {
|
|||
|
||||
bool get supportPictureInPicture => _supportPictureInPicture;
|
||||
|
||||
bool canDecodeRegion(String mimeType) => _regionDecodableMimeTypes.contains(mimeType);
|
||||
|
||||
Device._private();
|
||||
|
||||
Future<void> init() async {
|
||||
|
@ -82,6 +85,7 @@ class Device {
|
|||
_canUseCrypto = capabilities['canUseCrypto'] ?? false;
|
||||
_hasGeocoder = capabilities['hasGeocoder'] ?? false;
|
||||
_isDynamicColorAvailable = capabilities['isDynamicColorAvailable'] ?? false;
|
||||
_regionDecodableMimeTypes = (capabilities['regionDecodableMimeTypes'] ?? []).cast<String>();
|
||||
_showPinShortcutFeedback = capabilities['showPinShortcutFeedback'] ?? false;
|
||||
_supportEdgeToEdgeUIMode = capabilities['supportEdgeToEdgeUIMode'] ?? false;
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ import 'dart:io';
|
|||
import 'dart:ui';
|
||||
|
||||
import 'package:aves/model/app/support.dart';
|
||||
import 'package:aves/model/device.dart';
|
||||
import 'package:aves/model/entry/entry.dart';
|
||||
import 'package:aves/model/settings/settings.dart';
|
||||
import 'package:aves/model/source/trash.dart';
|
||||
|
@ -127,7 +128,7 @@ extension ExtraAvesEntryProps on AvesEntry {
|
|||
|
||||
bool get canDecode => AppSupport.canDecode(mimeType);
|
||||
|
||||
bool get canDecodeRegion => AppSupport.canDecodeRegion(mimeType) && !isAnimated;
|
||||
bool get canDecodeRegion => device.canDecodeRegion(mimeType) && !isAnimated;
|
||||
|
||||
bool get canEditExif => AppSupport.canEditExif(mimeType);
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ import 'package:aves/widgets/debug/app_debug_action.dart';
|
|||
import 'package:aves/widgets/debug/cache.dart';
|
||||
import 'package:aves/widgets/debug/colors.dart';
|
||||
import 'package:aves/widgets/debug/database.dart';
|
||||
import 'package:aves/widgets/debug/device.dart';
|
||||
import 'package:aves/widgets/debug/general.dart';
|
||||
import 'package:aves/widgets/debug/media_store_scan_dialog.dart';
|
||||
import 'package:aves/widgets/debug/report.dart';
|
||||
|
@ -75,6 +76,7 @@ class AppDebugPage extends StatelessWidget {
|
|||
DebugCacheSection(),
|
||||
DebugColorSection(),
|
||||
DebugAppDatabaseSection(),
|
||||
DebugDeviceSection(),
|
||||
DebugErrorReportingSection(),
|
||||
DebugSettingsSection(),
|
||||
DebugStorageSection(),
|
||||
|
|
51
lib/widgets/debug/device.dart
Normal file
51
lib/widgets/debug/device.dart
Normal file
|
@ -0,0 +1,51 @@
|
|||
import 'package:aves/model/device.dart';
|
||||
import 'package:aves/widgets/common/identity/aves_expansion_tile.dart';
|
||||
import 'package:aves/widgets/viewer/info/common.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class DebugDeviceSection extends StatefulWidget {
|
||||
const DebugDeviceSection({super.key});
|
||||
|
||||
@override
|
||||
State<DebugDeviceSection> createState() => _DebugDeviceSectionState();
|
||||
}
|
||||
|
||||
class _DebugDeviceSectionState extends State<DebugDeviceSection> with AutomaticKeepAliveClientMixin {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
super.build(context);
|
||||
return AvesExpansionTile(
|
||||
title: 'Device',
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 8, right: 8, bottom: 8),
|
||||
child: InfoRowGroup(
|
||||
info: {
|
||||
'packageName': device.packageName,
|
||||
'packageVersion': device.packageVersion,
|
||||
'userAgent': device.userAgent,
|
||||
'canAuthenticateUser': '${device.canAuthenticateUser}',
|
||||
'canGrantDirectoryAccess': '${device.canGrantDirectoryAccess}',
|
||||
'canPinShortcut': '${device.canPinShortcut}',
|
||||
'canRenderFlagEmojis': '${device.canRenderFlagEmojis}',
|
||||
'canRenderSubdivisionFlagEmojis': '${device.canRenderSubdivisionFlagEmojis}',
|
||||
'canRequestManageMedia': '${device.canRequestManageMedia}',
|
||||
'canSetLockScreenWallpaper': '${device.canSetLockScreenWallpaper}',
|
||||
'canUseCrypto': '${device.canUseCrypto}',
|
||||
'canUseVaults': '${device.canUseVaults}',
|
||||
'hasGeocoder': '${device.hasGeocoder}',
|
||||
'isDynamicColorAvailable': '${device.isDynamicColorAvailable}',
|
||||
'isTelevision': '${device.isTelevision}',
|
||||
'showPinShortcutFeedback': '${device.showPinShortcutFeedback}',
|
||||
'supportEdgeToEdgeUIMode': '${device.supportEdgeToEdgeUIMode}',
|
||||
'supportPictureInPicture': '${device.supportPictureInPicture}',
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
bool get wantKeepAlive => true;
|
||||
}
|
Loading…
Reference in a new issue