✨ Post with publish at and until
This commit is contained in:
parent
7655dfdf37
commit
c41a71388d
@ -7,6 +7,7 @@ import 'package:solian/models/post.dart';
|
|||||||
import 'package:solian/models/realm.dart';
|
import 'package:solian/models/realm.dart';
|
||||||
import 'package:solian/widgets/attachments/attachment_editor.dart';
|
import 'package:solian/widgets/attachments/attachment_editor.dart';
|
||||||
import 'package:solian/widgets/posts/editor/post_editor_categories_tags.dart';
|
import 'package:solian/widgets/posts/editor/post_editor_categories_tags.dart';
|
||||||
|
import 'package:solian/widgets/posts/editor/post_editor_date.dart';
|
||||||
import 'package:solian/widgets/posts/editor/post_editor_overview.dart';
|
import 'package:solian/widgets/posts/editor/post_editor_overview.dart';
|
||||||
import 'package:solian/widgets/posts/editor/post_editor_publish_zone.dart';
|
import 'package:solian/widgets/posts/editor/post_editor_publish_zone.dart';
|
||||||
import 'package:solian/widgets/posts/editor/post_editor_visibility.dart';
|
import 'package:solian/widgets/posts/editor/post_editor_visibility.dart';
|
||||||
@ -26,6 +27,8 @@ class PostEditorController extends GetxController {
|
|||||||
Rx<Post?> replyTo = Rx(null);
|
Rx<Post?> replyTo = Rx(null);
|
||||||
Rx<Post?> repostTo = Rx(null);
|
Rx<Post?> repostTo = Rx(null);
|
||||||
Rx<Realm?> realmZone = Rx(null);
|
Rx<Realm?> realmZone = Rx(null);
|
||||||
|
Rx<DateTime?> publishedAt = Rx(null);
|
||||||
|
Rx<DateTime?> publishedUntil = Rx(null);
|
||||||
RxList<int> attachments = RxList<int>.empty(growable: true);
|
RxList<int> attachments = RxList<int>.empty(growable: true);
|
||||||
RxList<String> tags = RxList<String>.empty(growable: true);
|
RxList<String> tags = RxList<String>.empty(growable: true);
|
||||||
|
|
||||||
@ -98,6 +101,15 @@ class PostEditorController extends GetxController {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> editPublishDate(BuildContext context) {
|
||||||
|
return showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => PostEditorDateDialog(
|
||||||
|
controller: this,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> editAttachment(BuildContext context) {
|
Future<void> editAttachment(BuildContext context) {
|
||||||
return showModalBottomSheet(
|
return showModalBottomSheet(
|
||||||
context: context,
|
context: context,
|
||||||
@ -173,6 +185,8 @@ class PostEditorController extends GetxController {
|
|||||||
titleController.text = value.body['title'] ?? '';
|
titleController.text = value.body['title'] ?? '';
|
||||||
descriptionController.text = value.body['description'] ?? '';
|
descriptionController.text = value.body['description'] ?? '';
|
||||||
contentController.text = value.body['content'] ?? '';
|
contentController.text = value.body['content'] ?? '';
|
||||||
|
publishedAt.value = value.publishedAt;
|
||||||
|
publishedUntil.value = value.publishedUntil;
|
||||||
tags.value =
|
tags.value =
|
||||||
value.body['tags']?.map((x) => x['alias']).toList() ?? List.empty();
|
value.body['tags']?.map((x) => x['alias']).toList() ?? List.empty();
|
||||||
tags.refresh();
|
tags.refresh();
|
||||||
@ -233,6 +247,9 @@ class PostEditorController extends GetxController {
|
|||||||
'visible_users': visibleUsers,
|
'visible_users': visibleUsers,
|
||||||
'invisible_users': invisibleUsers,
|
'invisible_users': invisibleUsers,
|
||||||
'visibility': visibility.value,
|
'visibility': visibility.value,
|
||||||
|
'published_at': publishedAt.value?.toUtc().toIso8601String() ??
|
||||||
|
DateTime.now().toUtc().toIso8601String(),
|
||||||
|
'published_until': publishedUntil.value?.toUtc().toIso8601String(),
|
||||||
'is_draft': isDraft.value,
|
'is_draft': isDraft.value,
|
||||||
if (replyTo.value != null) 'reply_to': replyTo.value!.id,
|
if (replyTo.value != null) 'reply_to': replyTo.value!.id,
|
||||||
if (repostTo.value != null) 'repost_to': repostTo.value!.id,
|
if (repostTo.value != null) 'repost_to': repostTo.value!.id,
|
||||||
@ -256,6 +273,12 @@ class PostEditorController extends GetxController {
|
|||||||
if (value['invisible_users'] != null) {
|
if (value['invisible_users'] != null) {
|
||||||
invisibleUsers.value = value['invisible_users'].cast<int>();
|
invisibleUsers.value = value['invisible_users'].cast<int>();
|
||||||
}
|
}
|
||||||
|
if (value['published_at'] != null) {
|
||||||
|
publishedAt.value = DateTime.parse(value['published_at']).toLocal();
|
||||||
|
}
|
||||||
|
if (value['published_until'] != null) {
|
||||||
|
publishedAt.value = DateTime.parse(value['published_until']).toLocal();
|
||||||
|
}
|
||||||
if (value['reply_to'] != null) {
|
if (value['reply_to'] != null) {
|
||||||
replyTo.value = Post.fromJson(value['reply_to']);
|
replyTo.value = Post.fromJson(value['reply_to']);
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@ class Post {
|
|||||||
Post? repostTo;
|
Post? repostTo;
|
||||||
Realm? realm;
|
Realm? realm;
|
||||||
DateTime? publishedAt;
|
DateTime? publishedAt;
|
||||||
|
DateTime? publishedUntil;
|
||||||
DateTime? pinnedAt;
|
DateTime? pinnedAt;
|
||||||
bool? isDraft;
|
bool? isDraft;
|
||||||
int authorId;
|
int authorId;
|
||||||
@ -44,6 +45,7 @@ class Post {
|
|||||||
required this.repostTo,
|
required this.repostTo,
|
||||||
required this.realm,
|
required this.realm,
|
||||||
required this.publishedAt,
|
required this.publishedAt,
|
||||||
|
required this.publishedUntil,
|
||||||
required this.pinnedAt,
|
required this.pinnedAt,
|
||||||
required this.isDraft,
|
required this.isDraft,
|
||||||
required this.authorId,
|
required this.authorId,
|
||||||
@ -80,6 +82,9 @@ class Post {
|
|||||||
publishedAt: json['published_at'] != null
|
publishedAt: json['published_at'] != null
|
||||||
? DateTime.parse(json['published_at'])
|
? DateTime.parse(json['published_at'])
|
||||||
: null,
|
: null,
|
||||||
|
publishedUntil: json['published_until'] != null
|
||||||
|
? DateTime.parse(json['published_until'])
|
||||||
|
: null,
|
||||||
pinnedAt: json['pinned_at'] != null
|
pinnedAt: json['pinned_at'] != null
|
||||||
? DateTime.parse(json['pinned_at'])
|
? DateTime.parse(json['pinned_at'])
|
||||||
: null,
|
: null,
|
||||||
@ -108,6 +113,7 @@ class Post {
|
|||||||
'repost_to': repostTo?.toJson(),
|
'repost_to': repostTo?.toJson(),
|
||||||
'realm': realm?.toJson(),
|
'realm': realm?.toJson(),
|
||||||
'published_at': publishedAt?.toIso8601String(),
|
'published_at': publishedAt?.toIso8601String(),
|
||||||
|
'published_until': publishedUntil?.toIso8601String(),
|
||||||
'pinned_at': pinnedAt?.toIso8601String(),
|
'pinned_at': pinnedAt?.toIso8601String(),
|
||||||
'is_draft': isDraft,
|
'is_draft': isDraft,
|
||||||
'author_id': authorId,
|
'author_id': authorId,
|
||||||
|
@ -34,7 +34,7 @@ class _PersonalizeScreenState extends State<PersonalizeScreen> {
|
|||||||
|
|
||||||
bool _isBusy = false;
|
bool _isBusy = false;
|
||||||
|
|
||||||
void selectBirthday() async {
|
void _selectBirthday() async {
|
||||||
final DateTime? picked = await showDatePicker(
|
final DateTime? picked = await showDatePicker(
|
||||||
context: context,
|
context: context,
|
||||||
initialDate: _birthday?.toLocal(),
|
initialDate: _birthday?.toLocal(),
|
||||||
@ -49,7 +49,7 @@ class _PersonalizeScreenState extends State<PersonalizeScreen> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void syncWidget() async {
|
void _syncWidget() async {
|
||||||
setState(() => _isBusy = true);
|
setState(() => _isBusy = true);
|
||||||
|
|
||||||
final AuthProvider auth = Get.find();
|
final AuthProvider auth = Get.find();
|
||||||
@ -72,7 +72,7 @@ class _PersonalizeScreenState extends State<PersonalizeScreen> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> updateImage(String position) async {
|
Future<void> _editImage(String position) async {
|
||||||
final AuthProvider auth = Get.find();
|
final AuthProvider auth = Get.find();
|
||||||
if (auth.isAuthorized.isFalse) return;
|
if (auth.isAuthorized.isFalse) return;
|
||||||
|
|
||||||
@ -87,11 +87,7 @@ class _PersonalizeScreenState extends State<PersonalizeScreen> {
|
|||||||
try {
|
try {
|
||||||
final file = File(image.path);
|
final file = File(image.path);
|
||||||
attachResp = await provider.createAttachment(
|
attachResp = await provider.createAttachment(
|
||||||
await file.readAsBytes(),
|
await file.readAsBytes(), file.path, 'p.$position', null);
|
||||||
file.path,
|
|
||||||
'p.$position',
|
|
||||||
null
|
|
||||||
);
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
setState(() => _isBusy = false);
|
setState(() => _isBusy = false);
|
||||||
context.showErrorDialog(e);
|
context.showErrorDialog(e);
|
||||||
@ -105,7 +101,7 @@ class _PersonalizeScreenState extends State<PersonalizeScreen> {
|
|||||||
{'attachment': attachResp.body['id']},
|
{'attachment': attachResp.body['id']},
|
||||||
);
|
);
|
||||||
if (resp.statusCode == 200) {
|
if (resp.statusCode == 200) {
|
||||||
syncWidget();
|
_syncWidget();
|
||||||
context.showSnackbar('accountPersonalizeApplied'.tr);
|
context.showSnackbar('accountPersonalizeApplied'.tr);
|
||||||
} else {
|
} else {
|
||||||
context.showErrorDialog(resp.bodyString);
|
context.showErrorDialog(resp.bodyString);
|
||||||
@ -114,7 +110,7 @@ class _PersonalizeScreenState extends State<PersonalizeScreen> {
|
|||||||
setState(() => _isBusy = false);
|
setState(() => _isBusy = false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void updatePersonalize() async {
|
void _editUserInfo() async {
|
||||||
final AuthProvider auth = Get.find();
|
final AuthProvider auth = Get.find();
|
||||||
if (auth.isAuthorized.isFalse) return;
|
if (auth.isAuthorized.isFalse) return;
|
||||||
|
|
||||||
@ -134,7 +130,7 @@ class _PersonalizeScreenState extends State<PersonalizeScreen> {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
if (resp.statusCode == 200) {
|
if (resp.statusCode == 200) {
|
||||||
syncWidget();
|
_syncWidget();
|
||||||
context.showSnackbar('accountPersonalizeApplied'.tr);
|
context.showSnackbar('accountPersonalizeApplied'.tr);
|
||||||
} else {
|
} else {
|
||||||
context.showErrorDialog(resp.bodyString);
|
context.showErrorDialog(resp.bodyString);
|
||||||
@ -147,7 +143,7 @@ class _PersonalizeScreenState extends State<PersonalizeScreen> {
|
|||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
|
||||||
Future.delayed(Duration.zero, () => syncWidget());
|
Future.delayed(Duration.zero, () => _syncWidget());
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -168,7 +164,7 @@ class _PersonalizeScreenState extends State<PersonalizeScreen> {
|
|||||||
left: 40,
|
left: 40,
|
||||||
child: FloatingActionButton.small(
|
child: FloatingActionButton.small(
|
||||||
heroTag: const Key('avatar-editor'),
|
heroTag: const Key('avatar-editor'),
|
||||||
onPressed: () => updateImage('avatar'),
|
onPressed: () => _editImage('avatar'),
|
||||||
child: const Icon(
|
child: const Icon(
|
||||||
Icons.camera,
|
Icons.camera,
|
||||||
),
|
),
|
||||||
@ -187,7 +183,8 @@ class _PersonalizeScreenState extends State<PersonalizeScreen> {
|
|||||||
color: Theme.of(context).colorScheme.surfaceContainerHigh,
|
color: Theme.of(context).colorScheme.surfaceContainerHigh,
|
||||||
child: _banner != null
|
child: _banner != null
|
||||||
? Image.network(
|
? Image.network(
|
||||||
ServiceFinder.buildUrl('files', '/attachments/$_banner'),
|
ServiceFinder.buildUrl(
|
||||||
|
'files', '/attachments/$_banner'),
|
||||||
fit: BoxFit.cover,
|
fit: BoxFit.cover,
|
||||||
loadingBuilder: (BuildContext context, Widget child,
|
loadingBuilder: (BuildContext context, Widget child,
|
||||||
ImageChunkEvent? loadingProgress) {
|
ImageChunkEvent? loadingProgress) {
|
||||||
@ -212,7 +209,7 @@ class _PersonalizeScreenState extends State<PersonalizeScreen> {
|
|||||||
right: 16,
|
right: 16,
|
||||||
child: FloatingActionButton(
|
child: FloatingActionButton(
|
||||||
heroTag: const Key('banner-editor'),
|
heroTag: const Key('banner-editor'),
|
||||||
onPressed: () => updateImage('banner'),
|
onPressed: () => _editImage('banner'),
|
||||||
child: const Icon(
|
child: const Icon(
|
||||||
Icons.camera_alt,
|
Icons.camera_alt,
|
||||||
),
|
),
|
||||||
@ -293,18 +290,18 @@ class _PersonalizeScreenState extends State<PersonalizeScreen> {
|
|||||||
border: const OutlineInputBorder(),
|
border: const OutlineInputBorder(),
|
||||||
labelText: 'birthday'.tr,
|
labelText: 'birthday'.tr,
|
||||||
),
|
),
|
||||||
onTap: () => selectBirthday(),
|
onTap: () => _selectBirthday(),
|
||||||
).paddingSymmetric(horizontal: padding),
|
).paddingSymmetric(horizontal: padding),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
children: [
|
children: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: _isBusy ? null : () => syncWidget(),
|
onPressed: _isBusy ? null : () => _syncWidget(),
|
||||||
child: Text('reset'.tr),
|
child: Text('reset'.tr),
|
||||||
),
|
),
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
onPressed: _isBusy ? null : () => updatePersonalize(),
|
onPressed: _isBusy ? null : () => _editUserInfo(),
|
||||||
child: Text('apply'.tr),
|
child: Text('apply'.tr),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@ -82,7 +82,7 @@ class _PostPublishScreenState extends State<PostPublishScreen> {
|
|||||||
setState(() => _isBusy = false);
|
setState(() => _isBusy = false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void syncWidget() {
|
void _syncWidget() {
|
||||||
_editorController.mode.value = widget.mode;
|
_editorController.mode.value = widget.mode;
|
||||||
if (widget.edit != null) {
|
if (widget.edit != null) {
|
||||||
_editorController.editTarget = widget.edit;
|
_editorController.editTarget = widget.edit;
|
||||||
@ -105,7 +105,7 @@ class _PostPublishScreenState extends State<PostPublishScreen> {
|
|||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
_editorController.contentController.addListener(() => setState(() {}));
|
_editorController.contentController.addListener(() => setState(() {}));
|
||||||
syncWidget();
|
_syncWidget();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -418,6 +418,25 @@ class _PostPublishScreenState extends State<PostPublishScreen> {
|
|||||||
_editorController.editPublishZone(context);
|
_editorController.editPublishZone(context);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
IconButton(
|
||||||
|
icon: Obx(() {
|
||||||
|
return badges.Badge(
|
||||||
|
showBadge:
|
||||||
|
_editorController.publishedAt.value != null ||
|
||||||
|
_editorController.publishedUntil.value !=
|
||||||
|
null,
|
||||||
|
position: badges.BadgePosition.topEnd(
|
||||||
|
top: -4,
|
||||||
|
end: -6,
|
||||||
|
),
|
||||||
|
child: const Icon(Icons.schedule),
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
color: Theme.of(context).colorScheme.primary,
|
||||||
|
onPressed: () {
|
||||||
|
_editorController.editPublishDate(context);
|
||||||
|
},
|
||||||
|
),
|
||||||
MarkdownToolbar(
|
MarkdownToolbar(
|
||||||
hideImage: true,
|
hideImage: true,
|
||||||
useIncludedTextField: false,
|
useIncludedTextField: false,
|
||||||
|
@ -101,6 +101,9 @@ const i18nEnglish = {
|
|||||||
'postRestoreFromLocal': 'Restore from local',
|
'postRestoreFromLocal': 'Restore from local',
|
||||||
'postAutoSaveAt': 'Auto saved at @date',
|
'postAutoSaveAt': 'Auto saved at @date',
|
||||||
'postCategoriesAndTags': 'Categories n\' Tags',
|
'postCategoriesAndTags': 'Categories n\' Tags',
|
||||||
|
'postPublishDate': 'Publish Date',
|
||||||
|
'postPublishAt': 'Publish At',
|
||||||
|
'postPublishedUntil': 'Publish Until',
|
||||||
'postPublishZone': 'Publish Zone',
|
'postPublishZone': 'Publish Zone',
|
||||||
'postPublishZoneNone': 'None',
|
'postPublishZoneNone': 'None',
|
||||||
'postVisibility': 'Visibility',
|
'postVisibility': 'Visibility',
|
||||||
|
@ -95,6 +95,9 @@ const i18nSimplifiedChinese = {
|
|||||||
'postRestoreFromLocal': '内容从本地暂存回复',
|
'postRestoreFromLocal': '内容从本地暂存回复',
|
||||||
'postAutoSaveAt': '已自动保存于 @date',
|
'postAutoSaveAt': '已自动保存于 @date',
|
||||||
'postCategoriesAndTags': '分类与标签',
|
'postCategoriesAndTags': '分类与标签',
|
||||||
|
'postPublishDate': '发布时间',
|
||||||
|
'postPublishAt': '发布帖子于',
|
||||||
|
'postPublishedUntil': '取消发布于',
|
||||||
'postPublishZone': '帖子发布区',
|
'postPublishZone': '帖子发布区',
|
||||||
'postPublishZoneNone': '无所属领域',
|
'postPublishZoneNone': '无所属领域',
|
||||||
'postVisibility': '帖子可见性',
|
'postVisibility': '帖子可见性',
|
||||||
|
118
lib/widgets/posts/editor/post_editor_date.dart
Normal file
118
lib/widgets/posts/editor/post_editor_date.dart
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:get/get.dart';
|
||||||
|
import 'package:intl/intl.dart';
|
||||||
|
import 'package:solian/controllers/post_editor_controller.dart';
|
||||||
|
|
||||||
|
class PostEditorDateDialog extends StatefulWidget {
|
||||||
|
final PostEditorController controller;
|
||||||
|
|
||||||
|
const PostEditorDateDialog({super.key, required this.controller});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<PostEditorDateDialog> createState() => _PostEditorDateDialogState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _PostEditorDateDialogState extends State<PostEditorDateDialog> {
|
||||||
|
final TextEditingController _publishedAtController = TextEditingController();
|
||||||
|
final TextEditingController _publishedUntilController =
|
||||||
|
TextEditingController();
|
||||||
|
|
||||||
|
final _dateFormatter = DateFormat('yyyy-MM-dd HH:mm:ss');
|
||||||
|
|
||||||
|
void _selectDate(int mode) async {
|
||||||
|
final initial = mode == 0
|
||||||
|
? widget.controller.publishedAt.value
|
||||||
|
: widget.controller.publishedUntil.value;
|
||||||
|
final DateTime? pickedDate = await showDatePicker(
|
||||||
|
context: context,
|
||||||
|
initialDate: initial?.toLocal(),
|
||||||
|
firstDate: DateTime(DateTime.now().year),
|
||||||
|
lastDate: DateTime(DateTime.now().year + 5),
|
||||||
|
);
|
||||||
|
if (pickedDate == null) return;
|
||||||
|
final TimeOfDay? pickedTime = await showTimePicker(
|
||||||
|
context: context,
|
||||||
|
initialTime: TimeOfDay.now(),
|
||||||
|
);
|
||||||
|
if (pickedTime == null) return;
|
||||||
|
final picked = pickedDate.copyWith(
|
||||||
|
hour: pickedTime.hour,
|
||||||
|
minute: pickedTime.minute,
|
||||||
|
);
|
||||||
|
if (mode == 0) {
|
||||||
|
setState(() {
|
||||||
|
widget.controller.publishedAt.value = picked;
|
||||||
|
_publishedAtController.text = _dateFormatter.format(picked);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
widget.controller.publishedUntil.value = pickedDate;
|
||||||
|
_publishedUntilController.text = _dateFormatter.format(picked);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
if (widget.controller.publishedAt.value != null) {
|
||||||
|
_publishedAtController.text =
|
||||||
|
_dateFormatter.format(widget.controller.publishedAt.value!);
|
||||||
|
}
|
||||||
|
if (widget.controller.publishedUntil.value != null) {
|
||||||
|
_publishedUntilController.text =
|
||||||
|
_dateFormatter.format(widget.controller.publishedUntil.value!);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
super.dispose();
|
||||||
|
_publishedAtController.dispose();
|
||||||
|
_publishedUntilController.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return AlertDialog(
|
||||||
|
title: Text('postPublishDate'.tr),
|
||||||
|
content: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
TextField(
|
||||||
|
controller: _publishedAtController,
|
||||||
|
readOnly: true,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
border: const UnderlineInputBorder(),
|
||||||
|
labelText: 'postPublishAt'.tr,
|
||||||
|
),
|
||||||
|
onTap: () => _selectDate(0),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
TextField(
|
||||||
|
controller: _publishedUntilController,
|
||||||
|
readOnly: true,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
border: const UnderlineInputBorder(),
|
||||||
|
labelText: 'postPublishedUntil'.tr,
|
||||||
|
),
|
||||||
|
onTap: () => _selectDate(1),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () {
|
||||||
|
widget.controller.publishedAt.value = null;
|
||||||
|
widget.controller.publishedUntil.value = null;
|
||||||
|
_publishedAtController.clear();
|
||||||
|
_publishedUntilController.clear();
|
||||||
|
},
|
||||||
|
child: Text('clear'.tr),
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => Navigator.pop(context),
|
||||||
|
child: Text('confirm'.tr),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user