✨ Post drafts
This commit is contained in:
parent
e16bc80eea
commit
857f3cc832
@ -769,5 +769,7 @@
|
|||||||
"decryptingKeyNotFound": "Key not found or exchange failed, the other party may not be online",
|
"decryptingKeyNotFound": "Key not found or exchange failed, the other party may not be online",
|
||||||
"messageUnablePreview": "Unable preview",
|
"messageUnablePreview": "Unable preview",
|
||||||
"messageUnablePreviewEncrypted": "Unable preview encrypted message",
|
"messageUnablePreviewEncrypted": "Unable preview encrypted message",
|
||||||
"postViewInGlobalDescription": "Do not view the post in the specific realm."
|
"postViewInGlobalDescription": "Do not view the post in the specific realm.",
|
||||||
|
"postDraftSaved": "The draft has been saved.",
|
||||||
|
"postDraftBox": "Draft Box"
|
||||||
}
|
}
|
||||||
|
@ -767,5 +767,7 @@
|
|||||||
"decryptingKeyNotFound": "未找到密钥对或交换失败,对方可能不在线",
|
"decryptingKeyNotFound": "未找到密钥对或交换失败,对方可能不在线",
|
||||||
"messageUnablePreview": "无法预览消息",
|
"messageUnablePreview": "无法预览消息",
|
||||||
"messageUnablePreviewEncrypted": "无法预览加密消息",
|
"messageUnablePreviewEncrypted": "无法预览加密消息",
|
||||||
"postViewInGlobalDescription": "不查看特定领域的帖子。"
|
"postViewInGlobalDescription": "不查看特定领域的帖子。",
|
||||||
|
"postDraftSaved": "已保存为草稿。",
|
||||||
|
"postDraftBox": "草稿箱"
|
||||||
}
|
}
|
||||||
|
@ -767,5 +767,7 @@
|
|||||||
"decryptingKeyNotFound": "未找到密鑰對或交換失敗,對方可能不在線",
|
"decryptingKeyNotFound": "未找到密鑰對或交換失敗,對方可能不在線",
|
||||||
"messageUnablePreview": "無法預覽消息",
|
"messageUnablePreview": "無法預覽消息",
|
||||||
"messageUnablePreviewEncrypted": "無法預覽加密消息",
|
"messageUnablePreviewEncrypted": "無法預覽加密消息",
|
||||||
"postViewInGlobalDescription": "不查看特定領域的帖子。"
|
"postViewInGlobalDescription": "不查看特定領域的帖子。",
|
||||||
|
"postDraftSaved": "已保存為草稿。",
|
||||||
|
"postDraftBox": "草稿箱"
|
||||||
}
|
}
|
||||||
|
@ -767,5 +767,7 @@
|
|||||||
"decryptingKeyNotFound": "未找到密鑰對或交換失敗,對方可能不在線",
|
"decryptingKeyNotFound": "未找到密鑰對或交換失敗,對方可能不在線",
|
||||||
"messageUnablePreview": "無法預覽消息",
|
"messageUnablePreview": "無法預覽消息",
|
||||||
"messageUnablePreviewEncrypted": "無法預覽加密消息",
|
"messageUnablePreviewEncrypted": "無法預覽加密消息",
|
||||||
"postViewInGlobalDescription": "不查看特定領域的帖子。"
|
"postViewInGlobalDescription": "不查看特定領域的帖子。",
|
||||||
|
"postDraftSaved": "已保存為草稿。",
|
||||||
|
"postDraftBox": "草稿箱"
|
||||||
}
|
}
|
||||||
|
@ -208,6 +208,7 @@ class PostWriteController extends ChangeNotifier {
|
|||||||
SnRealm? realm;
|
SnRealm? realm;
|
||||||
SnPublisher? publisher;
|
SnPublisher? publisher;
|
||||||
SnPost? editingPost, repostingPost, replyingPost;
|
SnPost? editingPost, repostingPost, replyingPost;
|
||||||
|
bool editingDraft = false;
|
||||||
|
|
||||||
int visibility = 0;
|
int visibility = 0;
|
||||||
List<int> visibleUsers = List.empty();
|
List<int> visibleUsers = List.empty();
|
||||||
@ -254,6 +255,8 @@ class PostWriteController extends ChangeNotifier {
|
|||||||
post.preload?.attachments?.map((ele) => PostWriteMedia(ele)) ?? []);
|
post.preload?.attachments?.map((ele) => PostWriteMedia(ele)) ?? []);
|
||||||
poll = post.preload?.poll;
|
poll = post.preload?.poll;
|
||||||
|
|
||||||
|
editingDraft = post.isDraft;
|
||||||
|
|
||||||
if (post.preload?.thumbnail != null &&
|
if (post.preload?.thumbnail != null &&
|
||||||
(post.preload?.thumbnail?.rid.isNotEmpty ?? false)) {
|
(post.preload?.thumbnail?.rid.isNotEmpty ?? false)) {
|
||||||
thumbnail = PostWriteMedia(post.preload!.thumbnail);
|
thumbnail = PostWriteMedia(post.preload!.thumbnail);
|
||||||
@ -474,7 +477,10 @@ class PostWriteController extends ChangeNotifier {
|
|||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> sendPost(BuildContext context) async {
|
Future<void> sendPost(
|
||||||
|
BuildContext context, {
|
||||||
|
bool saveAsDraft = false,
|
||||||
|
}) async {
|
||||||
if (isBusy || publisher == null) return;
|
if (isBusy || publisher == null) return;
|
||||||
|
|
||||||
final sn = context.read<SnNetworkProvider>();
|
final sn = context.read<SnNetworkProvider>();
|
||||||
@ -552,7 +558,7 @@ class PostWriteController extends ChangeNotifier {
|
|||||||
// Posting the content
|
// Posting the content
|
||||||
try {
|
try {
|
||||||
final baseProgressVal = progress!;
|
final baseProgressVal = progress!;
|
||||||
await sn.client.request(
|
final resp = await sn.client.request(
|
||||||
[
|
[
|
||||||
'/cgi/co/$mode',
|
'/cgi/co/$mode',
|
||||||
if (editingPost != null) '${editingPost!.id}',
|
if (editingPost != null) '${editingPost!.id}',
|
||||||
@ -585,6 +591,7 @@ class PostWriteController extends ChangeNotifier {
|
|||||||
if (videoAttachment != null) 'video': videoAttachment!.rid,
|
if (videoAttachment != null) 'video': videoAttachment!.rid,
|
||||||
if (poll != null) 'poll': poll!.id,
|
if (poll != null) 'poll': poll!.id,
|
||||||
if (realm != null) 'realm': realm!.id,
|
if (realm != null) 'realm': realm!.id,
|
||||||
|
'is_draft': saveAsDraft,
|
||||||
},
|
},
|
||||||
onSendProgress: (count, total) {
|
onSendProgress: (count, total) {
|
||||||
progress =
|
progress =
|
||||||
@ -601,7 +608,16 @@ class PostWriteController extends ChangeNotifier {
|
|||||||
method: editingPost != null ? 'PUT' : 'POST',
|
method: editingPost != null ? 'PUT' : 'POST',
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
reset();
|
if (saveAsDraft) {
|
||||||
|
if (!context.mounted) return;
|
||||||
|
editingDraft = true;
|
||||||
|
final out = SnPost.fromJson(resp.data);
|
||||||
|
final pt = context.read<SnPostContentProvider>();
|
||||||
|
editingPost = await pt.completePostData(out);
|
||||||
|
notifyListeners();
|
||||||
|
} else {
|
||||||
|
reset();
|
||||||
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (!context.mounted) return;
|
if (!context.mounted) return;
|
||||||
context.showErrorDialog(err);
|
context.showErrorDialog(err);
|
||||||
|
@ -60,16 +60,24 @@ class SnPostContentProvider {
|
|||||||
|
|
||||||
out[i] = out[i].copyWith(
|
out[i] = out[i].copyWith(
|
||||||
preload: SnPostPreload(
|
preload: SnPostPreload(
|
||||||
thumbnail: attachments.where((ele) => ele?.rid == out[i].body['thumbnail']).firstOrNull,
|
thumbnail: attachments
|
||||||
attachments: attachments.where((ele) => out[i].body['attachments']?.contains(ele?.rid) ?? false).toList(),
|
.where((ele) => ele?.rid == out[i].body['thumbnail'])
|
||||||
video: attachments.where((ele) => ele?.rid == out[i].body['video']).firstOrNull,
|
.firstOrNull,
|
||||||
|
attachments: attachments
|
||||||
|
.where((ele) =>
|
||||||
|
out[i].body['attachments']?.contains(ele?.rid) ?? false)
|
||||||
|
.toList(),
|
||||||
|
video: attachments
|
||||||
|
.where((ele) => ele?.rid == out[i].body['video'])
|
||||||
|
.firstOrNull,
|
||||||
poll: poll,
|
poll: poll,
|
||||||
realm: realm,
|
realm: realm,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
uids.addAll(attachments.where((ele) => ele != null).map((ele) => ele!.accountId));
|
uids.addAll(
|
||||||
|
attachments.where((ele) => ele != null).map((ele) => ele!.accountId));
|
||||||
await _ud.listAccount(uids);
|
await _ud.listAccount(uids);
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
@ -107,15 +115,23 @@ class SnPostContentProvider {
|
|||||||
|
|
||||||
out = out.copyWith(
|
out = out.copyWith(
|
||||||
preload: SnPostPreload(
|
preload: SnPostPreload(
|
||||||
thumbnail: attachments.where((ele) => ele?.rid == out.body['thumbnail']).firstOrNull,
|
thumbnail: attachments
|
||||||
attachments: attachments.where((ele) => out.body['attachments']?.contains(ele?.rid) ?? false).toList(),
|
.where((ele) => ele?.rid == out.body['thumbnail'])
|
||||||
video: attachments.where((ele) => ele?.rid == out.body['video']).firstOrNull,
|
.firstOrNull,
|
||||||
|
attachments: attachments
|
||||||
|
.where(
|
||||||
|
(ele) => out.body['attachments']?.contains(ele?.rid) ?? false)
|
||||||
|
.toList(),
|
||||||
|
video: attachments
|
||||||
|
.where((ele) => ele?.rid == out.body['video'])
|
||||||
|
.firstOrNull,
|
||||||
poll: poll,
|
poll: poll,
|
||||||
realm: realm,
|
realm: realm,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
uids.addAll(attachments.where((ele) => ele != null).map((ele) => ele!.accountId));
|
uids.addAll(
|
||||||
|
attachments.where((ele) => ele != null).map((ele) => ele!.accountId));
|
||||||
await _ud.listAccount(uids);
|
await _ud.listAccount(uids);
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
@ -138,17 +154,22 @@ class SnPostContentProvider {
|
|||||||
Iterable<String>? tags,
|
Iterable<String>? tags,
|
||||||
String? realm,
|
String? realm,
|
||||||
String? channel,
|
String? channel,
|
||||||
|
bool isDraft = false,
|
||||||
}) async {
|
}) async {
|
||||||
final resp = await _sn.client.get('/cgi/co/posts', queryParameters: {
|
final resp = await _sn.client.get(
|
||||||
'take': take,
|
'/cgi/co/posts${isDraft ? '/drafts' : ''}',
|
||||||
'offset': offset,
|
queryParameters: {
|
||||||
if (type != null) 'type': type,
|
'take': take,
|
||||||
if (author != null) 'author': author,
|
'offset': offset,
|
||||||
if (tags?.isNotEmpty ?? false) 'tags': tags!.join(','),
|
if (type != null) 'type': type,
|
||||||
if (categories?.isNotEmpty ?? false) 'categories': categories!.join(','),
|
if (author != null) 'author': author,
|
||||||
if (realm != null) 'realm': realm,
|
if (tags?.isNotEmpty ?? false) 'tags': tags!.join(','),
|
||||||
if (channel != null) 'channel': channel,
|
if (categories?.isNotEmpty ?? false)
|
||||||
});
|
'categories': categories!.join(','),
|
||||||
|
if (realm != null) 'realm': realm,
|
||||||
|
if (channel != null) 'channel': channel,
|
||||||
|
},
|
||||||
|
);
|
||||||
final List<SnPost> out = await _preloadRelatedDataInBatch(
|
final List<SnPost> out = await _preloadRelatedDataInBatch(
|
||||||
List.from(resp.data['data']?.map((e) => SnPost.fromJson(e)) ?? []),
|
List.from(resp.data['data']?.map((e) => SnPost.fromJson(e)) ?? []),
|
||||||
);
|
);
|
||||||
@ -161,7 +182,8 @@ class SnPostContentProvider {
|
|||||||
int take = 10,
|
int take = 10,
|
||||||
int offset = 0,
|
int offset = 0,
|
||||||
}) async {
|
}) async {
|
||||||
final resp = await _sn.client.get('/cgi/co/posts/$parentId/replies', queryParameters: {
|
final resp = await _sn.client
|
||||||
|
.get('/cgi/co/posts/$parentId/replies', queryParameters: {
|
||||||
'take': take,
|
'take': take,
|
||||||
'offset': offset,
|
'offset': offset,
|
||||||
});
|
});
|
||||||
@ -200,4 +222,9 @@ class SnPostContentProvider {
|
|||||||
);
|
);
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<SnPost> completePostData(SnPost post) async {
|
||||||
|
final out = await _preloadRelatedDataSingle(post);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,7 @@ import 'package:surface/screens/news/news_detail.dart';
|
|||||||
import 'package:surface/screens/news/news_list.dart';
|
import 'package:surface/screens/news/news_list.dart';
|
||||||
import 'package:surface/screens/notification.dart';
|
import 'package:surface/screens/notification.dart';
|
||||||
import 'package:surface/screens/post/post_detail.dart';
|
import 'package:surface/screens/post/post_detail.dart';
|
||||||
|
import 'package:surface/screens/post/post_draft.dart';
|
||||||
import 'package:surface/screens/post/post_editor.dart';
|
import 'package:surface/screens/post/post_editor.dart';
|
||||||
import 'package:surface/screens/post/publisher_page.dart';
|
import 'package:surface/screens/post/publisher_page.dart';
|
||||||
import 'package:surface/screens/post/post_search.dart';
|
import 'package:surface/screens/post/post_search.dart';
|
||||||
@ -65,6 +66,11 @@ final _appRoutes = [
|
|||||||
name: 'explore',
|
name: 'explore',
|
||||||
builder: (context, state) => const ExploreScreen(),
|
builder: (context, state) => const ExploreScreen(),
|
||||||
routes: [
|
routes: [
|
||||||
|
GoRoute(
|
||||||
|
path: '/draft',
|
||||||
|
name: 'postDraftBox',
|
||||||
|
builder: (context, state) => const PostDraftBox(),
|
||||||
|
),
|
||||||
GoRoute(
|
GoRoute(
|
||||||
path: '/write',
|
path: '/write',
|
||||||
name: 'postEditor',
|
name: 'postEditor',
|
||||||
|
@ -192,6 +192,21 @@ class _ExploreScreenState extends State<ExploreScreen>
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Text('postDraftBox').tr(),
|
||||||
|
const Gap(20),
|
||||||
|
FloatingActionButton(
|
||||||
|
heroTag: null,
|
||||||
|
tooltip: 'postDraftBox'.tr(),
|
||||||
|
onPressed: () {
|
||||||
|
GoRouter.of(context).pushNamed('postDraftBox');
|
||||||
|
_fabKey.currentState!.toggle();
|
||||||
|
},
|
||||||
|
child: const Icon(Symbols.box_edit),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
body: NestedScrollView(
|
body: NestedScrollView(
|
||||||
@ -293,9 +308,11 @@ class _ExploreScreenState extends State<ExploreScreen>
|
|||||||
.tr()
|
.tr()
|
||||||
: category.name,
|
: category.name,
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
).textColor(Theme.of(context)
|
).textColor(
|
||||||
.appBarTheme
|
Theme.of(context)
|
||||||
.foregroundColor!),
|
.appBarTheme
|
||||||
|
.foregroundColor!,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@ -321,9 +338,11 @@ class _ExploreScreenState extends State<ExploreScreen>
|
|||||||
child: Text(
|
child: Text(
|
||||||
'postChannel$channel',
|
'postChannel$channel',
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
).tr().textColor(Theme.of(context)
|
).tr().textColor(
|
||||||
.appBarTheme
|
Theme.of(context)
|
||||||
.foregroundColor),
|
.appBarTheme
|
||||||
|
.foregroundColor,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
88
lib/screens/post/post_draft.dart
Normal file
88
lib/screens/post/post_draft.dart
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
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/providers/post.dart';
|
||||||
|
import 'package:surface/types/post.dart';
|
||||||
|
import 'package:surface/widgets/dialog.dart';
|
||||||
|
import 'package:surface/widgets/loading_indicator.dart';
|
||||||
|
import 'package:surface/widgets/navigation/app_scaffold.dart';
|
||||||
|
import 'package:surface/widgets/post/post_item.dart';
|
||||||
|
import 'package:very_good_infinite_list/very_good_infinite_list.dart';
|
||||||
|
|
||||||
|
class PostDraftBox extends StatefulWidget {
|
||||||
|
const PostDraftBox({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<PostDraftBox> createState() => _PostDraftBoxState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _PostDraftBoxState extends State<PostDraftBox> {
|
||||||
|
bool _isBusy = false;
|
||||||
|
final List<SnPost> _posts = List.empty(growable: true);
|
||||||
|
int? _totalCount;
|
||||||
|
|
||||||
|
Future<void> _fetchPosts() async {
|
||||||
|
setState(() => _isBusy = true);
|
||||||
|
try {
|
||||||
|
final pt = context.read<SnPostContentProvider>();
|
||||||
|
final resp = await pt.listPosts(
|
||||||
|
take: 10,
|
||||||
|
offset: _posts.length,
|
||||||
|
isDraft: true,
|
||||||
|
);
|
||||||
|
final out = resp.$1;
|
||||||
|
_totalCount = resp.$2;
|
||||||
|
if (!mounted) return;
|
||||||
|
_posts.addAll(out);
|
||||||
|
} catch (err) {
|
||||||
|
if (!mounted) return;
|
||||||
|
context.showErrorDialog(err);
|
||||||
|
} finally {
|
||||||
|
setState(() => _isBusy = false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return AppScaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: Text('postDraftBox').tr(),
|
||||||
|
),
|
||||||
|
body: Column(
|
||||||
|
children: [
|
||||||
|
LoadingIndicator(isActive: _isBusy),
|
||||||
|
Expanded(
|
||||||
|
child: RefreshIndicator(
|
||||||
|
onRefresh: () {
|
||||||
|
_posts.clear();
|
||||||
|
return _fetchPosts();
|
||||||
|
},
|
||||||
|
child: InfiniteList(
|
||||||
|
padding: EdgeInsets.only(top: 8),
|
||||||
|
hasReachedMax:
|
||||||
|
_totalCount != null && _posts.length >= _totalCount!,
|
||||||
|
itemCount: _posts.length,
|
||||||
|
onFetchData: () => _fetchPosts(),
|
||||||
|
itemBuilder: (context, idx) {
|
||||||
|
final ele = _posts[idx];
|
||||||
|
return OpenablePostItem(
|
||||||
|
data: ele,
|
||||||
|
onChanged: (data) {
|
||||||
|
_posts[idx] = data;
|
||||||
|
},
|
||||||
|
onDeleted: () {
|
||||||
|
_posts.clear();
|
||||||
|
_fetchPosts();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
separatorBuilder: (_, __) => const Gap(8),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -138,6 +138,15 @@ class _PostEditorScreenState extends State<PostEditorScreen>
|
|||||||
],
|
],
|
||||||
scope: HotKeyScope.inapp,
|
scope: HotKeyScope.inapp,
|
||||||
);
|
);
|
||||||
|
final HotKey _saveDraftHotKey = HotKey(
|
||||||
|
key: PhysicalKeyboardKey.keyS,
|
||||||
|
modifiers: [
|
||||||
|
(!kIsWeb && Platform.isMacOS)
|
||||||
|
? HotKeyModifier.meta
|
||||||
|
: HotKeyModifier.control
|
||||||
|
],
|
||||||
|
scope: HotKeyScope.inapp,
|
||||||
|
);
|
||||||
|
|
||||||
void _registerHotKey() {
|
void _registerHotKey() {
|
||||||
if (kIsWeb || Platform.isAndroid || Platform.isIOS) return;
|
if (kIsWeb || Platform.isAndroid || Platform.isIOS) return;
|
||||||
@ -153,6 +162,11 @@ class _PostEditorScreenState extends State<PostEditorScreen>
|
|||||||
]);
|
]);
|
||||||
setState(() {});
|
setState(() {});
|
||||||
});
|
});
|
||||||
|
hotKeyManager.register(_saveDraftHotKey, keyDownHandler: (_) async {
|
||||||
|
if (mounted) {
|
||||||
|
_writeController.sendPost(context);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void _showPublisherPopup() {
|
void _showPublisherPopup() {
|
||||||
@ -218,6 +232,7 @@ class _PostEditorScreenState extends State<PostEditorScreen>
|
|||||||
_writeController.dispose();
|
_writeController.dispose();
|
||||||
if (!kIsWeb && !(Platform.isAndroid || Platform.isIOS)) {
|
if (!kIsWeb && !(Platform.isAndroid || Platform.isIOS)) {
|
||||||
hotKeyManager.unregister(_pasteHotKey);
|
hotKeyManager.unregister(_pasteHotKey);
|
||||||
|
hotKeyManager.unregister(_saveDraftHotKey);
|
||||||
}
|
}
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
@ -269,6 +284,20 @@ class _PostEditorScreenState extends State<PostEditorScreen>
|
|||||||
: 'untitled'.tr(),
|
: 'untitled'.tr(),
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
|
IconButton(
|
||||||
|
icon: _writeController.editingDraft
|
||||||
|
? const Icon(Icons.save)
|
||||||
|
: const Icon(Symbols.save_as),
|
||||||
|
onPressed: () {
|
||||||
|
_writeController.sendPost(context, saveAsDraft: true).then(
|
||||||
|
(_) {
|
||||||
|
if (!context.mounted) return;
|
||||||
|
context.showSnackbar('postDraftSaved'.tr());
|
||||||
|
HapticFeedback.mediumImpact();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: const Icon(Symbols.tune),
|
icon: const Icon(Symbols.tune),
|
||||||
onPressed: _writeController.isBusy ? null : _updateMeta,
|
onPressed: _writeController.isBusy ? null : _updateMeta,
|
||||||
@ -296,7 +325,8 @@ class _PostEditorScreenState extends State<PostEditorScreen>
|
|||||||
),
|
),
|
||||||
body: Column(
|
body: Column(
|
||||||
children: [
|
children: [
|
||||||
if (_writeController.editingPost != null)
|
if (_writeController.editingPost != null &&
|
||||||
|
!_writeController.editingDraft)
|
||||||
Container(
|
Container(
|
||||||
padding: const EdgeInsets.only(
|
padding: const EdgeInsets.only(
|
||||||
top: 4, bottom: 4, left: 20, right: 20),
|
top: 4, bottom: 4, left: 20, right: 20),
|
||||||
|
@ -223,7 +223,7 @@ class PostItem extends StatelessWidget {
|
|||||||
onShareImage: () => _doShareViaPicture(context),
|
onShareImage: () => _doShareViaPicture(context),
|
||||||
onSelectAnswer: onSelectAnswer,
|
onSelectAnswer: onSelectAnswer,
|
||||||
onDeleted: () {
|
onDeleted: () {
|
||||||
if (onDeleted != null) {}
|
onDeleted?.call();
|
||||||
},
|
},
|
||||||
).padding(bottom: 8),
|
).padding(bottom: 8),
|
||||||
if (data.preload?.video != null)
|
if (data.preload?.video != null)
|
||||||
@ -272,7 +272,7 @@ class PostItem extends StatelessWidget {
|
|||||||
onShareImage: () => _doShareViaPicture(context),
|
onShareImage: () => _doShareViaPicture(context),
|
||||||
onSelectAnswer: onSelectAnswer,
|
onSelectAnswer: onSelectAnswer,
|
||||||
onDeleted: () {
|
onDeleted: () {
|
||||||
if (onDeleted != null) {}
|
onDeleted?.call();
|
||||||
},
|
},
|
||||||
).padding(horizontal: 12, top: 8, bottom: 8),
|
).padding(horizontal: 12, top: 8, bottom: 8),
|
||||||
if (data.preload?.video != null)
|
if (data.preload?.video != null)
|
||||||
@ -363,7 +363,7 @@ class PostItem extends StatelessWidget {
|
|||||||
onShareImage: () => _doShareViaPicture(context),
|
onShareImage: () => _doShareViaPicture(context),
|
||||||
onSelectAnswer: onSelectAnswer,
|
onSelectAnswer: onSelectAnswer,
|
||||||
onDeleted: () {
|
onDeleted: () {
|
||||||
if (onDeleted != null) onDeleted!();
|
onDeleted?.call();
|
||||||
},
|
},
|
||||||
).padding(horizontal: 12, vertical: 8),
|
).padding(horizontal: 12, vertical: 8),
|
||||||
if (data.preload?.video != null)
|
if (data.preload?.video != null)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user