diff --git a/assets/translations/en.json b/assets/translations/en.json index 12a46f1..ebce122 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -256,6 +256,8 @@ }, "addAttachmentFromAlbum": "Add from album", "addAttachmentFromClipboard": "Paste file", + "addAttachmentFromCameraPhoto": "Take photo", + "addAttachmentFromCameraVideo": "Take video", "attachmentPastedImage": "Pasted Image", "attachmentInsertLink": "Insert Link", "attachmentSetAsPostThumbnail": "Set as post thumbnail", diff --git a/assets/translations/zh.json b/assets/translations/zh.json index 692f7f5..fadf81a 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -256,6 +256,8 @@ }, "addAttachmentFromAlbum": "从相册中添加附件", "addAttachmentFromClipboard": "粘贴附件", + "addAttachmentFromCameraPhoto": "拍摄照片", + "addAttachmentFromCameraVideo": "拍摄视频", "attachmentPastedImage": "粘贴的图片", "attachmentInsertLink": "插入连接", "attachmentSetAsPostThumbnail": "设置为帖子缩略图", diff --git a/lib/screens/post/post_editor.dart b/lib/screens/post/post_editor.dart index 6474628..f5f64f1 100644 --- a/lib/screens/post/post_editor.dart +++ b/lib/screens/post/post_editor.dart @@ -1,6 +1,9 @@ +import 'dart:io'; + import 'package:collection/collection.dart'; import 'package:dropdown_button2/dropdown_button2.dart'; import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/foundation.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:gap/gap.dart'; @@ -75,6 +78,16 @@ class _PostEditorScreenState extends State { final _imagePicker = ImagePicker(); + void _takeMedia(bool isVideo) async { + final result = isVideo + ? await _imagePicker.pickVideo(source: ImageSource.camera) + : await _imagePicker.pickImage(source: ImageSource.camera); + if (result == null) return; + _writeController.addAttachments([ + PostWriteMedia.fromFile(result), + ]); + } + void _selectMedia() async { final result = await _imagePicker.pickMultipleMedia(); if (result.isEmpty) return; @@ -396,6 +409,32 @@ class _PostEditorScreenState extends State { color: Theme.of(context).colorScheme.primary, ), itemBuilder: (context) => [ + if (!kIsWeb && !Platform.isLinux && !Platform.isMacOS && !Platform.isWindows) + PopupMenuItem( + child: Row( + children: [ + const Icon(Symbols.photo_camera), + const Gap(16), + Text('addAttachmentFromCameraPhoto').tr(), + ], + ), + onTap: () { + _takeMedia(false); + }, + ), + if (!kIsWeb && !Platform.isLinux && !Platform.isMacOS && !Platform.isWindows) + PopupMenuItem( + child: Row( + children: [ + const Icon(Symbols.videocam), + const Gap(16), + Text('addAttachmentFromCameraVideo').tr(), + ], + ), + onTap: () { + _takeMedia(true); + }, + ), PopupMenuItem( child: Row( children: [ @@ -443,7 +482,7 @@ class _PostEditorScreenState extends State { ).padding(horizontal: 16), ], ).padding( - bottom: MediaQuery.of(context).padding.bottom, + bottom: MediaQuery.of(context).padding.bottom + 8, top: 4, ), ), diff --git a/lib/widgets/chat/chat_message_input.dart b/lib/widgets/chat/chat_message_input.dart index e7a17f1..6fe8e2e 100644 --- a/lib/widgets/chat/chat_message_input.dart +++ b/lib/widgets/chat/chat_message_input.dart @@ -1,4 +1,7 @@ +import 'dart:io'; + import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:gap/gap.dart'; import 'package:image_picker/image_picker.dart'; @@ -125,6 +128,17 @@ class ChatMessageInputState extends State { final List _attachments = List.empty(growable: true); final _imagePicker = ImagePicker(); + void _takeMedia(bool isVideo) async { + final result = isVideo + ? await _imagePicker.pickVideo(source: ImageSource.camera) + : await _imagePicker.pickImage(source: ImageSource.camera); + if (result == null) return; + _attachments.add( + PostWriteMedia.fromFile(result), + ); + setState(() {}); + } + void _selectMedia() async { final result = await _imagePicker.pickMultipleMedia(); if (result.isEmpty) return; @@ -283,6 +297,32 @@ class ChatMessageInputState extends State { color: Theme.of(context).colorScheme.primary, ), itemBuilder: (context) => [ + if (!kIsWeb && !Platform.isLinux && !Platform.isMacOS && !Platform.isWindows) + PopupMenuItem( + child: Row( + children: [ + const Icon(Symbols.photo_camera), + const Gap(16), + Text('addAttachmentFromCameraPhoto').tr(), + ], + ), + onTap: () { + _takeMedia(false); + }, + ), + if (!kIsWeb && !Platform.isLinux && !Platform.isMacOS && !Platform.isWindows) + PopupMenuItem( + child: Row( + children: [ + const Icon(Symbols.videocam), + const Gap(16), + Text('addAttachmentFromCameraVideo').tr(), + ], + ), + onTap: () { + _takeMedia(true); + }, + ), PopupMenuItem( child: Row( children: [ diff --git a/lib/widgets/navigation/app_drawer_navigation.dart b/lib/widgets/navigation/app_drawer_navigation.dart index c5eebbb..b886ec0 100644 --- a/lib/widgets/navigation/app_drawer_navigation.dart +++ b/lib/widgets/navigation/app_drawer_navigation.dart @@ -8,6 +8,7 @@ import 'package:surface/providers/navigation.dart'; class AppNavigationDrawer extends StatefulWidget { final double? elevation; + const AppNavigationDrawer({super.key, this.elevation}); @override @@ -19,9 +20,7 @@ class _AppNavigationDrawerState extends State { void initState() { super.initState(); WidgetsBinding.instance.addPostFrameCallback((_) { - context - .read() - .autoDetectIndex(GoRouter.maybeOf(context)); + context.read().autoDetectIndex(GoRouter.maybeOf(context)); }); } @@ -29,9 +28,7 @@ class _AppNavigationDrawerState extends State { Widget build(BuildContext context) { final nav = context.watch(); - final backgroundColor = ResponsiveBreakpoints.of(context).largerThan(TABLET) - ? Colors.transparent - : null; + final backgroundColor = ResponsiveBreakpoints.of(context).largerThan(TABLET) ? Colors.transparent : null; return ListenableBuilder( listenable: nav, @@ -51,13 +48,14 @@ class _AppNavigationDrawerState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('Solar Network').bold(), - Text('Canary Preview 2.0α').fontSize(12).textColor( - Theme.of(context).colorScheme.onSurface.withOpacity(0.5)), + Text('Canary Preview 2.0α') + .fontSize(12) + .textColor(Theme.of(context).colorScheme.onSurface.withOpacity(0.5)), ], ).padding( horizontal: 32, - top: MediaQuery.of(context).padding.top > 32 ? 8 : 32, - bottom: 8, + top: MediaQuery.of(context).padding.top + 8, + bottom: 12, ), ...destinations.where((ele) => ele.isPinned).map((ele) { return NavigationDrawerDestination(