From d16158d8e770a721da8e30b270217cb534118e1b Mon Sep 17 00:00:00 2001 From: Thibault Deckers Date: Wed, 8 Dec 2021 11:28:30 +0900 Subject: [PATCH] minor fixes --- lib/services/android_app_service.dart | 4 + lib/services/media/media_file_service.dart | 4 +- lib/widgets/viewer/debug/db.dart | 10 +- lib/widgets/viewer/info/basic_section.dart | 80 +-------------- lib/widgets/viewer/info/common.dart | 3 +- .../info/metadata/metadata_dir_tile.dart | 1 + .../viewer/info/metadata/xmp_tile.dart | 7 +- lib/widgets/viewer/info/owner.dart | 97 +++++++++++++++++++ untranslated.json | 11 +-- 9 files changed, 120 insertions(+), 97 deletions(-) create mode 100644 lib/widgets/viewer/info/owner.dart diff --git a/lib/services/android_app_service.dart b/lib/services/android_app_service.dart index b78690476..b2d118d76 100644 --- a/lib/services/android_app_service.dart +++ b/lib/services/android_app_service.dart @@ -44,6 +44,10 @@ class PlatformAndroidAppService implements AndroidAppService { if (kakaoTalk != null) { kakaoTalk.ownedDirs.add('KakaoTalkDownload'); } + final imagingEdge = packages.firstWhereOrNull((package) => package.packageName == 'com.sony.playmemories.mobile'); + if (imagingEdge != null) { + imagingEdge.ownedDirs.add('Imaging Edge Mobile'); + } return packages; } on PlatformException catch (e, stack) { await reportService.recordError(e, stack); diff --git a/lib/services/media/media_file_service.dart b/lib/services/media/media_file_service.dart index ec0a941da..1b6f3f14e 100644 --- a/lib/services/media/media_file_service.dart +++ b/lib/services/media/media_file_service.dart @@ -194,7 +194,9 @@ class PlatformMediaFileService implements MediaFileService { // `await` here, so that `completeError` will be caught below return await completer.future; } on PlatformException catch (e, stack) { - await reportService.recordError(e, stack); + if (!MimeTypes.knownMediaTypes.contains(mimeType)) { + await reportService.recordError(e, stack); + } } return Uint8List(0); } diff --git a/lib/widgets/viewer/debug/db.dart b/lib/widgets/viewer/debug/db.dart index d5dcb04a1..11279a2f3 100644 --- a/lib/widgets/viewer/debug/db.dart +++ b/lib/widgets/viewer/debug/db.dart @@ -53,7 +53,7 @@ class _DbTabState extends State { future: _dbDateLoader, builder: (context, snapshot) { if (snapshot.hasError) return Text(snapshot.error.toString()); - if (snapshot.connectionState != ConnectionState.done) return const SizedBox.shrink(); + if (snapshot.connectionState != ConnectionState.done) return const SizedBox(); final data = snapshot.data; return Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -74,7 +74,7 @@ class _DbTabState extends State { future: _dbEntryLoader, builder: (context, snapshot) { if (snapshot.hasError) return Text(snapshot.error.toString()); - if (snapshot.connectionState != ConnectionState.done) return const SizedBox.shrink(); + if (snapshot.connectionState != ConnectionState.done) return const SizedBox(); final data = snapshot.data; return Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -105,7 +105,7 @@ class _DbTabState extends State { future: _dbMetadataLoader, builder: (context, snapshot) { if (snapshot.hasError) return Text(snapshot.error.toString()); - if (snapshot.connectionState != ConnectionState.done) return const SizedBox.shrink(); + if (snapshot.connectionState != ConnectionState.done) return const SizedBox(); final data = snapshot.data; return Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -134,7 +134,7 @@ class _DbTabState extends State { future: _dbAddressLoader, builder: (context, snapshot) { if (snapshot.hasError) return Text(snapshot.error.toString()); - if (snapshot.connectionState != ConnectionState.done) return const SizedBox.shrink(); + if (snapshot.connectionState != ConnectionState.done) return const SizedBox(); final data = snapshot.data; return Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -158,7 +158,7 @@ class _DbTabState extends State { future: _dbVideoPlaybackLoader, builder: (context, snapshot) { if (snapshot.hasError) return Text(snapshot.error.toString()); - if (snapshot.connectionState != ConnectionState.done) return const SizedBox.shrink(); + if (snapshot.connectionState != ConnectionState.done) return const SizedBox(); final data = snapshot.data; return Column( crossAxisAlignment: CrossAxisAlignment.start, diff --git a/lib/widgets/viewer/info/basic_section.dart b/lib/widgets/viewer/info/basic_section.dart index 677b1f759..811dac353 100644 --- a/lib/widgets/viewer/info/basic_section.dart +++ b/lib/widgets/viewer/info/basic_section.dart @@ -1,4 +1,3 @@ -import 'package:aves/image_providers/app_icon_image_provider.dart'; import 'package:aves/model/actions/entry_info_actions.dart'; import 'package:aves/model/entry.dart'; import 'package:aves/model/favourites.dart'; @@ -8,15 +7,14 @@ import 'package:aves/model/filters/mime.dart'; import 'package:aves/model/filters/tag.dart'; import 'package:aves/model/filters/type.dart'; import 'package:aves/model/source/collection_lens.dart'; -import 'package:aves/services/common/services.dart'; import 'package:aves/theme/format.dart'; import 'package:aves/theme/icons.dart'; -import 'package:aves/utils/android_file_utils.dart'; import 'package:aves/utils/file_utils.dart'; import 'package:aves/widgets/common/extensions/build_context.dart'; import 'package:aves/widgets/common/identity/aves_filter_chip.dart'; import 'package:aves/widgets/viewer/info/common.dart'; import 'package:aves/widgets/viewer/info/entry_info_action_delegate.dart'; +import 'package:aves/widgets/viewer/info/owner.dart'; import 'package:collection/collection.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; @@ -173,79 +171,3 @@ class BasicSection extends StatelessWidget { }; } } - -class OwnerProp extends StatefulWidget { - final AvesEntry entry; - - const OwnerProp({ - Key? key, - required this.entry, - }) : super(key: key); - - @override - _OwnerPropState createState() => _OwnerPropState(); -} - -class _OwnerPropState extends State { - late Future _ownerPackageFuture; - - AvesEntry get entry => widget.entry; - - static const ownerPackageNamePropKey = 'owner_package_name'; - static const iconSize = 20.0; - - @override - void initState() { - super.initState(); - final isMediaContent = entry.uri.startsWith('content://media/external/'); - if (isMediaContent) { - _ownerPackageFuture = metadataFetchService.hasContentResolverProp(ownerPackageNamePropKey).then((exists) { - return exists ? metadataFetchService.getContentResolverProp(entry, ownerPackageNamePropKey) : SynchronousFuture(null); - }); - } else { - _ownerPackageFuture = SynchronousFuture(null); - } - } - - @override - Widget build(BuildContext context) { - return FutureBuilder( - future: _ownerPackageFuture, - builder: (context, snapshot) { - final ownerPackage = snapshot.data; - if (ownerPackage == null) return const SizedBox(); - final appName = androidFileUtils.getCurrentAppName(ownerPackage) ?? ownerPackage; - // as of Flutter v1.22.6, `SelectableText` cannot contain `WidgetSpan` - // so we use a basic `Text` instead - return Text.rich( - TextSpan( - children: [ - TextSpan( - text: context.l10n.viewerInfoLabelOwner, - style: InfoRowGroup.keyStyle, - ), - WidgetSpan( - alignment: PlaceholderAlignment.middle, - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 4), - child: Image( - image: AppIconImage( - packageName: ownerPackage, - size: iconSize, - ), - width: iconSize, - height: iconSize, - ), - ), - ), - TextSpan( - text: appName, - style: InfoRowGroup.baseStyle, - ), - ], - ), - ); - }, - ); - } -} diff --git a/lib/widgets/viewer/info/common.dart b/lib/widgets/viewer/info/common.dart index 7e2edd613..3f26747e6 100644 --- a/lib/widgets/viewer/info/common.dart +++ b/lib/widgets/viewer/info/common.dart @@ -121,8 +121,9 @@ class _InfoRowGroupState extends State { value = '$value\n'; } - // as of Flutter v1.22.6, `SelectableText` cannot contain `WidgetSpan` + // as of Flutter v2.5.3, `SelectableText` cannot contain `WidgetSpan` // so we add padding using multiple hair spaces instead + // TODO TLAD 2021/10/26 other `InlineSpan` now possible thanks to https://github.com/flutter/flutter/pull/92295 final thisSpaceSize = max(0.0, (baseValueX - keySizes[key]!)) + InfoRowGroup.keyValuePadding; final spaceCount = (100 * thisSpaceSize / baseSpaceWidth).round(); diff --git a/lib/widgets/viewer/info/metadata/metadata_dir_tile.dart b/lib/widgets/viewer/info/metadata/metadata_dir_tile.dart index 6b1189548..9caaa55ba 100644 --- a/lib/widgets/viewer/info/metadata/metadata_dir_tile.dart +++ b/lib/widgets/viewer/info/metadata/metadata_dir_tile.dart @@ -42,6 +42,7 @@ class MetadataDirTile extends StatelessWidget { if (dirName == MetadataDirectory.xmpDirectory) { return XmpDirTile( entry: entry, + title: title, tags: tags, expandedNotifier: expandedDirectoryNotifier, initiallyExpanded: initiallyExpanded, diff --git a/lib/widgets/viewer/info/metadata/xmp_tile.dart b/lib/widgets/viewer/info/metadata/xmp_tile.dart index 7114adef2..7c738e002 100644 --- a/lib/widgets/viewer/info/metadata/xmp_tile.dart +++ b/lib/widgets/viewer/info/metadata/xmp_tile.dart @@ -2,6 +2,7 @@ import 'dart:collection'; import 'package:aves/model/entry.dart'; import 'package:aves/ref/xmp.dart'; +import 'package:aves/utils/color_utils.dart'; import 'package:aves/widgets/common/identity/aves_expansion_tile.dart'; import 'package:aves/widgets/viewer/info/metadata/xmp_namespaces.dart'; import 'package:collection/collection.dart'; @@ -9,6 +10,7 @@ import 'package:flutter/material.dart'; class XmpDirTile extends StatefulWidget { final AvesEntry entry; + final String title; final SplayTreeMap tags; final ValueNotifier? expandedNotifier; final bool initiallyExpanded; @@ -16,6 +18,7 @@ class XmpDirTile extends StatefulWidget { const XmpDirTile({ Key? key, required this.entry, + required this.title, required this.tags, required this.expandedNotifier, required this.initiallyExpanded, @@ -38,7 +41,9 @@ class _XmpDirTileState extends State { }).entries.map((kv) => XmpNamespace.create(kv.key, Map.fromEntries(kv.value))).toList() ..sort((a, b) => compareAsciiUpperCase(a.displayTitle, b.displayTitle)); return AvesExpansionTile( - title: 'XMP', + // title may contain parent to distinguish multiple XMP directories + title: widget.title, + color: stringToColor('XMP'), expandedNotifier: widget.expandedNotifier, initiallyExpanded: widget.initiallyExpanded, children: [ diff --git a/lib/widgets/viewer/info/owner.dart b/lib/widgets/viewer/info/owner.dart new file mode 100644 index 000000000..354a2629b --- /dev/null +++ b/lib/widgets/viewer/info/owner.dart @@ -0,0 +1,97 @@ +import 'package:aves/app_mode.dart'; +import 'package:aves/image_providers/app_icon_image_provider.dart'; +import 'package:aves/model/entry.dart'; +import 'package:aves/model/settings/settings.dart'; +import 'package:aves/services/common/services.dart'; +import 'package:aves/utils/android_file_utils.dart'; +import 'package:aves/widgets/common/extensions/build_context.dart'; +import 'package:aves/widgets/viewer/info/common.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +class OwnerProp extends StatefulWidget { + final AvesEntry entry; + + const OwnerProp({ + Key? key, + required this.entry, + }) : super(key: key); + + @override + _OwnerPropState createState() => _OwnerPropState(); +} + +class _OwnerPropState extends State { + Future _ownerPackageLoader = SynchronousFuture(null); + Future _appNameLoader = SynchronousFuture(null); + + AvesEntry get entry => widget.entry; + + static const ownerPackageNamePropKey = 'owner_package_name'; + static const iconSize = 20.0; + + @override + void initState() { + super.initState(); + final isMediaContent = entry.uri.startsWith('content://media/external/'); + if (isMediaContent) { + _ownerPackageLoader = metadataFetchService.hasContentResolverProp(ownerPackageNamePropKey).then((exists) { + return exists ? metadataFetchService.getContentResolverProp(entry, ownerPackageNamePropKey) : SynchronousFuture(null); + }); + final isViewerMode = context.read>().value == AppMode.view; + if (isViewerMode && settings.isInstalledAppAccessAllowed) { + _appNameLoader = androidFileUtils.initAppNames(); + } + } + } + + @override + Widget build(BuildContext context) { + return FutureBuilder( + future: _ownerPackageLoader, + builder: (context, snapshot) { + final ownerPackage = snapshot.data; + if (ownerPackage == null) return const SizedBox(); + + return FutureBuilder( + future: _appNameLoader, + builder: (context, snapshot) { + final appName = androidFileUtils.getCurrentAppName(ownerPackage) ?? ownerPackage; + // as of Flutter v2.5.3, `SelectableText` cannot contain `WidgetSpan` + // so we use a basic `Text` instead + // TODO TLAD 2021/10/26 other `InlineSpan` now possible thanks to https://github.com/flutter/flutter/pull/92295 + return Text.rich( + TextSpan( + children: [ + TextSpan( + text: context.l10n.viewerInfoLabelOwner, + style: InfoRowGroup.keyStyle, + ), + WidgetSpan( + alignment: PlaceholderAlignment.middle, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 4), + child: Image( + image: AppIconImage( + packageName: ownerPackage, + size: iconSize, + ), + width: iconSize, + height: iconSize, + ), + ), + ), + TextSpan( + text: appName, + style: InfoRowGroup.baseStyle, + ), + ], + ), + ); + }, + ); + }, + ); + } +} diff --git a/untranslated.json b/untranslated.json index 353479079..9e26dfeeb 100644 --- a/untranslated.json +++ b/untranslated.json @@ -1,10 +1 @@ -{ - "ru": [ - "resetButtonTooltip", - "entryInfoActionEditTags", - "settingsViewerMaximumBrightness", - "tagEditorPageTitle", - "tagEditorPageNewTagFieldLabel", - "tagEditorPageAddTagTooltip" - ] -} +{} \ No newline at end of file