Compare commits

..

No commits in common. "f26edce071b3feaa395c2baefddde4bca7da8992" and "96fd64d85d876d0c3e02497b54525ce14e5f93a3" have entirely different histories.

17 changed files with 162 additions and 380 deletions

View File

@ -282,7 +282,6 @@
"other": "{} attachments" "other": "{} attachments"
}, },
"fieldAttachmentRandomId": "Random ID", "fieldAttachmentRandomId": "Random ID",
"fieldAttachmentAlt": "Alternative text",
"addAttachmentFromAlbum": "Add from album", "addAttachmentFromAlbum": "Add from album",
"addAttachmentFromClipboard": "Paste file", "addAttachmentFromClipboard": "Paste file",
"addAttachmentFromCameraPhoto": "Take photo", "addAttachmentFromCameraPhoto": "Take photo",
@ -294,7 +293,6 @@
"attachmentUnsetAsPostThumbnail": "Unset as post thumbnail", "attachmentUnsetAsPostThumbnail": "Unset as post thumbnail",
"attachmentCompressVideo": "Re-encode video", "attachmentCompressVideo": "Re-encode video",
"attachmentSetThumbnail": "Set thumbnail", "attachmentSetThumbnail": "Set thumbnail",
"attachmentSetAlt": "Set alternative text",
"attachmentCopyRandomId": "Copy RID", "attachmentCopyRandomId": "Copy RID",
"attachmentUpload": "Upload", "attachmentUpload": "Upload",
"attachmentInputDialog": "Upload attachments", "attachmentInputDialog": "Upload attachments",

View File

@ -280,7 +280,6 @@
"other": "{} 个附件" "other": "{} 个附件"
}, },
"fieldAttachmentRandomId": "访问 ID", "fieldAttachmentRandomId": "访问 ID",
"fieldAttachmentAlt": "概述文字",
"addAttachmentFromAlbum": "从相册中添加附件", "addAttachmentFromAlbum": "从相册中添加附件",
"addAttachmentFromClipboard": "粘贴附件", "addAttachmentFromClipboard": "粘贴附件",
"addAttachmentFromCameraPhoto": "拍摄照片", "addAttachmentFromCameraPhoto": "拍摄照片",
@ -292,7 +291,6 @@
"attachmentUnsetAsPostThumbnail": "取消设置为帖子缩略图", "attachmentUnsetAsPostThumbnail": "取消设置为帖子缩略图",
"attachmentCompressVideo": "重新编码视频", "attachmentCompressVideo": "重新编码视频",
"attachmentSetThumbnail": "设置缩略图", "attachmentSetThumbnail": "设置缩略图",
"attachmentSetAlt": "设置概述文字",
"attachmentCopyRandomId": "复制访问 ID", "attachmentCopyRandomId": "复制访问 ID",
"attachmentUpload": "上传", "attachmentUpload": "上传",
"attachmentInputDialog": "上传附件", "attachmentInputDialog": "上传附件",

View File

@ -280,7 +280,6 @@
"other": "{} 個附件" "other": "{} 個附件"
}, },
"fieldAttachmentRandomId": "訪問 ID", "fieldAttachmentRandomId": "訪問 ID",
"fieldAttachmentAlt": "概述文字",
"addAttachmentFromAlbum": "從相冊中添加附件", "addAttachmentFromAlbum": "從相冊中添加附件",
"addAttachmentFromClipboard": "粘貼附件", "addAttachmentFromClipboard": "粘貼附件",
"addAttachmentFromCameraPhoto": "拍攝照片", "addAttachmentFromCameraPhoto": "拍攝照片",
@ -292,7 +291,6 @@
"attachmentUnsetAsPostThumbnail": "取消設置為帖子縮略圖", "attachmentUnsetAsPostThumbnail": "取消設置為帖子縮略圖",
"attachmentCompressVideo": "重新編碼視頻", "attachmentCompressVideo": "重新編碼視頻",
"attachmentSetThumbnail": "設置縮略圖", "attachmentSetThumbnail": "設置縮略圖",
"attachmentSetAlt": "設置概述文字",
"attachmentCopyRandomId": "複製訪問 ID", "attachmentCopyRandomId": "複製訪問 ID",
"attachmentUpload": "上傳", "attachmentUpload": "上傳",
"attachmentInputDialog": "上傳附件", "attachmentInputDialog": "上傳附件",

View File

