Skip to content

Commit

Permalink
compose: Prototype upload-from-camera UI
Browse files Browse the repository at this point in the history
Fixes: #61
  • Loading branch information
chrisbobbe committed Apr 22, 2023
1 parent 1eca02e commit a3a889a
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 0 deletions.
2 changes: 2 additions & 0 deletions ios/Runner/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@
<array>
<string>fetch</string>
</array>
<key>NSCameraUsageDescription</key>
<string>By allowing camera access, you can take photos and send them in Zulip messages.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>Choose photos from your library and send them in Zulip messages.</string>
</dict>
Expand Down
47 changes: 47 additions & 0 deletions lib/widgets/compose_box.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import 'package:app_settings/app_settings.dart';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:image_picker/image_picker.dart';
import 'dialog.dart';

import '../api/route/messages.dart';
Expand Down Expand Up @@ -376,6 +377,51 @@ class _AttachMediaButton extends _AttachUploadsButton {
}
}

class _AttachFromCameraButton extends _AttachUploadsButton {
const _AttachFromCameraButton({required super.contentController, required super.contentFocusNode});

@override
IconData get icon => Icons.camera_alt;

@override
Future<Iterable<_File>?> getFiles(BuildContext context) async {
final picker = ImagePicker();
final XFile? result;
try {
// Ideally we'd open a platform interface that lets you choose between
// taking a photo and a video. `image_picker` doesn't yet have that
// option: https://github.com/flutter/flutter/issues/89159
// so just stick with images for now. We could add another button for
// videos, but we don't want too many buttons.
result = await picker.pickImage(source: ImageSource.camera, requestFullMetadata: false);
} catch (e) {
if (e is PlatformException && e.code == 'camera_access_denied') {
// iOS has a quirk where it will only request the native
// permission-request alert once, the first time the app wants to
// use a protected resource. After that, the only way the user can
// grant it is in Settings.
showSuggestedActionDialog(context: context, // TODO(i18n)
title: 'Permissions needed',
message: 'To upload an image, please grant Zulip additional permissions in Settings.',
actionButtonText: 'Open settings',
onActionButtonPress: () {
AppSettings.openAppSettings();
});
} else {
// TODO(i18n)
showErrorDialog(context: context, title: 'Error', message: e.toString());
}
return null;
}
if (result == null) {
return null; // User cancelled; do nothing
}
final length = await result.length();

return [_File(content: result.openRead(), length: length, filename: result.name)];
}
}

/// The send button for StreamComposeBox.
class _StreamSendButton extends StatefulWidget {
const _StreamSendButton({required this.topicController, required this.contentController});
Expand Down Expand Up @@ -575,6 +621,7 @@ class _StreamComposeBoxState extends State<StreamComposeBox> {
children: [
_AttachFileButton(contentController: _contentController, contentFocusNode: _contentFocusNode),
_AttachMediaButton(contentController: _contentController, contentFocusNode: _contentFocusNode),
_AttachFromCameraButton(contentController: _contentController, contentFocusNode: _contentFocusNode),
])),
]))));
}
Expand Down

0 comments on commit a3a889a

Please sign in to comment.