Skip to content

Commit b93a10f

Browse files
authored
✨ Add CameraErrorHandler (#52)
1 parent 0567ae6 commit b93a10f

File tree

5 files changed

+64
-15
lines changed

5 files changed

+64
-15
lines changed

lib/src/internals/extensions.dart

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
///
32
/// [Author] Alex (https://github.com/AlexV525)
43
/// [Date] 2021/9/30 17:02
@@ -16,3 +15,12 @@ extension SafeSetStateExtension on State {
1615
}
1716
}
1817
}
18+
19+
extension NullableObjectExtension on Object? {
20+
StackTrace? get nullableStackTrace {
21+
if (this is Error?) {
22+
return (this as Error?)?.stackTrace;
23+
}
24+
return null;
25+
}
26+
}

lib/src/internals/methods.dart

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,21 @@ import 'dart:developer';
66

77
import 'package:flutter/foundation.dart';
88

9+
import 'extensions.dart';
10+
import 'type_defs.dart';
11+
912
/// Log only in debug mode.
1013
/// 只在调试模式打印
1114
void realDebugPrint(dynamic message) {
1215
if (!kReleaseMode) {
1316
log('$message', name: 'CameraPicker - LOG');
1417
}
1518
}
19+
20+
void handleErrorWithHandler(Object error, CameraErrorHandler? handler) {
21+
if (handler != null) {
22+
handler(error, error.nullableStackTrace);
23+
return;
24+
}
25+
throw error;
26+
}

lib/src/internals/type_defs.dart

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,12 @@ typedef EntitySaveCallback = FutureOr<dynamic> Function({
2929
CameraPickerViewType viewType,
3030
File file,
3131
});
32+
33+
/// {@template wechat_camera_picker.CameraErrorHandler}
34+
/// The error handler when any error occurred during the picking process.
35+
/// 拍摄照片过程中的自定义错误处理
36+
/// {@endtemplate}
37+
typedef CameraErrorHandler = void Function(
38+
Object error,
39+
StackTrace? stackTrace,
40+
);

