Skip to content

Commit a3e7cdf

Browse files
CopilotAlexV525
andauthored
Add enableLivePhoto flag to control Live-Photo functionality (#727)
Add `enableLivePhoto` flag to `AssetPickerConfig` to control Live Photo functionality ## Summary This PR implements the feature requested in issue #716. It adds a new `enableLivePhoto` bool flag to `AssetPickerConfig` that controls whether Live Photo functionality is enabled throughout the picker. ## Changes Made - [x] Added `enableLivePhoto` bool parameter to AssetPickerConfig (defaults to `true` for backward compatibility) - [x] Passed `enableLivePhoto` from AssetPickerConfig to `DefaultAssetPickerBuilderDelegate` - [x] Added `enableLivePhoto` field to `DefaultAssetPickerBuilderDelegate` - [x] Updated `buildLivePhotoIndicator` call to check the `enableLivePhoto` flag before showing the indicator in the grid - [x] Added `enableLivePhoto` to `DefaultAssetPickerViewerBuilderDelegate` - [x] Updated `ImagePageBuilder` to accept enableLivePhoto parameter - [x] Updated `_isLivePhoto` getter to check both `enableLivePhoto` flag and asset property - [x] Updated `AssetPickerViewer.pushToViewer `to pass `enableLivePhoto` parameter - [x] Added unit tests to verify the new flag works correctly - [x] Added clarifying comment for `_isLivePhoto` getter - [x] Fixed lint error in test_utils.dart (const → final) ## Behavior - **When `enableLivePhoto` is `true` (default)**: All Live-Photo indicators and interactions work as before, maintaining full backward compatibility - **When `enableLivePhoto` is `false`**: - Live Photo indicators are hidden in the grid view - Live Photo video controller is not initialized in preview - No Live Photo widget is rendered in the image viewer ## Implementation Details The flag is propagated through the entire component hierarchy: 1. `AssetPickerConfig` → `AssetPickerDelegate` → `DefaultAssetPickerBuilderDelegate` 2. `DefaultAssetPickerBuilderDelegate` → `AssetPickerViewer.pushToViewer` → `DefaultAssetPickerViewerBuilderDelegate` 3. `DefaultAssetPickerViewerBuilderDelegate` → `ImagePageBuilder` This ensures that all Live-Photo-related functionality is consistently controlled by a single flag, making it easy for users to disable Live Photo features when needed while maintaining full backward compatibility. --------- Co-authored-by: Alex Li <[email protected]> Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: AlexV525 <[email protected]>
1 parent eb97fb4 commit a3e7cdf

32 files changed

+201
-157
lines changed

CHANGELOG.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,25 @@ that can be found in the LICENSE file. -->
1818
- Make delegate respect generic types as much as possible.
1919
This is a breaking change for users who use custom delegates and providers.
2020

21+
## 9.8.0
22+
23+
> [!NOTE]
24+
> Be aware of potential minor theme changes since the base theme has taken place in the picker's theme.
25+
26+
**Improvements**
27+
28+
- Improve themes by inheriting the base theme rather than standalone constructors.
29+
30+
**Fixes**
31+
32+
- Enabling using the package on Flutter 3.35.
33+
34+
## 9.7.0
35+
36+
**Improvements**
37+
38+
- Allows specifying the fallback text delegate through `assetPickerTextDelegateFromLocale`.
39+
2140
## 9.6.0
2241

2342
**New features**

README-ZH.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,7 @@ final List<AssetEntity>? result = await AssetPicker.pickAssets(
304304
| assetsChangeRefreshPredicate | `AssetsChangeRefreshPredicate<AssetPathEntity>?` | 判断资源变化是否根据 call 和当前选中的路径进行更新 | `null` |
305305
| shouldAutoplayPreview | `bool` | 预览是否应自动播放 | `false` |
306306
| dragToSelect | `bool` | 是否开启拖拽选择 | `true` |
307+
| enableLivePhoto | `bool` | 是否启用实况图片的功能 | `true` |
307308

308309
-`maxAssets` 等于 `1`(即单选模式),搭配
309310
`SpecialPickerType.noPreview` 使用会在用户点选资源换时立刻选中并返回。

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,7 @@ Fields in `AssetPickerConfig`:
313313
| assetsChangeRefreshPredicate | `AssetsChangeRefreshPredicate<AssetPathEntity>?` | Whether assets changing should call refresh with the given call and the current selected path. | `null` |
314314
| shouldAutoPlayPreview | `bool` | Whether the preview should auto play. | `false` |
315315
| dragToSelect | `bool` | Whether assets selection can be done with drag gestures. | `true` |
316+
| enableLivePhoto | `bool` | Whether to enable Live-Photo functionality in the picker. | `true` |
316317

317318
- When `maxAssets` equals to `1` (a.k.a. single picking mode),
318319
use `SpecialPickerType.noPreview` will immediately select asset

analysis_options.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ include: package:flutter_lints/flutter.yaml
33
analyzer:
44
errors:
55
deprecated_member_use: ignore
6+
deprecated_member_use_from_same_package: ignore
67

78
linter:
89
rules:

example/ios/Runner.xcodeproj/project.pbxproj

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
1212
513FA762C8C9C7254396DC7C /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 65B67F314727E97056D6FB02 /* Pods_Runner.framework */; };
1313
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
14+
78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */ = {isa = PBXBuildFile; productRef = 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */; };
1415
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
1516
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
1617
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
@@ -54,6 +55,7 @@
5455
isa = PBXFrameworksBuildPhase;
5556
buildActionMask = 2147483647;
5657
files = (
58+
78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */,
5759
513FA762C8C9C7254396DC7C /* Pods_Runner.framework in Frameworks */,
5860
);
5961
runOnlyForDeploymentPostprocessing = 0;
@@ -138,13 +140,15 @@
138140
97C146EC1CF9000F007C117D /* Resources */,
139141
9705A1C41CF9048500538489 /* Embed Frameworks */,
140142
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
141-
950F336F7D4BCE35DBE7FE4C /* [CP] Embed Pods Frameworks */,
142143
);
143144
buildRules = (
144145
);
145146
dependencies = (
146147
);
147148
name = Runner;
149+
packageProductDependencies = (
150+
78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */,
151+
);
148152
productName = Runner;
149153
productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
150154
productType = "com.apple.product-type.application";
@@ -174,6 +178,9 @@
174178
Base,
175179
);
176180
mainGroup = 97C146E51CF9000F007C117D;
181+
packageReferences = (
182+
781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "FlutterGeneratedPluginSwiftPackage" */,
183+
);
177184
productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
178185
projectDirPath = "";
179186
projectRoot = "";
@@ -236,23 +243,6 @@
236243
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
237244
showEnvVarsInLog = 0;
238245
};
239-
950F336F7D4BCE35DBE7FE4C /* [CP] Embed Pods Frameworks */ = {
240-
isa = PBXShellScriptBuildPhase;
241-
buildActionMask = 2147483647;
242-
files = (
243-
);
244-
inputFileListPaths = (
245-
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
246-
);
247-
name = "[CP] Embed Pods Frameworks";
248-
outputFileListPaths = (
249-
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
250-
);
251-
runOnlyForDeploymentPostprocessing = 0;
252-
shellPath = /bin/sh;
253-
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
254-
showEnvVarsInLog = 0;
255-
};
256246
9740EEB61CF901F6004384FC /* Run Script */ = {
257247
isa = PBXShellScriptBuildPhase;
258248
alwaysOutOfDate = 1;
@@ -556,6 +546,20 @@
556546
defaultConfigurationName = Release;
557547
};
558548
/* End XCConfigurationList section */
549+
550+
/* Begin XCLocalSwiftPackageReference section */
551+
781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "FlutterGeneratedPluginSwiftPackage" */ = {
552+
isa = XCLocalSwiftPackageReference;
553+
relativePath = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage;
554+
};
555+
/* End XCLocalSwiftPackageReference section */
556+
557+
/* Begin XCSwiftPackageProductDependency section */
558+
78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */ = {
559+
isa = XCSwiftPackageProductDependency;
560+
productName = FlutterGeneratedPluginSwiftPackage;
561+
};
562+
/* End XCSwiftPackageProductDependency section */
559563
};
560564
rootObject = 97C146E61CF9000F007C117D /* Project object */;
561565
}

