add drafts section to settings
This commit is contained in:
parent
5f23176e6e
commit
89df32f4a9
|
@ -12,6 +12,7 @@ import 'app_config.dart';
|
|||
import 'l10n/timeago/pl.dart';
|
||||
import 'pages/log_console/log_console_page_store.dart';
|
||||
import 'stores/accounts_store.dart';
|
||||
import 'stores/comment_drafts_store.dart';
|
||||
import 'stores/config_store.dart';
|
||||
import 'util/mobx_provider.dart';
|
||||
|
||||
|
@ -21,6 +22,7 @@ Future<void> mainCommon(AppConfig appConfig) async {
|
|||
final logConsoleStore = LogConsolePageStore();
|
||||
final sharedPrefs = await SharedPreferences.getInstance();
|
||||
await Hive.initFlutter();
|
||||
await CommentDraftStore.open();
|
||||
|
||||
_setupLogger(appConfig, logConsoleStore);
|
||||
_setupTimeago();
|
||||
|
|
|
@ -0,0 +1,140 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
|
||||
import '../../stores/comment_drafts_store.dart';
|
||||
|
||||
class DraftsPage extends HookWidget {
|
||||
const DraftsPage._();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return DefaultTabController(
|
||||
length: 2,
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
leading: const BackButton(),
|
||||
title: const Text('Drafts'),
|
||||
bottom: const TabBar(
|
||||
isScrollable: true,
|
||||
tabs: [
|
||||
Tab(child: Text('Comments')),
|
||||
Tab(child: Text('Posts')),
|
||||
],
|
||||
),
|
||||
),
|
||||
body: const TabBarView(children: [
|
||||
_CommentsTab(),
|
||||
_PostsTab(),
|
||||
])),
|
||||
);
|
||||
}
|
||||
|
||||
static Route route() => MaterialPageRoute(
|
||||
builder: (context) => const DraftsPage._(),
|
||||
);
|
||||
}
|
||||
|
||||
class _CommentsTab extends HookWidget {
|
||||
const _CommentsTab();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ValueListenableBuilder<LazyBox<String>>(
|
||||
valueListenable: CommentDraftStore.allDraftsListenable(),
|
||||
builder: (context, box, widget) {
|
||||
if (box.isEmpty) {
|
||||
return const Center(child: Text('no drafts yet'));
|
||||
}
|
||||
|
||||
Future<void> removeAllDrafts() async {
|
||||
final removeAll = await showDialog<bool>(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
title: const Text(
|
||||
'Do you want to remove ALL comment drafts?'),
|
||||
actions: [
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop(true);
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
primary: Colors.red,
|
||||
),
|
||||
child: const Text('Yes'),
|
||||
),
|
||||
OutlinedButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop(false);
|
||||
},
|
||||
child: const Text('No'),
|
||||
),
|
||||
],
|
||||
)) ??
|
||||
false;
|
||||
if (removeAll) {
|
||||
await CommentDraftStore.removeAllDrafts();
|
||||
}
|
||||
}
|
||||
|
||||
return ListView.builder(
|
||||
itemCount: box.length + 1,
|
||||
itemBuilder: (context, index) {
|
||||
if (index == box.length) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: ElevatedButton(
|
||||
onPressed: removeAllDrafts,
|
||||
style: ElevatedButton.styleFrom(
|
||||
primary: Colors.red,
|
||||
),
|
||||
child: const Text('Remove all drafts'),
|
||||
),
|
||||
);
|
||||
}
|
||||
return _CommentDraftTile(CommentDraftStore.keyAt(index)!);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _CommentDraftTile extends HookWidget {
|
||||
final String databaseKey;
|
||||
|
||||
const _CommentDraftTile(this.databaseKey);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final body = useState<String?>(null);
|
||||
useEffect(() {
|
||||
CommentDraftStore.loadDraft(databaseKey)
|
||||
.then((value) => body.value = value);
|
||||
return null;
|
||||
});
|
||||
|
||||
return ListTile(
|
||||
key: ValueKey(key),
|
||||
title: body.value == null
|
||||
? const CircularProgressIndicator.adaptive()
|
||||
: Text(body.value!),
|
||||
trailing: IconButton(
|
||||
icon: const Icon(Icons.delete),
|
||||
onPressed: () {
|
||||
CommentDraftStore.removeDraft(databaseKey);
|
||||
},
|
||||
),
|
||||
subtitle: Text(databaseKey),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _PostsTab extends StatelessWidget {
|
||||
const _PostsTab();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return const Center(child: Text('TBD'));
|
||||
}
|
||||
}
|
|
@ -16,6 +16,7 @@ import '../manage_account.dart';
|
|||
import 'add_account_page.dart';
|
||||
import 'add_instance_page.dart';
|
||||
import 'blocks/blocks.dart';
|
||||
import 'drafts_page.dart';
|
||||
|
||||
/// Page with a list of different settings sections
|
||||
class SettingsPage extends HookWidget {
|
||||
|
@ -60,6 +61,13 @@ class SettingsPage extends HookWidget {
|
|||
goTo(context, (_) => const AppearanceConfigPage());
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
leading: const Icon(Icons.drive_file_rename_outline_outlined),
|
||||
title: const Text('Drafts'),
|
||||
onTap: () {
|
||||
Navigator.of(context).push(DraftsPage.route());
|
||||
},
|
||||
),
|
||||
const AboutTile()
|
||||
],
|
||||
),
|
||||
|
|
|
@ -1,24 +1,37 @@
|
|||
import 'package:hive/hive.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:hive_flutter/adapters.dart';
|
||||
|
||||
class CommentDraftStore {
|
||||
static const _boxKey = 'comment_drafts';
|
||||
static late LazyBox<String> _box;
|
||||
|
||||
static Future<String?> loadDraft(String apId) async {
|
||||
final box = await Hive.openBox<String>(_boxKey);
|
||||
final text = box.get(apId);
|
||||
await box.close();
|
||||
return text;
|
||||
static Future<void> open() async {
|
||||
_box = await Hive.openLazyBox<String>(_boxKey);
|
||||
}
|
||||
|
||||
static Future<void> saveDraft(String apId, String text) async {
|
||||
final box = await Hive.openBox<String>(_boxKey);
|
||||
await box.put(apId, text);
|
||||
await box.close();
|
||||
static Future<void> close() async {
|
||||
await _box.compact();
|
||||
await _box.close();
|
||||
}
|
||||
|
||||
static Future<void> removeDraft(String apId) async {
|
||||
final box = await Hive.openBox<String>(_boxKey);
|
||||
await box.delete(apId);
|
||||
await box.close();
|
||||
static Future<void> compact() async {
|
||||
await _box.compact();
|
||||
}
|
||||
|
||||
static String? keyAt(int index) => _box.keyAt(index);
|
||||
|
||||
static ValueListenable<LazyBox<String>> allDraftsListenable() =>
|
||||
_box.listenable();
|
||||
|
||||
static Future<String?> loadDraft(String apId) => _box.get(apId);
|
||||
|
||||
static Future<void> saveDraft(String apId, String text) =>
|
||||
_box.put(apId, text);
|
||||
|
||||
static Future<void> removeDraft(String apId) => _box.delete(apId);
|
||||
|
||||
static Future<void> removeAllDrafts() async {
|
||||
await _box.deleteFromDisk();
|
||||
await open();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -116,10 +116,15 @@ class WriteComment extends HookWidget {
|
|||
leading: CloseButton(
|
||||
onPressed: () async {
|
||||
// save draft before closing
|
||||
if (!_isEdit &&
|
||||
editorController.textEditingController.text.trim().isNotEmpty) {
|
||||
await CommentDraftStore.saveDraft(comment?.apId ?? post.apId,
|
||||
editorController.textEditingController.text);
|
||||
if (!_isEdit) {
|
||||
if (editorController.textEditingController.text
|
||||
.trim()
|
||||
.isNotEmpty) {
|
||||
await CommentDraftStore.saveDraft(comment?.apId ?? post.apId,
|
||||
editorController.textEditingController.text);
|
||||
} else {
|
||||
await CommentDraftStore.removeDraft(comment?.apId ?? post.apId);
|
||||
}
|
||||
}
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue