minor fixes
This commit is contained in:
parent
02131c3836
commit
d16158d8e7
9 changed files with 120 additions and 97 deletions
|
@ -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);
|
||||
|
|
|
@ -194,8 +194,10 @@ class PlatformMediaFileService implements MediaFileService {
|
|||
// `await` here, so that `completeError` will be caught below
|
||||
return await completer.future;
|
||||
} on PlatformException catch (e, stack) {
|
||||
if (!MimeTypes.knownMediaTypes.contains(mimeType)) {
|
||||
await reportService.recordError(e, stack);
|
||||
}
|
||||
}
|
||||
return Uint8List(0);
|
||||
}
|
||||
|
||||
|
|
|
@ -53,7 +53,7 @@ class _DbTabState extends State<DbTab> {
|
|||
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<DbTab> {
|
|||
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<DbTab> {
|
|||
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<DbTab> {
|
|||
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<DbTab> {
|
|||
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,
|
||||
|
|
|
@ -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<OwnerProp> {
|
||||
late Future<String?> _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<String?>(
|
||||
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,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -121,8 +121,9 @@ class _InfoRowGroupState extends State<InfoRowGroup> {
|
|||
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();
|
||||
|
||||
|
|
|
@ -42,6 +42,7 @@ class MetadataDirTile extends StatelessWidget {
|
|||
if (dirName == MetadataDirectory.xmpDirectory) {
|
||||
return XmpDirTile(
|
||||
entry: entry,
|
||||
title: title,
|
||||
tags: tags,
|
||||
expandedNotifier: expandedDirectoryNotifier,
|
||||
initiallyExpanded: initiallyExpanded,
|
||||
|
|
|
@ -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<String, String> tags;
|
||||
final ValueNotifier<String?>? 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<XmpDirTile> {
|
|||
}).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: [
|
||||
|
|
97
lib/widgets/viewer/info/owner.dart
Normal file
97
lib/widgets/viewer/info/owner.dart
Normal file
|
@ -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<OwnerProp> {
|
||||
Future<String?> _ownerPackageLoader = SynchronousFuture(null);
|
||||
Future<void> _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<ValueNotifier<AppMode>>().value == AppMode.view;
|
||||
if (isViewerMode && settings.isInstalledAppAccessAllowed) {
|
||||
_appNameLoader = androidFileUtils.initAppNames();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return FutureBuilder<String?>(
|
||||
future: _ownerPackageLoader,
|
||||
builder: (context, snapshot) {
|
||||
final ownerPackage = snapshot.data;
|
||||
if (ownerPackage == null) return const SizedBox();
|
||||
|
||||
return FutureBuilder<void>(
|
||||
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,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,10 +1 @@
|
|||
{
|
||||
"ru": [
|
||||
"resetButtonTooltip",
|
||||
"entryInfoActionEditTags",
|
||||
"settingsViewerMaximumBrightness",
|
||||
"tagEditorPageTitle",
|
||||
"tagEditorPageNewTagFieldLabel",
|
||||
"tagEditorPageAddTagTooltip"
|
||||
]
|
||||
}
|
||||
{}
|
Loading…
Reference in a new issue