@@ -31,6 +31,8 @@ import '../widget/gaps.dart';
31
31
import '../widget/platform_progress_indicator.dart' ;
32
32
import '../widget/scale_text.dart' ;
33
33
34
+ const String _ordinalNamePermissionOverlay = 'permissionOverlay' ;
35
+
34
36
typedef IndicatorBuilder = Widget Function (
35
37
BuildContext context,
36
38
bool isAssetsEmpty,
@@ -623,7 +625,10 @@ abstract class AssetPickerBuilderDelegate<Asset, Path> {
623
625
}
624
626
return Positioned .fill (
625
627
child: Semantics (
626
- sortKey: const OrdinalSortKey (0 ),
628
+ sortKey: const OrdinalSortKey (
629
+ 0 ,
630
+ name: _ordinalNamePermissionOverlay,
631
+ ),
627
632
child: Container (
628
633
padding: context.mediaQuery.padding,
629
634
color: context.themeData.canvasColor,
@@ -876,6 +881,32 @@ class DefaultAssetPickerBuilderDelegate
876
881
}
877
882
}
878
883
884
+ @override
885
+ AssetPickerAppBar appBar (BuildContext context) {
886
+ return AssetPickerAppBar (
887
+ backgroundColor: theme.appBarTheme.backgroundColor,
888
+ centerTitle: isAppleOS,
889
+ title: Semantics (
890
+ onTapHint: textDelegate.sActionSwitchPathLabel,
891
+ child: pathEntitySelector (context),
892
+ ),
893
+ leading: backButton (context),
894
+ // Condition for displaying the confirm button:
895
+ // - On Android, show if preview is enabled or if multi asset mode.
896
+ // If no preview and single asset mode, do not show confirm button,
897
+ // because any click on an asset selects it.
898
+ // - On iOS, show if no preview and multi asset mode. This is because for iOS
899
+ // the [bottomActionBar] has the confirm button, but if no preview,
900
+ // [bottomActionBar] is not displayed.
901
+ actions: (! isAppleOS || ! isPreviewEnabled) &&
902
+ (isPreviewEnabled || ! isSingleAssetMode)
903
+ ? < Widget > [confirmButton (context)]
904
+ : null ,
905
+ actionsPadding: const EdgeInsetsDirectional .only (end: 14 ),
906
+ blurRadius: isAppleOS ? appleOSBlurRadius : 0 ,
907
+ );
908
+ }
909
+
879
910
@override
880
911
Widget androidLayout (BuildContext context) {
881
912
return AssetPickerAppBarWrapper (
@@ -911,32 +942,6 @@ class DefaultAssetPickerBuilderDelegate
911
942
);
912
943
}
913
944
914
- @override
915
- AssetPickerAppBar appBar (BuildContext context) {
916
- return AssetPickerAppBar (
917
- backgroundColor: theme.appBarTheme.backgroundColor,
918
- centerTitle: isAppleOS,
919
- title: Semantics (
920
- onTapHint: textDelegate.sActionSwitchPathLabel,
921
- child: pathEntitySelector (context),
922
- ),
923
- leading: backButton (context),
924
- // Condition for displaying the confirm button:
925
- // - On Android, show if preview is enabled or if multi asset mode.
926
- // If no preview and single asset mode, do not show confirm button,
927
- // because any click on an asset selects it.
928
- // - On iOS, show if no preview and multi asset mode. This is because for iOS
929
- // the [bottomActionBar] has the confirm button, but if no preview,
930
- // [bottomActionBar] is not displayed.
931
- actions: (! isAppleOS || ! isPreviewEnabled) &&
932
- (isPreviewEnabled || ! isSingleAssetMode)
933
- ? < Widget > [confirmButton (context)]
934
- : null ,
935
- actionsPadding: const EdgeInsetsDirectional .only (end: 14 ),
936
- blurRadius: isAppleOS ? appleOSBlurRadius : 0 ,
937
- );
938
- }
939
-
940
945
@override
941
946
Widget appleOSLayout (BuildContext context) {
942
947
Widget _gridLayout (BuildContext context) {
@@ -990,7 +995,7 @@ class DefaultAssetPickerBuilderDelegate
990
995
},
991
996
),
992
997
),
993
- Semantics (sortKey : const OrdinalSortKey ( 0 ), child : appBar (context) ),
998
+ appBar (context),
994
999
],
995
1000
);
996
1001
}
@@ -1003,7 +1008,7 @@ class DefaultAssetPickerBuilderDelegate
1003
1008
}
1004
1009
return Semantics (
1005
1010
excludeSemantics: true ,
1006
- sortKey: const OrdinalSortKey (1 ),
1011
+ sortKey: const OrdinalSortKey (1 , name : _ordinalNamePermissionOverlay ),
1007
1012
child: child,
1008
1013
);
1009
1014
},
@@ -1263,59 +1268,70 @@ class DefaultAssetPickerBuilderDelegate
1263
1268
AssetEntity asset,
1264
1269
Widget child,
1265
1270
) {
1266
- return Consumer <DefaultAssetPickerProvider >(
1267
- child: child,
1268
- builder: (_, DefaultAssetPickerProvider p, Widget ? child) {
1269
- final bool isBanned =
1270
- (! p.selectedAssets.contains (asset) && p.selectedMaximumAssets) ||
1271
+ return ValueListenableBuilder <bool >(
1272
+ valueListenable: isSwitchingPath,
1273
+ builder: (_, bool isSwitchingPath, Widget ? child) {
1274
+ return Consumer <DefaultAssetPickerProvider >(
1275
+ builder: (_, DefaultAssetPickerProvider p, __) {
1276
+ final bool isBanned = (! p.selectedAssets.contains (asset) &&
1277
+ p.selectedMaximumAssets) ||
1271
1278
(isWeChatMoment &&
1272
1279
asset.type == AssetType .video &&
1273
1280
p.selectedAssets.isNotEmpty);
1274
- final bool isSelected = p.selectedDescriptions.contains (
1275
- asset.toString (),
1276
- );
1277
- final int selectedIndex = p.selectedAssets.indexOf (asset) + 1 ;
1278
- String hint = '' ;
1279
- if (asset.type == AssetType .audio || asset.type == AssetType .video) {
1280
- hint += '${textDelegate .sNameDurationLabel }: ' ;
1281
- hint += textDelegate.durationIndicatorBuilder (asset.videoDuration);
1282
- }
1283
- if (asset.title? .isNotEmpty == true ) {
1284
- hint += ', ${asset .title }' ;
1285
- }
1286
- return Semantics (
1287
- button: false ,
1288
- enabled: ! isBanned,
1289
- excludeSemantics: true ,
1290
- focusable: ! isSwitchingPath.value,
1291
- label: '${textDelegate .semanticTypeLabel (asset .type )}'
1292
- '${semanticIndex (index )}, '
1293
- '${asset .createDateTime .toString ().replaceAll ('.000' , '' )}' ,
1294
- hidden: isSwitchingPath.value,
1295
- hint: hint,
1296
- image: asset.type == AssetType .image || asset.type == AssetType .video,
1297
- onTap: () => selectAsset (context, asset, isSelected),
1298
- onTapHint: textDelegate.sActionSelectHint,
1299
- onLongPress: isPreviewEnabled
1300
- ? () => _pushAssetToViewer (context, index, asset)
1301
- : null ,
1302
- onLongPressHint: textDelegate.sActionPreviewHint,
1303
- selected: isSelected,
1304
- sortKey: OrdinalSortKey (
1305
- semanticIndex (index).toDouble (),
1306
- name: 'GridItem' ,
1307
- ),
1308
- value: selectedIndex > 0 ? '$selectedIndex ' : null ,
1309
- child: GestureDetector (
1310
- // Regression https://github.com/flutter/flutter/issues/35112.
1311
- onLongPress:
1312
- isPreviewEnabled && context.mediaQuery.accessibleNavigation
1313
- ? () => _pushAssetToViewer (context, index, asset)
1314
- : null ,
1315
- child: IndexedSemantics (index: semanticIndex (index), child: child),
1316
- ),
1281
+ final bool isSelected = p.selectedDescriptions.contains (
1282
+ asset.toString (),
1283
+ );
1284
+ final int selectedIndex = p.selectedAssets.indexOf (asset) + 1 ;
1285
+ String hint = '' ;
1286
+ if (asset.type == AssetType .audio ||
1287
+ asset.type == AssetType .video) {
1288
+ hint += '${textDelegate .sNameDurationLabel }: ' ;
1289
+ hint +=
1290
+ textDelegate.durationIndicatorBuilder (asset.videoDuration);
1291
+ }
1292
+ if (asset.title? .isNotEmpty == true ) {
1293
+ hint += ', ${asset .title }' ;
1294
+ }
1295
+ return Semantics (
1296
+ button: false ,
1297
+ enabled: ! isBanned,
1298
+ excludeSemantics: true ,
1299
+ focusable: ! isSwitchingPath,
1300
+ label: '${textDelegate .semanticTypeLabel (asset .type )}'
1301
+ '${semanticIndex (index )}, '
1302
+ '${asset .createDateTime .toString ().replaceAll ('.000' , '' )}' ,
1303
+ hidden: isSwitchingPath,
1304
+ hint: hint,
1305
+ image: asset.type == AssetType .image ||
1306
+ asset.type == AssetType .video,
1307
+ onTap: () => selectAsset (context, asset, isSelected),
1308
+ onTapHint: textDelegate.sActionSelectHint,
1309
+ onLongPress: isPreviewEnabled
1310
+ ? () => _pushAssetToViewer (context, index, asset)
1311
+ : null ,
1312
+ onLongPressHint: textDelegate.sActionPreviewHint,
1313
+ selected: isSelected,
1314
+ sortKey: OrdinalSortKey (
1315
+ semanticIndex (index).toDouble (),
1316
+ name: 'GridItem' ,
1317
+ ),
1318
+ value: selectedIndex > 0 ? '$selectedIndex ' : null ,
1319
+ child: GestureDetector (
1320
+ // Regression https://github.com/flutter/flutter/issues/35112.
1321
+ onLongPress:
1322
+ isPreviewEnabled && context.mediaQuery.accessibleNavigation
1323
+ ? () => _pushAssetToViewer (context, index, asset)
1324
+ : null ,
1325
+ child: IndexedSemantics (
1326
+ index: semanticIndex (index),
1327
+ child: child,
1328
+ ),
1329
+ ),
1330
+ );
1331
+ },
1317
1332
);
1318
1333
},
1334
+ child: child,
1319
1335
);
1320
1336
}
1321
1337
@@ -1553,9 +1569,7 @@ class DefaultAssetPickerBuilderDelegate
1553
1569
child: ValueListenableBuilder <bool >(
1554
1570
valueListenable: isSwitchingPath,
1555
1571
builder: (_, bool isSwitchingPath, Widget ? child) => Semantics (
1556
- focusable: isSwitchingPath,
1557
- sortKey: const OrdinalSortKey (1 ),
1558
- hidden: ! isSwitchingPath,
1572
+ hidden: isSwitchingPath ? null : true ,
1559
1573
child: AnimatedAlign (
1560
1574
duration: switchingPathDuration,
1561
1575
curve: switchingPathCurve,
0 commit comments