lib/src/widgets/camera_picker.dart

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ class CameraPicker extends StatefulWidget {
4949
this.cameraQuarterTurns = 0,
5050
this.foregroundBuilder,
5151
this.onEntitySaving,
52+
this.onError,
5253
CameraPickerTextDelegate? textDelegate,
5354
}) : assert(
5455
enableRecording == true || onlyEnableRecording != true,
@@ -123,6 +124,9 @@ class CameraPicker extends StatefulWidget {
123124
/// {@macro wechat_camera_picker.EntitySaveCallback}
124125
final EntitySaveCallback? onEntitySaving;
125126

127+
/// {@macro wechat_camera_picker.CameraErrorHandler}
128+
final CameraErrorHandler? onError;
129+
126130
/// Static method to create [AssetEntity] through camera.
127131
/// 通过相机创建 [AssetEntity] 的静态方法
128132
static Future<AssetEntity?> pickFromCamera(
@@ -143,6 +147,7 @@ class CameraPicker extends StatefulWidget {
143147
ImageFormatGroup imageFormatGroup = ImageFormatGroup.unknown,
144148
Widget Function(CameraValue)? foregroundBuilder,
145149
EntitySaveCallback? onEntitySaving,
150+
CameraErrorHandler? onError,
146151
bool useRootNavigator = true,
147152
}) {
148153
if (enableRecording != true && onlyEnableRecording == true) {
@@ -170,6 +175,7 @@ class CameraPicker extends StatefulWidget {
170175
imageFormatGroup: imageFormatGroup,
171176
foregroundBuilder: foregroundBuilder,
172177
onEntitySaving: onEntitySaving,
178+
onError: onError,
173179
),
174180
transitionCurve: Curves.easeIn,
175181
transitionDuration: _kRouteDuration,
@@ -472,9 +478,12 @@ class CameraPickerState extends State<CameraPicker>
472478
// After cameras fetched, judge again with the list is empty or not to
473479
// ensure there is at least an available camera for use.
474480
if (cameraDescription == null && (cameras.isEmpty)) {
475-
throw CameraException(
476-
'No CameraDescription found.',
477-
'No cameras are available in the controller.',
481+
handleErrorWithHandler(
482+
CameraException(
483+
'No CameraDescription found.',
484+
'No cameras are available in the controller.',
485+
),
486+
widget.onError,
478487
);
479488
}
480489

@@ -486,9 +495,12 @@ class CameraPickerState extends State<CameraPicker>
486495
imageFormatGroup: widget.imageFormatGroup,
487496
)..addListener(() {
488497
if (controller.value.hasError) {
489-
throw CameraException(
490-
'CameraController exception',
491-
controller.value.errorDescription,
498+
handleErrorWithHandler(
499+
CameraException(
500+
'CameraController exception',
501+
controller.value.errorDescription,
502+
),
503+
widget.onError,
492504
);
493505
}
494506
});
@@ -505,8 +517,8 @@ class CameraPickerState extends State<CameraPicker>
505517
(() async =>
506518
_minAvailableZoom = await controller.getMinZoomLevel())(),
507519
]);
508-
} catch (_) {
509-
rethrow;
520+
} catch (e) {
521+
handleErrorWithHandler(e, widget.onError);
510522
} finally {
511523
safeSetState(() {});
512524
}
@@ -692,7 +704,10 @@ class CameraPickerState extends State<CameraPicker>
692704
/// 仅当初始化成功且相机未在拍照时拍照。
693705
Future<void> takePicture() async {
694706
if (!controller.value.isInitialized) {
695-
throw StateError('Camera has not initialized.');
707+
handleErrorWithHandler(
708+
StateError('Camera has not initialized.'),
709+
widget.onError,
710+
);
696711
}
697712
if (controller.value.isTakingPicture) {
698713
return;
@@ -720,7 +735,7 @@ class CameraPickerState extends State<CameraPicker>
720735
safeSetState(() {});
721736
} catch (e) {
722737
realDebugPrint('Error when preview the captured file: $e');
723-
rethrow;
738+
handleErrorWithHandler(e, widget.onError);
724739
}
725740
}
726741

@@ -784,7 +799,7 @@ class CameraPickerState extends State<CameraPicker>
784799
stopRecordingVideo();
785800
});
786801
}
787-
throw e;
802+
handleErrorWithHandler(e, widget.onError);
788803
});
789804
}
790805
}
@@ -816,7 +831,7 @@ class CameraPickerState extends State<CameraPicker>
816831
realDebugPrint('Try to initialize a new CameraController...');
817832
initCameras();
818833
_handleError();
819-
throw e;
834+
handleErrorWithHandler(e, widget.onError);
820835
}).whenComplete(() {
821836
isShootingButtonAnimate = false;
822837
safeSetState(() {});

lib/src/widgets/camera_picker_viewer.dart

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ class CameraPickerViewer extends StatefulWidget {
2828
required this.theme,
2929
this.shouldDeletePreviewFile = false,
3030
this.onEntitySaving,
31+
this.onError,
3132
}) : super(key: key);
3233

3334
/// State of the picker.
@@ -53,6 +54,9 @@ class CameraPickerViewer extends StatefulWidget {
5354
/// {@macro wechat_camera_picker.EntitySaveCallback}
5455
final EntitySaveCallback? onEntitySaving;
5556

57+
/// {@macro wechat_camera_picker.CameraErrorHandler}
58+
final CameraErrorHandler? onError;
59+
5660
/// Static method to push with the navigator.
5761
/// 跳转至选择预览的静态方法
5862
static Future<AssetEntity?> pushToViewer(
@@ -63,6 +67,7 @@ class CameraPickerViewer extends StatefulWidget {
6367
required ThemeData theme,
6468
bool shouldDeletePreviewFile = false,
6569
EntitySaveCallback? onEntitySaving,
70+
CameraErrorHandler? onError,
6671
}) {
6772
return Navigator.of(context).push<AssetEntity?>(
6873
PageRouteBuilder<AssetEntity?>(
@@ -73,6 +78,7 @@ class CameraPickerViewer extends StatefulWidget {
7378
theme: theme,
7479
shouldDeletePreviewFile: shouldDeletePreviewFile,
7580
onEntitySaving: onEntitySaving,
81+
onError: onError,
7682
),
7783
transitionsBuilder: (
7884
BuildContext context,
@@ -155,7 +161,7 @@ class _CameraPickerViewerState extends State<CameraPickerViewer> {
155161
} catch (e) {
156162
hasErrorWhenInitializing = true;
157163
realDebugPrint('Error when initializing video controller: $e');
158-
rethrow;
164+
handleErrorWithHandler(e, widget.onError);
159165
} finally {
160166
if (mounted) {
161167
setState(() {});
@@ -229,7 +235,7 @@ class _CameraPickerViewerState extends State<CameraPickerViewer> {
229235
}
230236
} catch (e) {
231237
realDebugPrint('Saving entity failed: $e');
232-
rethrow;
238+
handleErrorWithHandler(e, widget.onError);
233239
} finally {
234240
Navigator.of(context).pop(entity);
235241
}

0 commit comments

Comments
 (0)