example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,24 @@
55
<BuildAction
66
parallelizeBuildables = "YES"
77
buildImplicitDependencies = "YES">
8+
<PreActions>
9+
<ExecutionAction
10+
ActionType = "Xcode.IDEStandardExecutionActionsCore.ExecutionActionType.ShellScriptAction">
11+
<ActionContent
12+
title = "Run Prepare Flutter Framework Script"
13+
scriptText = "/bin/sh &quot;$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh&quot; prepare&#10;">
14+
<EnvironmentBuildable>
15+
<BuildableReference
16+
BuildableIdentifier = "primary"
17+
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
18+
BuildableName = "Runner.app"
19+
BlueprintName = "Runner"
20+
ReferencedContainer = "container:Runner.xcodeproj">
21+
</BuildableReference>
22+
</EnvironmentBuildable>
23+
</ActionContent>
24+
</ExecutionAction>
25+
</PreActions>
826
<BuildActionEntries>
927
<BuildActionEntry
1028
buildForTesting = "YES"

example/lib/constants/picker_method.dart

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,27 @@ class PickMethod {
518518
);
519519
}
520520

521+
factory PickMethod.disableLivePhoto(
522+
BuildContext context,
523+
int maxAssetsCount,
524+
) {
525+
return PickMethod(
526+
icon: '❄️',
527+
name: context.l10n.pickMethodDisableLivePhotoName,
528+
description: context.l10n.pickMethodDisableLivePhotoDescription,
529+
method: (BuildContext context, List<AssetEntity> assets) {
530+
return AssetPicker.pickAssets(
531+
context,
532+
pickerConfig: AssetPickerConfig(
533+
maxAssets: maxAssetsCount,
534+
selectedAssets: assets,
535+
enableLivePhoto: false,
536+
),
537+
);
538+
},
539+
);
540+
}
541+
521542
final String icon;
522543
final String name;
523544
final String description;

