Skip to content

Commit df5c555

Browse files
authored
Merge pull request #41 from powersync-ja/handle-missing-camera
Handle missing camera in demo
2 parents 030f84c + c4f9615 commit df5c555

File tree

4 files changed

+67
-40
lines changed

4 files changed

+67
-40
lines changed
Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,20 @@
11
import 'package:camera/camera.dart';
22
import 'package:flutter/widgets.dart';
3-
4-
late final CameraDescription? camera;
3+
import 'package:powersync_flutter_demo/powersync.dart';
54

65
Future<CameraDescription?> setupCamera() async {
76
// Ensure that plugin services are initialized so that `availableCameras()`
87
// can be called before `runApp()`
98
WidgetsFlutterBinding.ensureInitialized();
109
// Obtain a list of the available cameras on the device.
11-
final cameras = await availableCameras();
12-
// Get a specific camera from the list of available cameras.
13-
final camera = cameras.isNotEmpty ? cameras.first : null;
14-
return camera;
10+
try {
11+
final cameras = await availableCameras();
12+
// Get a specific camera from the list of available cameras.
13+
final camera = cameras.isNotEmpty ? cameras.first : null;
14+
return camera;
15+
} catch (e) {
16+
// Camera is not supported on all platforms
17+
log.warning('Failed to setup camera: $e');
18+
return null;
19+
}
1520
}

demos/supabase-todolist/lib/attachments/photo_capture_widget.dart

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,16 @@ import 'dart:async';
33
import 'package:camera/camera.dart';
44
import 'package:flutter/material.dart';
55
import 'package:powersync/powersync.dart' as powersync;
6-
import 'package:powersync_flutter_demo/attachments/camera_helpers.dart';
76
import 'package:powersync_flutter_demo/attachments/queue.dart';
87
import 'package:powersync_flutter_demo/models/todo_item.dart';
98
import 'package:powersync_flutter_demo/powersync.dart';
109

1110
class TakePhotoWidget extends StatefulWidget {
1211
final String todoId;
12+
final CameraDescription camera;
1313

14-
const TakePhotoWidget({super.key, required this.todoId});
14+
const TakePhotoWidget(
15+
{super.key, required this.todoId, required this.camera});
1516

1617
@override
1718
State<StatefulWidget> createState() {
@@ -28,7 +29,7 @@ class _TakePhotoWidgetState extends State<TakePhotoWidget> {
2829
super.initState();
2930

3031
_cameraController = CameraController(
31-
camera!,
32+
widget.camera,
3233
ResolutionPreset.medium,
3334
);
3435

Lines changed: 52 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import 'dart:io';
22

33
import 'package:flutter/material.dart';
4+
import 'package:powersync_flutter_demo/attachments/camera_helpers.dart';
45
import 'package:powersync_flutter_demo/attachments/photo_capture_widget.dart';
56
import 'package:powersync_flutter_demo/attachments/queue.dart';
67

@@ -19,31 +20,58 @@ class PhotoWidget extends StatefulWidget {
1920
}
2021
}
2122

23+
class _ResolvedPhotoState {
24+
String? photoPath;
25+
bool fileExists;
26+
27+
_ResolvedPhotoState({required this.photoPath, required this.fileExists});
28+
}
29+
2230
class _PhotoWidgetState extends State<PhotoWidget> {
2331
late String photoPath;
2432

25-
Future<Map<String, dynamic>> _getPhoto(photoId) async {
33+
Future<_ResolvedPhotoState> _getPhotoState(photoId) async {
2634
if (photoId == null) {
27-
return {"photoPath": null, "fileExists": false};
35+
return _ResolvedPhotoState(photoPath: null, fileExists: false);
2836
}
2937
photoPath = await attachmentQueue.getLocalUri('$photoId.jpg');
3038

3139
bool fileExists = await File(photoPath).exists();
3240

33-
return {"photoPath": photoPath, "fileExists": fileExists};
41+
return _ResolvedPhotoState(photoPath: photoPath, fileExists: fileExists);
3442
}
3543

3644
@override
3745
Widget build(BuildContext context) {
3846
return FutureBuilder(
39-
future: _getPhoto(widget.todo.photoId),
40-
builder: (BuildContext context, AsyncSnapshot snapshot) {
47+
future: _getPhotoState(widget.todo.photoId),
48+
builder: (BuildContext context,
49+
AsyncSnapshot<_ResolvedPhotoState> snapshot) {
50+
if (snapshot.data == null) {
51+
return Container();
52+
}
53+
final data = snapshot.data!;
4154
Widget takePhotoButton = ElevatedButton(
42-
onPressed: () {
55+
onPressed: () async {
56+
final camera = await setupCamera();
57+
if (!mounted) return;
58+
59+
if (camera == null) {
60+
const snackBar = SnackBar(
61+
content: Text('No camera available'),
62+
backgroundColor:
63+
Colors.red, // Optional: to highlight it's an error
64+
);
65+
66+
ScaffoldMessenger.of(context).showSnackBar(snackBar);
67+
return;
68+
}
69+
4370
Navigator.push(
4471
context,
4572
MaterialPageRoute(
46-
builder: (context) => TakePhotoWidget(todoId: widget.todo.id),
73+
builder: (context) =>
74+
TakePhotoWidget(todoId: widget.todo.id, camera: camera),
4775
),
4876
);
4977
},
@@ -54,29 +82,25 @@ class _PhotoWidgetState extends State<PhotoWidget> {
5482
return takePhotoButton;
5583
}
5684

57-
if (snapshot.hasData) {
58-
String filePath = snapshot.data['photoPath'];
59-
bool fileIsDownloading = !snapshot.data['fileExists'];
60-
61-
if (fileIsDownloading) {
62-
return const Text("Downloading...");
63-
}
64-
65-
File imageFile = File(filePath);
66-
int lastModified = imageFile.existsSync()
67-
? imageFile.lastModifiedSync().millisecondsSinceEpoch
68-
: 0;
69-
Key key = ObjectKey('$filePath:$lastModified');
70-
71-
return Image.file(
72-
key: key,
73-
imageFile,
74-
width: 50,
75-
height: 50,
76-
);
85+
String? filePath = data.photoPath;
86+
bool fileIsDownloading = !data.fileExists;
87+
88+
if (fileIsDownloading) {
89+
return const Text("Downloading...");
7790
}
7891

79-
return takePhotoButton;
92+
File imageFile = File(filePath!);
93+
int lastModified = imageFile.existsSync()
94+
? imageFile.lastModifiedSync().millisecondsSinceEpoch
95+
: 0;
96+
Key key = ObjectKey('$filePath:$lastModified');
97+
98+
return Image.file(
99+
key: key,
100+
imageFile,
101+
width: 50,
102+
height: 50,
103+
);
80104
});
81105
}
82106
}

demos/supabase-todolist/lib/main.dart

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import 'package:flutter/foundation.dart';
22
import 'package:flutter/material.dart';
33
import 'package:logging/logging.dart';
44
import 'package:powersync_flutter_demo/app_config.dart';
5-
import 'package:powersync_flutter_demo/attachments/camera_helpers.dart';
65
import 'package:powersync_flutter_demo/attachments/queue.dart';
76
import 'package:powersync_flutter_demo/models/schema.dart';
87

@@ -38,8 +37,6 @@ void main() async {
3837
initializeAttachmentQueue(db);
3938
}
4039

41-
camera = await setupCamera();
42-
4340
final loggedIn = isLoggedIn();
4441
runApp(MyApp(loggedIn: loggedIn));
4542
}

0 commit comments

Comments
 (0)