asset_picker_delegate.dart
9.69 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
// Copyright 2019 The FlutterCandies author. All rights reserved.
// Use of this source code is governed by an Apache license that can be found
// in the LICENSE file.
import 'package:flutter/material.dart' hide Path;
import 'package:flutter/services.dart';
import 'package:photo_manager/photo_manager.dart';
import 'package:wechat_picker_library/wechat_picker_library.dart'
show buildTheme;
import '../constants/config.dart';
import '../constants/constants.dart';
import '../provider/asset_picker_provider.dart';
import '../widget/asset_picker.dart';
import '../widget/asset_picker_page_route.dart';
import 'asset_picker_builder_delegate.dart';
class AssetPickerDelegate {
const AssetPickerDelegate();
/// {@template wechat_assets_picker.delegates.AssetPickerDelegate.permissionCheck}
/// Request the current [PermissionState] of required permissions.
/// 请求所需权限的 [PermissionState]。
///
/// Throws a [StateError] when the state is not [PermissionState.authorized]
/// or [PermissionState.limited],
/// which means the picker can not perform further actions.
/// 当权限状态不是 [PermissionState.authorized] 或 [PermissionState.limited] 时,
/// 将抛出 [StateError],此时选择器无法执行其他操作。
///
/// See also:
/// * [PermissionState] which defined all states of required permissions.
/// {@endtemplate}
Future<PermissionState> permissionCheck({
PermissionRequestOption requestOption = const PermissionRequestOption(),
}) async {
final PermissionState ps = await PhotoManager.requestPermissionExtend(
requestOption: requestOption,
);
if (ps != PermissionState.authorized && ps != PermissionState.limited) {
throw StateError('Permission state error with $ps.');
}
return ps;
}
/// {@template wechat_assets_picker.delegates.AssetPickerDelegate.pickAssets}
/// Pick assets with the given [pickerConfig].
/// 根据给定的 [pickerConfig] 选择资源。
///
/// Set [useRootNavigator] to determine
/// whether the picker route should use the root [Navigator].
/// 使用 [useRootNavigator] 来控制选择器的路由是否使用最顶层的 [Navigator]。
///
/// By extending the [AssetPickerPageRoute], users can customize the route
/// and use it with the [pageRouteBuilder].
/// 继承 [AssetPickerPageRoute] 可以自定义路由,
/// 并且通过 [pageRouteBuilder] 进行使用。
///
/// See also:
/// * [AssetPickerConfig] which holds all configurations for basic picking.
/// * [DefaultAssetPickerProvider] which is the default provider that
/// manages assets during the picking process.
/// * [DefaultAssetPickerBuilderDelegate] which is the default builder that
/// builds all widgets during the picking process.
/// {@endtemplate}
Future<List<AssetEntity>?> pickAssets(
BuildContext context, {
Key? key,
AssetPickerConfig pickerConfig = const AssetPickerConfig(),
PermissionRequestOption? permissionRequestOption,
bool useRootNavigator = true,
RouteSettings? pageRouteSettings,
AssetPickerPageRouteBuilder<List<AssetEntity>>? pageRouteBuilder,
}) async {
permissionRequestOption ??= PermissionRequestOption(
androidPermission: AndroidPermission(
type: pickerConfig.requestType,
mediaLocation: false,
),
);
final PermissionState ps = await permissionCheck(
requestOption: permissionRequestOption,
);
final AssetPickerPageRoute<List<AssetEntity>> route =
pageRouteBuilder?.call(const SizedBox.shrink()) ??
AssetPickerPageRoute<List<AssetEntity>>(
builder: (_) => const SizedBox.shrink(),
settings: pageRouteSettings,
);
final DefaultAssetPickerProvider provider = DefaultAssetPickerProvider(
maxAssets: pickerConfig.maxAssets,
pageSize: pickerConfig.pageSize,
pathThumbnailSize: pickerConfig.pathThumbnailSize,
selectedAssets: pickerConfig.selectedAssets,
requestType: pickerConfig.requestType,
sortPathDelegate: pickerConfig.sortPathDelegate,
filterOptions: pickerConfig.filterOptions,
initializeDelayDuration: route.transitionDuration,
);
final Widget picker = AssetPicker<AssetEntity, AssetPathEntity>(
key: key,
permissionRequestOption: permissionRequestOption,
builder: DefaultAssetPickerBuilderDelegate(
provider: provider,
initialPermission: ps,
gridCount: pickerConfig.gridCount,
pickerTheme: pickerConfig.pickerTheme,
gridThumbnailSize: pickerConfig.gridThumbnailSize,
previewThumbnailSize: pickerConfig.previewThumbnailSize,
specialPickerType: pickerConfig.specialPickerType,
specialItemPosition: pickerConfig.specialItemPosition,
specialItemBuilder: pickerConfig.specialItemBuilder,
loadingIndicatorBuilder: pickerConfig.loadingIndicatorBuilder,
selectPredicate: pickerConfig.selectPredicate,
shouldRevertGrid: pickerConfig.shouldRevertGrid,
limitedPermissionOverlayPredicate:
pickerConfig.limitedPermissionOverlayPredicate,
pathNameBuilder: pickerConfig.pathNameBuilder,
assetsChangeCallback: pickerConfig.assetsChangeCallback,
assetsChangeRefreshPredicate: pickerConfig.assetsChangeRefreshPredicate,
textDelegate: pickerConfig.textDelegate,
themeColor: pickerConfig.themeColor,
locale: Localizations.maybeLocaleOf(context),
shouldAutoplayPreview: pickerConfig.shouldAutoplayPreview,
dragToSelect: pickerConfig.dragToSelect,
),
);
final List<AssetEntity>? result = await Navigator.maybeOf(
context,
rootNavigator: useRootNavigator,
)?.push<List<AssetEntity>>(
pageRouteBuilder?.call(picker) ??
AssetPickerPageRoute<List<AssetEntity>>(
builder: (_) => picker,
settings: pageRouteSettings,
),
);
return result;
}
/// {@template wechat_assets_picker.delegates.AssetPickerDelegate.pickAssetsWithDelegate}
/// Pick assets with the given [delegate].
/// 根据给定的 [delegate] 选择资源。
///
/// Set [useRootNavigator] to determine
/// whether the picker route should use the root [Navigator].
/// 使用 [useRootNavigator] 来控制选择器的路由是否使用最顶层的 [Navigator]。
///
/// By extending the [AssetPickerPageRoute], users can customize the route
/// and use it with the [pageRouteBuilder].
/// 继承 [AssetPickerPageRoute] 可以自定义路由,
/// 并且通过 [pageRouteBuilder] 进行使用。
///
/// See also:
/// * [AssetPickerBuilderDelegate] for how to customize/override widgets
/// during the picking process.
/// {@endtemplate}
Future<List<Asset>?> pickAssetsWithDelegate<Asset, Path,
PickerProvider extends AssetPickerProvider<Asset, Path>>(
BuildContext context, {
required AssetPickerBuilderDelegate<Asset, Path> delegate,
PermissionRequestOption permissionRequestOption =
const PermissionRequestOption(),
Key? key,
bool useRootNavigator = true,
RouteSettings? pageRouteSettings,
AssetPickerPageRouteBuilder<List<Asset>>? pageRouteBuilder,
}) async {
await permissionCheck(requestOption: permissionRequestOption);
final Widget picker = AssetPicker<Asset, Path>(
key: key,
permissionRequestOption: permissionRequestOption,
builder: delegate,
);
final List<Asset>? result = await Navigator.maybeOf(
context,
rootNavigator: useRootNavigator,
)?.push<List<Asset>>(
pageRouteBuilder?.call(picker) ??
AssetPickerPageRoute<List<Asset>>(
builder: (_) => picker,
settings: pageRouteSettings,
),
);
return result;
}
/// {@template wechat_assets_picker.delegates.AssetPickerDelegate.registerObserve}
/// Register observe callback with assets changes.
/// 注册资源(图库)变化的监听回调
/// {@endtemplate}
void registerObserve([ValueChanged<MethodCall>? callback]) {
if (callback == null) {
return;
}
try {
PhotoManager.addChangeCallback(callback);
PhotoManager.startChangeNotify();
} catch (e, s) {
FlutterError.presentError(
FlutterErrorDetails(
exception: e,
stack: s,
library: packageName,
silent: true,
),
);
}
}
/// {@template wechat_assets_picker.delegates.AssetPickerDelegate.unregisterObserve}
/// Unregister the observation callback with assets changes.
/// 取消注册资源(图库)变化的监听回调
/// {@endtemplate}
void unregisterObserve([ValueChanged<MethodCall>? callback]) {
if (callback == null) {
return;
}
try {
PhotoManager.removeChangeCallback(callback);
PhotoManager.stopChangeNotify();
} catch (e, s) {
FlutterError.presentError(
FlutterErrorDetails(
exception: e,
stack: s,
library: packageName,
silent: true,
),
);
}
}
/// {@template wechat_assets_picker.delegates.AssetPickerDelegate.themeData}
/// Build a [ThemeData] with the given [themeColor] for the picker.
/// 为选择器构建基于 [themeColor] 的 [ThemeData]。
///
/// If [themeColor] is null, the color will use the fallback
/// [defaultThemeColorWeChat] which is the default color in the WeChat design.
/// 如果 [themeColor] 为 null,主题色将回落使用 [defaultThemeColorWeChat],
/// 即微信设计中的绿色主题色。
///
/// Set [light] to true if pickers require a light version of the theme.
/// 设置 [light] 为 true 时可以获取浅色版本的主题。
/// {@endtemplate}
ThemeData themeData(Color? themeColor, {bool light = false}) {
return buildTheme(themeColor, light: light);
}
}