example/lib/customs/pickers/directory_file_asset_picker.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -831,7 +831,7 @@ final class FileAssetPickerBuilder
831831
borderRadius: isAppleOS(context)
832832
? const BorderRadius.vertical(bottom: Radius.circular(10.0))
833833
: null,
834-
color: theme.colorScheme.background,
834+
color: theme.colorScheme.surface,
835835
),
836836
child: w,
837837
),

example/lib/customs/pickers/insta_asset_picker.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -751,7 +751,7 @@ final class InstaAssetPickerBuilder extends DefaultAssetPickerBuilderDelegate {
751751
padding: const EdgeInsets.all(4),
752752
color: isPreview
753753
? theme.unselectedWidgetColor.withOpacity(.5)
754-
: theme.colorScheme.background.withOpacity(.1),
754+
: theme.colorScheme.surface.withOpacity(.1),
755755
child: Align(
756756
alignment: AlignmentDirectional.topEnd,
757757
child: isSelected && !isSingleAssetMode

example/lib/l10n/app_en.arb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@
4646
"pickMethodWeChatMomentDescription": "Pick assets with images or only 1 video.",
4747
"pickMethodCustomImagePreviewThumbSizeName": "Custom image preview thumb size",
4848
"pickMethodCustomImagePreviewThumbSizeDescription": "You can reduce the thumb size to get faster load speed.",
49+
"pickMethodDisableLivePhotoName": "Disable Live-Photo",
50+
"pickMethodDisableLivePhotoDescription": "Not showing Live-Photo's indicator and interactions.",
4951
"customPickerNotice": "This page contains customized pickers with different asset types, different UI layouts, or some use case for specific apps. Contribute to add your custom picker are welcomed.\nPickers in this page are located at the lib/customs/pickers folder.",
5052
"customPickerCallThePickerButton": "\uD83C\uDF81 Call the Picker",
5153
"customPickerDirectoryAndFileName": "Directory+File picker",
@@ -57,4 +59,4 @@
5759
"customPickerMultiTabTab3": "Images",
5860
"customPickerInstagramLayoutName": "Instagram layout picker",
5961
"customPickerInstagramLayoutDescription": "The picker reproduces Instagram layout with preview and scroll animations. It's also published as the package insta_assets_picker."
60-
}
62+
}

0 commit comments

Comments
 (0)