@ -280,7 +280,6 @@
"other": "{} 個附件" "other": "{} 個附件"
}, },
"fieldAttachmentRandomId": "訪問 ID", "fieldAttachmentRandomId": "訪問 ID",
"fieldAttachmentAlt": "概述文字",
"addAttachmentFromAlbum": "從相冊中添加附件", "addAttachmentFromAlbum": "從相冊中添加附件",
"addAttachmentFromClipboard": "粘貼附件", "addAttachmentFromClipboard": "粘貼附件",
"addAttachmentFromCameraPhoto": "拍攝照片", "addAttachmentFromCameraPhoto": "拍攝照片",
@ -292,7 +291,6 @@
"attachmentUnsetAsPostThumbnail": "取消設置為帖子縮略圖", "attachmentUnsetAsPostThumbnail": "取消設置為帖子縮略圖",
"attachmentCompressVideo": "重新編碼視頻", "attachmentCompressVideo": "重新編碼視頻",
"attachmentSetThumbnail": "設置縮略圖", "attachmentSetThumbnail": "設置縮略圖",
"attachmentSetAlt": "設置概述文字",
"attachmentCopyRandomId": "複製訪問 ID", "attachmentCopyRandomId": "複製訪問 ID",
"attachmentUpload": "上傳", "attachmentUpload": "上傳",
"attachmentInputDialog": "上傳附件", "attachmentInputDialog": "上傳附件",

View File

@ -211,9 +211,6 @@ PODS:
- shared_preferences_foundation (0.0.1): - shared_preferences_foundation (0.0.1):
- Flutter - Flutter
- FlutterMacOS - FlutterMacOS
- sqflite_darwin (0.0.4):
- Flutter
- FlutterMacOS
- SwiftyGif (5.4.5) - SwiftyGif (5.4.5)
- url_launcher_ios (0.0.1): - url_launcher_ios (0.0.1):
- Flutter - Flutter
@ -259,7 +256,6 @@ DEPENDENCIES:
- screen_brightness_ios (from `.symlinks/plugins/screen_brightness_ios/ios`) - screen_brightness_ios (from `.symlinks/plugins/screen_brightness_ios/ios`)
- share_plus (from `.symlinks/plugins/share_plus/ios`) - share_plus (from `.symlinks/plugins/share_plus/ios`)
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`) - shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
- sqflite_darwin (from `.symlinks/plugins/sqflite_darwin/darwin`)
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`) - url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
- video_compress (from `.symlinks/plugins/video_compress/ios`) - video_compress (from `.symlinks/plugins/video_compress/ios`)
- volume_controller (from `.symlinks/plugins/volume_controller/ios`) - volume_controller (from `.symlinks/plugins/volume_controller/ios`)
@ -347,8 +343,6 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/share_plus/ios" :path: ".symlinks/plugins/share_plus/ios"
shared_preferences_foundation: shared_preferences_foundation:
:path: ".symlinks/plugins/shared_preferences_foundation/darwin" :path: ".symlinks/plugins/shared_preferences_foundation/darwin"
sqflite_darwin:
:path: ".symlinks/plugins/sqflite_darwin/darwin"
url_launcher_ios: url_launcher_ios:
:path: ".symlinks/plugins/url_launcher_ios/ios" :path: ".symlinks/plugins/url_launcher_ios/ios"
video_compress: video_compress:
@ -407,7 +401,6 @@ SPEC CHECKSUMS:
SDWebImage: 73c6079366fea25fa4bb9640d5fb58f0893facd8 SDWebImage: 73c6079366fea25fa4bb9640d5fb58f0893facd8
share_plus: 8b6f8b3447e494cca5317c8c3073de39b3600d1f share_plus: 8b6f8b3447e494cca5317c8c3073de39b3600d1f
shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78 shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78
sqflite_darwin: 5a7236e3b501866c1c9befc6771dfd73ffb8702d
SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4 SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4
url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe
video_compress: fce97e4fb1dfd88175aa07d2ffc8a2f297f87fbe video_compress: fce97e4fb1dfd88175aa07d2ffc8a2f297f87fbe

View File

@ -213,11 +213,11 @@ class PostWriteController extends ChangeNotifier {
aliasController.text = post.alias ?? ''; aliasController.text = post.alias ?? '';
publishedAt = post.publishedAt; publishedAt = post.publishedAt;
publishedUntil = post.publishedUntil; publishedUntil = post.publishedUntil;
visibleUsers = List.from(post.visibleUsersList ?? [], growable: true); visibleUsers = List.from(post.visibleUsersList ?? []);
invisibleUsers = List.from(post.invisibleUsersList ?? [], growable: true); invisibleUsers = List.from(post.invisibleUsersList ?? []);
visibility = post.visibility; visibility = post.visibility;
tags = List.from(post.tags.map((ele) => ele.alias), growable: true); tags = List.from(post.tags.map((ele) => ele.alias));
categories = List.from(post.categories.map((ele) => ele.alias), growable: true); categories = List.from(post.categories.map((ele) => ele.alias));
attachments.addAll(post.preload?.attachments?.map((ele) => PostWriteMedia(ele)) ?? []); attachments.addAll(post.preload?.attachments?.map((ele) => PostWriteMedia(ele)) ?? []);
if (post.preload?.thumbnail != null && (post.preload?.thumbnail?.rid.isNotEmpty ?? false)) { if (post.preload?.thumbnail != null && (post.preload?.thumbnail?.rid.isNotEmpty ?? false)) {
@ -344,10 +344,9 @@ class PostWriteController extends ChangeNotifier {
if (titleController.text.isNotEmpty) 'title': titleController.text, if (titleController.text.isNotEmpty) 'title': titleController.text,
if (descriptionController.text.isNotEmpty) 'description': descriptionController.text, if (descriptionController.text.isNotEmpty) 'description': descriptionController.text,
if (thumbnail != null && thumbnail!.attachment != null) 'thumbnail': thumbnail!.attachment!.toJson(), if (thumbnail != null && thumbnail!.attachment != null) 'thumbnail': thumbnail!.attachment!.toJson(),
'attachments': 'attachments': attachments.where((e) => e.attachment != null).map((e) => e.attachment!.toJson()).toList(),
attachments.where((e) => e.attachment != null).map((e) => e.attachment!.toJson()).toList(growable: true), 'tags': tags.map((ele) => {'alias': ele}).toList(),
'tags': tags.map((ele) => {'alias': ele}).toList(growable: true), 'categories': categories.map((ele) => {'alias': ele}).toList(),
'categories': categories.map((ele) => {'alias': ele}).toList(growable: true),
'visibility': visibility, 'visibility': visibility,
'visible_users_list': visibleUsers, 'visible_users_list': visibleUsers,
'invisible_users_list': invisibleUsers, 'invisible_users_list': invisibleUsers,

View File

@ -365,8 +365,6 @@ class _PostEditorScreenState extends State<PostEditorScreen> {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Container( Container(
child: _writeController.temporaryRestored
? Container(
padding: const EdgeInsets.only(top: 4, bottom: 4, left: 28, right: 22), padding: const EdgeInsets.only(top: 4, bottom: 4, left: 28, right: 22),
decoration: BoxDecoration( decoration: BoxDecoration(
border: Border( border: Border(
@ -376,7 +374,8 @@ class _PostEditorScreenState extends State<PostEditorScreen> {
), ),
), ),
), ),
child: Row( child: _writeController.temporaryRestored
? Row(
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
children: [ children: [
const Icon(Icons.restore, size: 20), const Icon(Icons.restore, size: 20),
@ -389,7 +388,7 @@ class _PostEditorScreenState extends State<PostEditorScreen> {
}, },
), ),
], ],
)) )
: const SizedBox.shrink(), : const SizedBox.shrink(),
) )
.height(_writeController.temporaryRestored ? 32 : 0, animate: true) .height(_writeController.temporaryRestored ? 32 : 0, animate: true)

View File

@ -315,7 +315,6 @@ class _AttachmentItemContentVideoState extends State<_AttachmentItemContentVideo
} }
return MaterialDesktopVideoControlsTheme( return MaterialDesktopVideoControlsTheme(
key: Key('material-desktop-video-controls-theme-$_showOriginal'),
normal: MaterialDesktopVideoControlsThemeData( normal: MaterialDesktopVideoControlsThemeData(
buttonBarButtonSize: 24, buttonBarButtonSize: 24,
buttonBarButtonColor: Colors.white, buttonBarButtonColor: Colors.white,
@ -325,16 +324,14 @@ class _AttachmentItemContentVideoState extends State<_AttachmentItemContentVideo
MaterialDesktopCustomButton( MaterialDesktopCustomButton(
iconSize: 24, iconSize: 24,
onPressed: _toggleOriginal, onPressed: _toggleOriginal,
icon: Icon( icon: Builder(builder: (context) {
_showOriginal ? Symbols.high_quality : Symbols.sd, return _showOriginal ? const Icon(Symbols.high_quality, size: 24) : const Icon(Symbols.sd, size: 24);
size: 24, }),
),
), ),
], ],
), ),
fullscreen: const MaterialDesktopVideoControlsThemeData(), fullscreen: const MaterialDesktopVideoControlsThemeData(),
child: MaterialVideoControlsTheme( child: MaterialVideoControlsTheme(
key: Key('material-video-controls-theme-$_showOriginal'),
normal: MaterialVideoControlsThemeData( normal: MaterialVideoControlsThemeData(
buttonBarButtonSize: 24, buttonBarButtonSize: 24,
buttonBarButtonColor: Colors.white, buttonBarButtonColor: Colors.white,

View File

@ -1,87 +0,0 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:gap/gap.dart';
import 'package:provider/provider.dart';
import 'package:surface/controllers/post_write_controller.dart';
import 'package:surface/providers/sn_attachment.dart';
import 'package:surface/widgets/dialog.dart';
class PendingAttachmentAltDialog extends StatefulWidget {
final PostWriteMedia media;
const PendingAttachmentAltDialog({super.key, required this.media});
@override
State<PendingAttachmentAltDialog> createState() => _PendingAttachmentAltDialogState();
}
class _PendingAttachmentAltDialogState extends State<PendingAttachmentAltDialog> {
final _contentController = TextEditingController();
@override
void initState() {
super.initState();
_contentController.text = widget.media.attachment!.alt;
}
bool _isBusy = false;
Future<void> _performAction() async {
if (_isBusy) return;
setState(() => _isBusy = true);
try {
final attach = context.read<SnAttachmentProvider>();
final result = await attach.updateOne(
widget.media.attachment!,
alt: _contentController.text,
);
if (!mounted) return;
attach.putCache([result]);
Navigator.pop(context, result);
} catch (err) {
if (!mounted) return;
context.showErrorDialog(err);
setState(() => _isBusy = false);
}
}
@override
void dispose() {
_contentController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return AlertDialog(
title: Text('attachmentSetAlt').tr(),
content: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TextField(
controller: _contentController,
decoration: InputDecoration(
labelText: 'fieldAttachmentAlt'.tr(),
border: const UnderlineInputBorder(),
),
onTapOutside: (_) => FocusManager.instance.primaryFocus?.unfocus(),
),
],
),
actions: [
TextButton(
onPressed: _isBusy ? null : () {
Navigator.pop(context);
},
child: Text('dialogDismiss'.tr()),
),
TextButton(
onPressed: _isBusy ? null : () => _performAction(),
child: Text('dialogConfirm'.tr()),
),
],
);
}
}

View File

@ -53,7 +53,7 @@ class ChatMessage extends StatelessWidget {
iconOnRightSwipe: Symbols.edit, iconOnRightSwipe: Symbols.edit,
swipeSensitivity: 20, swipeSensitivity: 20,
onLeftSwipe: onReply != null ? (_) => onReply!(data) : null, onLeftSwipe: onReply != null ? (_) => onReply!(data) : null,
onRightSwipe: (onEdit != null && isOwner) ? (_) => onEdit!(data) : null, onRightSwipe: onEdit != null ? (_) => onEdit!(data) : null,
child: ContextMenuArea( child: ContextMenuArea(
contextMenu: ContextMenu( contextMenu: ContextMenu(
entries: [ entries: [
@ -103,17 +103,18 @@ class ChatMessage extends StatelessWidget {
children: [ children: [
if (!isMerged) if (!isMerged)
Row( Row(
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.baseline,
textBaseline: TextBaseline.alphabetic,
children: [ children: [
if (isCompact) if (isCompact)
AccountImage( AccountImage(
content: user?.avatar, content: user?.avatar,
radius: 12, radius: 12,
).padding(right: 8), ).padding(right: 6),
Text( Text(
(data.sender.nick?.isNotEmpty ?? false) ? data.sender.nick! : user?.nick ?? 'unknown', (data.sender.nick?.isNotEmpty ?? false) ? data.sender.nick! : user?.nick ?? 'unknown',
).bold(), ).bold(),
const Gap(8), const Gap(6),
Text( Text(
dateFormatter.format(data.createdAt.toLocal()), dateFormatter.format(data.createdAt.toLocal()),
).fontSize(13), ).fontSize(13),
@ -152,7 +153,7 @@ class ChatMessage extends StatelessWidget {
) )
], ],
).opacity(isPending ? 0.5 : 1), ).opacity(isPending ? 0.5 : 1),
if (data.body['text'] != null && data.type == 'messages.new' && (data.body['text']?.isNotEmpty ?? false)) if (data.body['text'] != null && (data.body['text']?.isNotEmpty ?? false))
LinkPreviewWidget(text: data.body['text']!), LinkPreviewWidget(text: data.body['text']!),
if (data.preload?.attachments?.isNotEmpty ?? false) if (data.preload?.attachments?.isNotEmpty ?? false)
AttachmentList( AttachmentList(
@ -160,8 +161,7 @@ class ChatMessage extends StatelessWidget {
bordered: true, bordered: true,
gridded: true, gridded: true,
noGrow: true, noGrow: true,
maxHeight: 560, maxHeight: 520,
minWidth: 480,
padding: const EdgeInsets.only(top: 8), padding: const EdgeInsets.only(top: 8),
), ),
if (!hasMerged && !isCompact) const Gap(12) else if (!isCompact) const Gap(6), if (!hasMerged && !isCompact) const Gap(12) else if (!isCompact) const Gap(6),

View File

@ -161,84 +161,75 @@ class ChatMessageInputState extends State<ChatMessageInput> {
.animate(const Duration(milliseconds: 300), Curves.fastEaseInToSlowEaseOut), .animate(const Duration(milliseconds: 300), Curves.fastEaseInToSlowEaseOut),
SingleChildScrollView( SingleChildScrollView(
physics: const NeverScrollableScrollPhysics(), physics: const NeverScrollableScrollPhysics(),
child: Padding(
padding: _replyingMessage != null ? const EdgeInsets.only(top: 8) : EdgeInsets.zero,
child: _replyingMessage != null child: _replyingMessage != null
? Container( ? MaterialBanner(
padding: const EdgeInsets.only(left: 16, right: 16), padding: const EdgeInsets.only(left: 16.0),
decoration: BoxDecoration( leading: const Icon(Symbols.reply),
borderRadius: const BorderRadius.all(Radius.circular(8)), backgroundColor: Colors.transparent,
border: Border( content: SingleChildScrollView(
bottom: BorderSide( physics: const NeverScrollableScrollPhysics(),
color: Theme.of(context).dividerColor, child: Column(
width: 1 / MediaQuery.of(context).devicePixelRatio, mainAxisAlignment: MainAxisAlignment.center,
), crossAxisAlignment: CrossAxisAlignment.start,
),
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [ children: [
const Icon(Symbols.reply, size: 20), if (_replyingMessage?.body['text'] != null)
const Gap(8), MarkdownTextContent(
Expanded( content: _replyingMessage?.body['text'],
child: Text( ),
_replyingMessage?.body['text'] ?? '${_replyingMessage?.sender.nick}', ],
maxLines: 1,
overflow: TextOverflow.ellipsis,
), ),
), ),
const Gap(16), actions: [
InkWell( TextButton(
child: Text('cancel'.tr()), child: Text('cancel'.tr()),
onTap: () { onPressed: () {
setState(() => _replyingMessage = null); setState(() => _replyingMessage = null);
}, },
), ),
], ],
).padding(vertical: 8),
) )
: const SizedBox.shrink(), : const SizedBox.shrink(),
),
) )
.height(_replyingMessage != null ? 38 : 0, animate: true) .height(_replyingMessage != null ? 54 + 8 : 0, animate: true)
.animate(const Duration(milliseconds: 300), Curves.fastEaseInToSlowEaseOut), .animate(const Duration(milliseconds: 300), Curves.fastEaseInToSlowEaseOut),
SingleChildScrollView( SingleChildScrollView(
physics: const NeverScrollableScrollPhysics(), physics: const NeverScrollableScrollPhysics(),
child: Padding(
padding: _editingMessage != null ? const EdgeInsets.only(top: 8) : EdgeInsets.zero,
child: _editingMessage != null child: _editingMessage != null
? Container( ? MaterialBanner(
padding: const EdgeInsets.only(left: 16, right: 16), padding: const EdgeInsets.only(left: 16.0),
decoration: BoxDecoration( leading: const Icon(Symbols.edit),
borderRadius: const BorderRadius.all(Radius.circular(8)), backgroundColor: Colors.transparent,
border: Border( content: SingleChildScrollView(
bottom: BorderSide( physics: const NeverScrollableScrollPhysics(),
color: Theme.of(context).dividerColor, child: Column(
width: 1 / MediaQuery.of(context).devicePixelRatio, mainAxisAlignment: MainAxisAlignment.center,
), crossAxisAlignment: CrossAxisAlignment.start,
),
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [ children: [
const Icon(Symbols.edit, size: 20), if (_editingMessage?.body['text'] != null)
const Gap(8), MarkdownTextContent(
Expanded( content: _editingMessage?.body['text'],
child: Text( ),
_editingMessage?.body['text'] ?? '${_editingMessage?.sender.nick}', ],
maxLines: 1,
overflow: TextOverflow.ellipsis,
), ),
), ),
const Gap(16), actions: [
InkWell( TextButton(
child: Text('cancel'.tr()), child: Text('cancel'.tr()),
onTap: () { onPressed: () {
_contentController.clear();
setState(() => _editingMessage = null); setState(() => _editingMessage = null);
}, },
), ),
], ],
).padding(vertical: 8),
) )
: const SizedBox.shrink(), : const SizedBox.shrink(),
),
) )
.height(_editingMessage != null ? 38 : 0, animate: true) .height(_editingMessage != null ? 54 + 8 : 0, animate: true)
.animate(const Duration(milliseconds: 300), Curves.fastEaseInToSlowEaseOut), .animate(const Duration(milliseconds: 300), Curves.fastEaseInToSlowEaseOut),
SizedBox( SizedBox(
height: 56, height: 56,

View File

@ -21,7 +21,6 @@ import 'package:surface/providers/sn_network.dart';
import 'package:surface/types/attachment.dart'; import 'package:surface/types/attachment.dart';
import 'package:surface/widgets/attachment/attachment_input.dart'; import 'package:surface/widgets/attachment/attachment_input.dart';
import 'package:surface/widgets/attachment/attachment_zoom.dart'; import 'package:surface/widgets/attachment/attachment_zoom.dart';
import 'package:surface/widgets/attachment/pending_attachment_alt.dart';
import 'package:surface/widgets/attachment/pending_attachment_boost.dart'; import 'package:surface/widgets/attachment/pending_attachment_boost.dart';
import 'package:surface/widgets/context_menu.dart'; import 'package:surface/widgets/context_menu.dart';
import 'package:surface/widgets/dialog.dart'; import 'package:surface/widgets/dialog.dart';
@ -158,16 +157,6 @@ class PostMediaPendingList extends StatelessWidget {
onUpdate!(idx, result); onUpdate!(idx, result);
} }
Future<void> _setAlt(BuildContext context, int idx) async {
final result = await showDialog<SnAttachment?>(
context: context,
builder: (context) => PendingAttachmentAltDialog(media: attachments[idx]),
);
if (result == null) return;
onUpdate!(idx, PostWriteMedia(result));
}
ContextMenu _createContextMenu(BuildContext context, int idx, PostWriteMedia media) { ContextMenu _createContextMenu(BuildContext context, int idx, PostWriteMedia media) {
final canCompressVideo = !kIsWeb && (Platform.isAndroid || Platform.isIOS || Platform.isMacOS); final canCompressVideo = !kIsWeb && (Platform.isAndroid || Platform.isIOS || Platform.isMacOS);
return ContextMenu( return ContextMenu(
@ -180,14 +169,6 @@ class PostMediaPendingList extends StatelessWidget {
_compressVideo(context, idx); _compressVideo(context, idx);
}, },
), ),
if (media.attachment != null)
MenuItem(
label: 'attachmentSetAlt'.tr(),
icon: Symbols.description,
onSelected: () {
_setAlt(context, idx);
},
),
if (media.attachment != null) if (media.attachment != null)
MenuItem( MenuItem(
label: 'attachmentBoost'.tr(), label: 'attachmentBoost'.tr(),

View File

@ -1,4 +1,4 @@
import 'package:cached_network_image/cached_network_image.dart'; import 'package:extended_image/extended_image.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:material_symbols_icons/symbols.dart'; import 'package:material_symbols_icons/symbols.dart';
@ -7,7 +7,6 @@ import 'package:styled_widget/styled_widget.dart';
import 'package:flutter_animate/flutter_animate.dart'; import 'package:flutter_animate/flutter_animate.dart';
// Keep this import to make the web image render work // Keep this import to make the web image render work
import 'package:cached_network_image_platform_interface/cached_network_image_platform_interface.dart';
import 'package:surface/providers/config.dart'; import 'package:surface/providers/config.dart';
class UniversalImage extends StatelessWidget { class UniversalImage extends StatelessWidget {
@ -34,45 +33,27 @@ class UniversalImage extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final devicePixelRatio = MediaQuery.of(context).devicePixelRatio; final quality = filterQuality ?? context.read<ConfigProvider>().imageQuality;
final double? resizeHeight = cacheHeight != null ? (cacheHeight! * devicePixelRatio) : null;
final double? resizeWidth = cacheWidth != null ? (cacheWidth! * devicePixelRatio) : null;
return Image( return ExtendedImage.network(
filterQuality: filterQuality ?? context.read<ConfigProvider>().imageQuality, url,
image: kIsWeb
? UniversalImage.provider(url)
: ResizeImage(
UniversalImage.provider(url),
width: resizeWidth?.round(),
height: resizeHeight?.round(),
policy: ResizeImagePolicy.fit,
),
width: width, width: width,
height: height, height: height,
fit: fit, fit: fit,
loadingBuilder: noProgressIndicator cache: true,
? null compressionRatio: kIsWeb ? 1 : switch(quality) {
: (BuildContext context, Widget child, ImageChunkEvent? loadingProgress) { FilterQuality.high => 1,
if (loadingProgress == null) return child; FilterQuality.medium => 0.75,
return Center( FilterQuality.low => 0.5,
child: TweenAnimationBuilder( FilterQuality.none => 0.25,
tween: Tween(
begin: 0,
end: loadingProgress.expectedTotalBytes != null
? loadingProgress.cumulativeBytesLoaded / loadingProgress.expectedTotalBytes!
: 0,
),
duration: const Duration(milliseconds: 300),
builder: (context, value, _) => CircularProgressIndicator(
value: loadingProgress.expectedTotalBytes != null ? value.toDouble() : null,
),
),
);
}, },
errorBuilder: noErrorWidget filterQuality: quality,
? null enableLoadState: true,
: (context, error, stackTrace) { retries: 3,
loadStateChanged: (ExtendedImageState state) {
if (state.extendedImageLoadState == LoadState.completed) {
return state.completedWidget;
} else if (state.extendedImageLoadState == LoadState.failed) {
return Material( return Material(
color: Theme.of(context).colorScheme.surface, color: Theme.of(context).colorScheme.surface,
child: Container( child: Container(
@ -84,13 +65,21 @@ class UniversalImage extends StatelessWidget {
.animate(onPlay: (e) => e.repeat(reverse: true)) .animate(onPlay: (e) => e.repeat(reverse: true))
.fade(duration: 500.ms), .fade(duration: 500.ms),
Text( Text(
error.toString(), state.lastException.toString(),
textAlign: TextAlign.center, textAlign: TextAlign.center,
), ),
], ],
).center(), ).center(),
), ),
); );
}
return Center(
child: CircularProgressIndicator(
value: state.loadingProgress != null
? state.loadingProgress!.cumulativeBytesLoaded / state.loadingProgress!.expectedTotalBytes!
: null,
),
);
}, },
); );
} }
@ -99,9 +88,10 @@ class UniversalImage extends StatelessWidget {
// This place used to use network image or cached network image depending on the platform. // This place used to use network image or cached network image depending on the platform.
// But now the cached network image is working on every platform. // But now the cached network image is working on every platform.
// So we just use it now. // So we just use it now.
return CachedNetworkImageProvider( return ExtendedNetworkImageProvider(
url, url,
imageRenderMethodForWeb: ImageRenderMethodForWeb.HttpGet, cache: true,
retries: 3,
); );
} }
} }

View File

@ -26,7 +26,6 @@ import path_provider_foundation
import screen_brightness_macos import screen_brightness_macos
import share_plus import share_plus
import shared_preferences_foundation import shared_preferences_foundation
import sqflite_darwin
import url_launcher_macos import url_launcher_macos
import video_compress import video_compress
import wakelock_plus import wakelock_plus
@ -53,7 +52,6 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
ScreenBrightnessMacosPlugin.register(with: registry.registrar(forPlugin: "ScreenBrightnessMacosPlugin")) ScreenBrightnessMacosPlugin.register(with: registry.registrar(forPlugin: "ScreenBrightnessMacosPlugin"))
SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin")) SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin"))
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
VideoCompressPlugin.register(with: registry.registrar(forPlugin: "VideoCompressPlugin")) VideoCompressPlugin.register(with: registry.registrar(forPlugin: "VideoCompressPlugin"))
WakelockPlusMacosPlugin.register(with: registry.registrar(forPlugin: "WakelockPlusMacosPlugin")) WakelockPlusMacosPlugin.register(with: registry.registrar(forPlugin: "WakelockPlusMacosPlugin"))

View File

@ -165,9 +165,6 @@ PODS:
- shared_preferences_foundation (0.0.1): - shared_preferences_foundation (0.0.1):
- Flutter - Flutter
- FlutterMacOS - FlutterMacOS
- sqflite_darwin (0.0.4):
- Flutter
- FlutterMacOS
- url_launcher_macos (0.0.1): - url_launcher_macos (0.0.1):
- FlutterMacOS - FlutterMacOS
- video_compress (0.3.0): - video_compress (0.3.0):
@ -201,7 +198,6 @@ DEPENDENCIES:
- screen_brightness_macos (from `Flutter/ephemeral/.symlinks/plugins/screen_brightness_macos/macos`) - screen_brightness_macos (from `Flutter/ephemeral/.symlinks/plugins/screen_brightness_macos/macos`)
- share_plus (from `Flutter/ephemeral/.symlinks/plugins/share_plus/macos`) - share_plus (from `Flutter/ephemeral/.symlinks/plugins/share_plus/macos`)
- shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin`) - shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin`)
- sqflite_darwin (from `Flutter/ephemeral/.symlinks/plugins/sqflite_darwin/darwin`)
- url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`) - url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`)
- video_compress (from `Flutter/ephemeral/.symlinks/plugins/video_compress/macos`) - video_compress (from `Flutter/ephemeral/.symlinks/plugins/video_compress/macos`)
- wakelock_plus (from `Flutter/ephemeral/.symlinks/plugins/wakelock_plus/macos`) - wakelock_plus (from `Flutter/ephemeral/.symlinks/plugins/wakelock_plus/macos`)
@ -271,8 +267,6 @@ EXTERNAL SOURCES:
:path: Flutter/ephemeral/.symlinks/plugins/share_plus/macos :path: Flutter/ephemeral/.symlinks/plugins/share_plus/macos
shared_preferences_foundation: shared_preferences_foundation:
:path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin :path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin
sqflite_darwin:
:path: Flutter/ephemeral/.symlinks/plugins/sqflite_darwin/darwin
url_launcher_macos: url_launcher_macos:
:path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos :path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos
video_compress: video_compress:
@ -317,7 +311,6 @@ SPEC CHECKSUMS:
screen_brightness_macos: 2d6d3af2165592d9a55ffcd95b7550970e41ebda screen_brightness_macos: 2d6d3af2165592d9a55ffcd95b7550970e41ebda
share_plus: 1fa619de8392a4398bfaf176d441853922614e89 share_plus: 1fa619de8392a4398bfaf176d441853922614e89
shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78 shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78
sqflite_darwin: 5a7236e3b501866c1c9befc6771dfd73ffb8702d
url_launcher_macos: c82c93949963e55b228a30115bd219499a6fe404 url_launcher_macos: c82c93949963e55b228a30115bd219499a6fe404
video_compress: c896234f100791b5fef7f049afa38f6d2ef7b42f video_compress: c896234f100791b5fef7f049afa38f6d2ef7b42f
wakelock_plus: 4783562c9a43d209c458cb9b30692134af456269 wakelock_plus: 4783562c9a43d209c458cb9b30692134af456269

View File

@ -182,30 +182,6 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "8.9.3" version: "8.9.3"
cached_network_image:
dependency: "direct main"
description:
name: cached_network_image
sha256: "7c1183e361e5c8b0a0f21a28401eecdbde252441106a9816400dd4c2b2424916"
url: "https://pub.dev"
source: hosted
version: "3.4.1"
cached_network_image_platform_interface:
dependency: transitive
description:
name: cached_network_image_platform_interface
sha256: "35814b016e37fbdc91f7ae18c8caf49ba5c88501813f73ce8a07027a395e2829"
url: "https://pub.dev"
source: hosted
version: "4.1.1"
cached_network_image_web:
dependency: transitive
description:
name: cached_network_image_web
sha256: "980842f4e8e2535b8dbd3d5ca0b1f0ba66bf61d14cc3a17a9b4788a3685ba062"
url: "https://pub.dev"
source: hosted
version: "1.3.1"
cassowary: cassowary:
dependency: transitive dependency: transitive
description: description:
@ -454,6 +430,22 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.7" version: "2.0.7"
extended_image:
dependency: "direct main"
description:
name: extended_image
sha256: "93890a88d89ce017789f6c031c32ad8d2c685f1a5c25c169550746d973ca5e44"
url: "https://pub.dev"
source: hosted
version: "9.0.9"
extended_image_library:
dependency: transitive
description:
name: extended_image_library
sha256: "9a94ec9314aa206cfa35f16145c3cd6e2c924badcc670eaaca8a3a8063a68cd7"
url: "https://pub.dev"
source: hosted
version: "4.0.5"
fading_edge_scrollview: fading_edge_scrollview:
dependency: transitive dependency: transitive
description: description:
@ -643,14 +635,6 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.2.2" version: "3.2.2"
flutter_cache_manager:
dependency: transitive
description:
name: flutter_cache_manager
sha256: "400b6592f16a4409a7f2bb929a9a7e38c72cceb8ffb99ee57bbf2cb2cecf8386"
url: "https://pub.dev"
source: hosted
version: "3.4.1"
flutter_colorpicker: flutter_colorpicker:
dependency: "direct main" dependency: "direct main"
description: description:
@ -890,6 +874,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.2.2" version: "1.2.2"
http_client_helper:
dependency: transitive
description:
name: http_client_helper
sha256: "8a9127650734da86b5c73760de2b404494c968a3fd55602045ffec789dac3cb1"
url: "https://pub.dev"
source: hosted
version: "3.0.0"
http_multi_server: http_multi_server:
dependency: transitive dependency: transitive
description: description:
@ -1250,14 +1242,6 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.5.0" version: "0.5.0"
octo_image:
dependency: transitive
description:
name: octo_image
sha256: "34faa6639a78c7e3cbe79be6f9f96535867e879748ade7d17c9b1ae7536293bd"
url: "https://pub.dev"
source: hosted
version: "2.1.0"
package_config: package_config:
dependency: transitive dependency: transitive
description: description:
@ -1546,14 +1530,6 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.5.1" version: "1.5.1"
rxdart:
dependency: transitive
description:
name: rxdart
sha256: "5c3004a4a8dbb94bd4bf5412a4def4acdaa12e12f269737a5751369e12d1a962"
url: "https://pub.dev"
source: hosted
version: "0.28.0"
safe_local_storage: safe_local_storage:
dependency: transitive dependency: transitive
description: description:
@ -1767,46 +1743,6 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "7.0.0" version: "7.0.0"
sqflite:
dependency: transitive
description:
name: sqflite
sha256: "2d7299468485dca85efeeadf5d38986909c5eb0cd71fd3db2c2f000e6c9454bb"
url: "https://pub.dev"
source: hosted
version: "2.4.1"
sqflite_android:
dependency: transitive
description:
name: sqflite_android
sha256: "78f489aab276260cdd26676d2169446c7ecd3484bbd5fead4ca14f3ed4dd9ee3"
url: "https://pub.dev"
source: hosted
version: "2.4.0"
sqflite_common:
dependency: transitive
description:
name: sqflite_common
sha256: "761b9740ecbd4d3e66b8916d784e581861fd3c3553eda85e167bc49fdb68f709"
url: "https://pub.dev"
source: hosted
version: "2.5.4+6"
sqflite_darwin:
dependency: transitive
description:
name: sqflite_darwin
sha256: "96a698e2bc82bd770a4d6aab00b42396a7c63d9e33513a56945cbccb594c2474"
url: "https://pub.dev"
source: hosted
version: "2.4.1"
sqflite_platform_interface:
dependency: transitive
description:
name: sqflite_platform_interface
sha256: "8dd4515c7bdcae0a785b0062859336de775e8c65db81ae33dd5445f35be61920"
url: "https://pub.dev"
source: hosted
version: "2.4.0"
stack_trace: stack_trace:
dependency: transitive dependency: transitive
description: description:

View File

@ -16,7 +16,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
# In Windows, build-name is used as the major, minor, and patch parts # In Windows, build-name is used as the major, minor, and patch parts
# of the product and file versions while build-number is used as the build suffix. # of the product and file versions while build-number is used as the build suffix.
version: 2.2.1+43 version: 2.2.1+42
environment: environment:
sdk: ^3.5.4 sdk: ^3.5.4
@ -115,7 +115,7 @@ dependencies:
flutter_webrtc: ^0.12.5+hotfix.1 flutter_webrtc: ^0.12.5+hotfix.1
slide_countdown: ^2.0.2 slide_countdown: ^2.0.2
video_compress: ^3.1.3 video_compress: ^3.1.3
cached_network_image: ^3.4.1 extended_image: ^9.0.9
dev_dependencies: dev_dependencies:
flutter_test: flutter_test: