✨ Reworked post draft
This commit is contained in:
@@ -471,6 +471,8 @@
|
||||
"close": "Close",
|
||||
"drafts": "Drafts",
|
||||
"noDrafts": "No drafts yet",
|
||||
"searchDrafts": "Search drafts...",
|
||||
"noSearchResults": "No search results",
|
||||
"articleDrafts": "Article drafts",
|
||||
"postDrafts": "Post drafts",
|
||||
"saveDraft": "Save draft",
|
||||
|
@@ -2,8 +2,15 @@ import 'package:drift/drift.dart';
|
||||
|
||||
class PostDrafts extends Table {
|
||||
TextColumn get id => text()();
|
||||
TextColumn get post => text()(); // Store SnPost model as JSON string
|
||||
// Searchable fields stored separately for performance
|
||||
TextColumn get title => text().nullable()();
|
||||
TextColumn get description => text().nullable()();
|
||||
TextColumn get content => text().nullable()();
|
||||
IntColumn get visibility => integer().withDefault(const Constant(0))();
|
||||
IntColumn get type => integer().withDefault(const Constant(0))();
|
||||
DateTimeColumn get lastModified => dateTime()();
|
||||
// Full post data stored as JSON for complete restoration
|
||||
TextColumn get postData => text()();
|
||||
|
||||
@override
|
||||
Set<Column> get primaryKey => {id};
|
||||
|
@@ -12,7 +12,7 @@ class AppDatabase extends _$AppDatabase {
|
||||
AppDatabase(super.e);
|
||||
|
||||
@override
|
||||
int get schemaVersion => 4;
|
||||
int get schemaVersion => 6;
|
||||
|
||||
@override
|
||||
MigrationStrategy get migration => MigrationStrategy(
|
||||
@@ -28,9 +28,67 @@ class AppDatabase extends _$AppDatabase {
|
||||
// Drop old draft tables if they exist
|
||||
await m.createTable(postDrafts);
|
||||
}
|
||||
if (from < 6) {
|
||||
// Migrate from old schema to new schema with separate searchable fields
|
||||
await _migrateToVersion6(m);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
Future<void> _migrateToVersion6(Migrator m) async {
|
||||
// Rename existing table to old if it exists
|
||||
try {
|
||||
await customStatement(
|
||||
'ALTER TABLE post_drafts RENAME TO post_drafts_old',
|
||||
);
|
||||
} catch (e) {
|
||||
// Table might not exist
|
||||
}
|
||||
|
||||
// Drop the table
|
||||
await customStatement('DROP TABLE IF EXISTS post_drafts');
|
||||
|
||||
// Create new table
|
||||
await m.createTable(postDrafts);
|
||||
|
||||
// Migrate existing data if any
|
||||
try {
|
||||
final oldDrafts =
|
||||
await customSelect(
|
||||
'SELECT id, post, lastModified FROM post_drafts_old',
|
||||
readsFrom: {postDrafts},
|
||||
).get();
|
||||
|
||||
for (final row in oldDrafts) {
|
||||
final postJson = row.read<String>('post');
|
||||
final id = row.read<String>('id');
|
||||
final lastModified = row.read<DateTime>('lastModified');
|
||||
|
||||
if (postJson.isNotEmpty) {
|
||||
final post = SnPost.fromJson(jsonDecode(postJson));
|
||||
await into(postDrafts).insert(
|
||||
PostDraftsCompanion(
|
||||
id: Value(id),
|
||||
title: Value(post.title),
|
||||
description: Value(post.description),
|
||||
content: Value(post.content),
|
||||
visibility: Value(post.visibility),
|
||||
type: Value(post.type),
|
||||
lastModified: Value(lastModified),
|
||||
postData: Value(postJson),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Drop old table
|
||||
await customStatement('DROP TABLE IF EXISTS post_drafts_old');
|
||||
} catch (e) {
|
||||
// If migration fails, just recreate the table
|
||||
await m.createTable(postDrafts);
|
||||
}
|
||||
}
|
||||
|
||||
// Methods for chat messages
|
||||
Future<List<ChatMessage>> getMessagesForRoom(
|
||||
String roomId, {
|
||||
@@ -69,7 +127,9 @@ class AppDatabase extends _$AppDatabase {
|
||||
}
|
||||
|
||||
Future<int> getTotalMessagesForRoom(String roomId) {
|
||||
return (select(chatMessages)..where((m) => m.roomId.equals(roomId))).get().then((list) => list.length);
|
||||
return (select(
|
||||
chatMessages,
|
||||
)..where((m) => m.roomId.equals(roomId))).get().then((list) => list.length);
|
||||
}
|
||||
|
||||
Future<List<LocalChatMessage>> searchMessages(
|
||||
@@ -85,10 +145,6 @@ class AppDatabase extends _$AppDatabase {
|
||||
..where((m) => m.content.like('%${query.toLowerCase()}%'));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
final messages =
|
||||
await (selectStatement
|
||||
..orderBy([(m) => OrderingTerm.desc(m.createdAt)]))
|
||||
@@ -129,10 +185,31 @@ class AppDatabase extends _$AppDatabase {
|
||||
Future<List<SnPost>> getAllPostDrafts() async {
|
||||
final drafts = await select(postDrafts).get();
|
||||
return drafts
|
||||
.map((draft) => SnPost.fromJson(jsonDecode(draft.post)))
|
||||
.map((draft) => SnPost.fromJson(jsonDecode(draft.postData)))
|
||||
.toList();
|
||||
}
|
||||
|
||||
Future<List<PostDraft>> getAllPostDraftRecords() async {
|
||||
return await select(postDrafts).get();
|
||||
}
|
||||
|
||||
Future<List<PostDraft>> searchPostDrafts(String query) async {
|
||||
if (query.isEmpty) {
|
||||
return await select(postDrafts).get();
|
||||
}
|
||||
|
||||
final searchTerm = '%${query.toLowerCase()}%';
|
||||
return await (select(postDrafts)
|
||||
..where(
|
||||
(draft) =>
|
||||
draft.title.like(searchTerm) |
|
||||
draft.description.like(searchTerm) |
|
||||
draft.content.like(searchTerm),
|
||||
)
|
||||
..orderBy([(draft) => OrderingTerm.desc(draft.lastModified)]))
|
||||
.get();
|
||||
}
|
||||
|
||||
Future<void> addPostDraft(PostDraftsCompanion entry) async {
|
||||
await into(postDrafts).insert(entry, mode: InsertMode.replace);
|
||||
}
|
||||
@@ -144,4 +221,9 @@ class AppDatabase extends _$AppDatabase {
|
||||
Future<void> clearAllPostDrafts() async {
|
||||
await delete(postDrafts).go();
|
||||
}
|
||||
|
||||
Future<PostDraft?> getPostDraftById(String id) async {
|
||||
return await (select(postDrafts)
|
||||
..where((tbl) => tbl.id.equals(id))).getSingleOrNull();
|
||||
}
|
||||
}
|
||||
|
@@ -584,14 +584,58 @@ class $PostDraftsTable extends PostDrafts
|
||||
type: DriftSqlType.string,
|
||||
requiredDuringInsert: true,
|
||||
);
|
||||
static const VerificationMeta _postMeta = const VerificationMeta('post');
|
||||
static const VerificationMeta _titleMeta = const VerificationMeta('title');
|
||||
@override
|
||||
late final GeneratedColumn<String> post = GeneratedColumn<String>(
|
||||
'post',
|
||||
late final GeneratedColumn<String> title = GeneratedColumn<String>(
|
||||
'title',
|
||||
aliasedName,
|
||||
true,
|
||||
type: DriftSqlType.string,
|
||||
requiredDuringInsert: false,
|
||||
);
|
||||
static const VerificationMeta _descriptionMeta = const VerificationMeta(
|
||||
'description',
|
||||
);
|
||||
@override
|
||||
late final GeneratedColumn<String> description = GeneratedColumn<String>(
|
||||
'description',
|
||||
aliasedName,
|
||||
true,
|
||||
type: DriftSqlType.string,
|
||||
requiredDuringInsert: false,
|
||||
);
|
||||
static const VerificationMeta _contentMeta = const VerificationMeta(
|
||||
'content',
|
||||
);
|
||||
@override
|
||||
late final GeneratedColumn<String> content = GeneratedColumn<String>(
|
||||
'content',
|
||||
aliasedName,
|
||||
true,
|
||||
type: DriftSqlType.string,
|
||||
requiredDuringInsert: false,
|
||||
);
|
||||
static const VerificationMeta _visibilityMeta = const VerificationMeta(
|
||||
'visibility',
|
||||
);
|
||||
@override
|
||||
late final GeneratedColumn<int> visibility = GeneratedColumn<int>(
|
||||
'visibility',
|
||||
aliasedName,
|
||||
false,
|
||||
type: DriftSqlType.string,
|
||||
requiredDuringInsert: true,
|
||||
type: DriftSqlType.int,
|
||||
requiredDuringInsert: false,
|
||||
defaultValue: const Constant(0),
|
||||
);
|
||||
static const VerificationMeta _typeMeta = const VerificationMeta('type');
|
||||
@override
|
||||
late final GeneratedColumn<int> type = GeneratedColumn<int>(
|
||||
'type',
|
||||
aliasedName,
|
||||
false,
|
||||
type: DriftSqlType.int,
|
||||
requiredDuringInsert: false,
|
||||
defaultValue: const Constant(0),
|
||||
);
|
||||
static const VerificationMeta _lastModifiedMeta = const VerificationMeta(
|
||||
'lastModified',
|
||||
@@ -604,8 +648,28 @@ class $PostDraftsTable extends PostDrafts
|
||||
type: DriftSqlType.dateTime,
|
||||
requiredDuringInsert: true,
|
||||
);
|
||||
static const VerificationMeta _postDataMeta = const VerificationMeta(
|
||||
'postData',
|
||||
);
|
||||
@override
|
||||
List<GeneratedColumn> get $columns => [id, post, lastModified];
|
||||
late final GeneratedColumn<String> postData = GeneratedColumn<String>(
|
||||
'post_data',
|
||||
aliasedName,
|
||||
false,
|
||||
type: DriftSqlType.string,
|
||||
requiredDuringInsert: true,
|
||||
);
|
||||
@override
|
||||
List<GeneratedColumn> get $columns => [
|
||||
id,
|
||||
title,
|
||||
description,
|
||||
content,
|
||||
visibility,
|
||||
type,
|
||||
lastModified,
|
||||
postData,
|
||||
];
|
||||
@override
|
||||
String get aliasedName => _alias ?? actualTableName;
|
||||
@override
|
||||
@@ -623,13 +687,38 @@ class $PostDraftsTable extends PostDrafts
|
||||
} else if (isInserting) {
|
||||
context.missing(_idMeta);
|
||||
}
|
||||
if (data.containsKey('post')) {
|
||||
if (data.containsKey('title')) {
|
||||
context.handle(
|
||||
_postMeta,
|
||||
post.isAcceptableOrUnknown(data['post']!, _postMeta),
|
||||
_titleMeta,
|
||||
title.isAcceptableOrUnknown(data['title']!, _titleMeta),
|
||||
);
|
||||
}
|
||||
if (data.containsKey('description')) {
|
||||
context.handle(
|
||||
_descriptionMeta,
|
||||
description.isAcceptableOrUnknown(
|
||||
data['description']!,
|
||||
_descriptionMeta,
|
||||
),
|
||||
);
|
||||
}
|
||||
if (data.containsKey('content')) {
|
||||
context.handle(
|
||||
_contentMeta,
|
||||
content.isAcceptableOrUnknown(data['content']!, _contentMeta),
|
||||
);
|
||||
}
|
||||
if (data.containsKey('visibility')) {
|
||||
context.handle(
|
||||
_visibilityMeta,
|
||||
visibility.isAcceptableOrUnknown(data['visibility']!, _visibilityMeta),
|
||||
);
|
||||
}
|
||||
if (data.containsKey('type')) {
|
||||
context.handle(
|
||||
_typeMeta,
|
||||
type.isAcceptableOrUnknown(data['type']!, _typeMeta),
|
||||
);
|
||||
} else if (isInserting) {
|
||||
context.missing(_postMeta);
|
||||
}
|
||||
if (data.containsKey('last_modified')) {
|
||||
context.handle(
|
||||
@@ -642,6 +731,14 @@ class $PostDraftsTable extends PostDrafts
|
||||
} else if (isInserting) {
|
||||
context.missing(_lastModifiedMeta);
|
||||
}
|
||||
if (data.containsKey('post_data')) {
|
||||
context.handle(
|
||||
_postDataMeta,
|
||||
postData.isAcceptableOrUnknown(data['post_data']!, _postDataMeta),
|
||||
);
|
||||
} else if (isInserting) {
|
||||
context.missing(_postDataMeta);
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
@@ -656,16 +753,38 @@ class $PostDraftsTable extends PostDrafts
|
||||
DriftSqlType.string,
|
||||
data['${effectivePrefix}id'],
|
||||
)!,
|
||||
post:
|
||||
title: attachedDatabase.typeMapping.read(
|
||||
DriftSqlType.string,
|
||||
data['${effectivePrefix}title'],
|
||||
),
|
||||
description: attachedDatabase.typeMapping.read(
|
||||
DriftSqlType.string,
|
||||
data['${effectivePrefix}description'],
|
||||
),
|
||||
content: attachedDatabase.typeMapping.read(
|
||||
DriftSqlType.string,
|
||||
data['${effectivePrefix}content'],
|
||||
),
|
||||
visibility:
|
||||
attachedDatabase.typeMapping.read(
|
||||
DriftSqlType.string,
|
||||
data['${effectivePrefix}post'],
|
||||
DriftSqlType.int,
|
||||
data['${effectivePrefix}visibility'],
|
||||
)!,
|
||||
type:
|
||||
attachedDatabase.typeMapping.read(
|
||||
DriftSqlType.int,
|
||||
data['${effectivePrefix}type'],
|
||||
)!,
|
||||
lastModified:
|
||||
attachedDatabase.typeMapping.read(
|
||||
DriftSqlType.dateTime,
|
||||
data['${effectivePrefix}last_modified'],
|
||||
)!,
|
||||
postData:
|
||||
attachedDatabase.typeMapping.read(
|
||||
DriftSqlType.string,
|
||||
data['${effectivePrefix}post_data'],
|
||||
)!,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -677,27 +796,60 @@ class $PostDraftsTable extends PostDrafts
|
||||
|
||||
class PostDraft extends DataClass implements Insertable<PostDraft> {
|
||||
final String id;
|
||||
final String post;
|
||||
final String? title;
|
||||
final String? description;
|
||||
final String? content;
|
||||
final int visibility;
|
||||
final int type;
|
||||
final DateTime lastModified;
|
||||
final String postData;
|
||||
const PostDraft({
|
||||
required this.id,
|
||||
required this.post,
|
||||
this.title,
|
||||
this.description,
|
||||
this.content,
|
||||
required this.visibility,
|
||||
required this.type,
|
||||
required this.lastModified,
|
||||
required this.postData,
|
||||
});
|
||||
@override
|
||||
Map<String, Expression> toColumns(bool nullToAbsent) {
|
||||
final map = <String, Expression>{};
|
||||
map['id'] = Variable<String>(id);
|
||||
map['post'] = Variable<String>(post);
|
||||
if (!nullToAbsent || title != null) {
|
||||
map['title'] = Variable<String>(title);
|
||||
}
|
||||
if (!nullToAbsent || description != null) {
|
||||
map['description'] = Variable<String>(description);
|
||||
}
|
||||
if (!nullToAbsent || content != null) {
|
||||
map['content'] = Variable<String>(content);
|
||||
}
|
||||
map['visibility'] = Variable<int>(visibility);
|
||||
map['type'] = Variable<int>(type);
|
||||
map['last_modified'] = Variable<DateTime>(lastModified);
|
||||
map['post_data'] = Variable<String>(postData);
|
||||
return map;
|
||||
}
|
||||
|
||||
PostDraftsCompanion toCompanion(bool nullToAbsent) {
|
||||
return PostDraftsCompanion(
|
||||
id: Value(id),
|
||||
post: Value(post),
|
||||
title:
|
||||
title == null && nullToAbsent ? const Value.absent() : Value(title),
|
||||
description:
|
||||
description == null && nullToAbsent
|
||||
? const Value.absent()
|
||||
: Value(description),
|
||||
content:
|
||||
content == null && nullToAbsent
|
||||
? const Value.absent()
|
||||
: Value(content),
|
||||
visibility: Value(visibility),
|
||||
type: Value(type),
|
||||
lastModified: Value(lastModified),
|
||||
postData: Value(postData),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -708,8 +860,13 @@ class PostDraft extends DataClass implements Insertable<PostDraft> {
|
||||
serializer ??= driftRuntimeOptions.defaultSerializer;
|
||||
return PostDraft(
|
||||
id: serializer.fromJson<String>(json['id']),
|
||||
post: serializer.fromJson<String>(json['post']),
|
||||
title: serializer.fromJson<String?>(json['title']),
|
||||
description: serializer.fromJson<String?>(json['description']),
|
||||
content: serializer.fromJson<String?>(json['content']),
|
||||
visibility: serializer.fromJson<int>(json['visibility']),
|
||||
type: serializer.fromJson<int>(json['type']),
|
||||
lastModified: serializer.fromJson<DateTime>(json['lastModified']),
|
||||
postData: serializer.fromJson<String>(json['postData']),
|
||||
);
|
||||
}
|
||||
@override
|
||||
@@ -717,25 +874,50 @@ class PostDraft extends DataClass implements Insertable<PostDraft> {
|
||||
serializer ??= driftRuntimeOptions.defaultSerializer;
|
||||
return <String, dynamic>{
|
||||
'id': serializer.toJson<String>(id),
|
||||
'post': serializer.toJson<String>(post),
|
||||
'title': serializer.toJson<String?>(title),
|
||||
'description': serializer.toJson<String?>(description),
|
||||
'content': serializer.toJson<String?>(content),
|
||||
'visibility': serializer.toJson<int>(visibility),
|
||||
'type': serializer.toJson<int>(type),
|
||||
'lastModified': serializer.toJson<DateTime>(lastModified),
|
||||
'postData': serializer.toJson<String>(postData),
|
||||
};
|
||||
}
|
||||
|
||||
PostDraft copyWith({String? id, String? post, DateTime? lastModified}) =>
|
||||
PostDraft(
|
||||
id: id ?? this.id,
|
||||
post: post ?? this.post,
|
||||
lastModified: lastModified ?? this.lastModified,
|
||||
);
|
||||
PostDraft copyWith({
|
||||
String? id,
|
||||
Value<String?> title = const Value.absent(),
|
||||
Value<String?> description = const Value.absent(),
|
||||
Value<String?> content = const Value.absent(),
|
||||
int? visibility,
|
||||
int? type,
|
||||
DateTime? lastModified,
|
||||
String? postData,
|
||||
}) => PostDraft(
|
||||
id: id ?? this.id,
|
||||
title: title.present ? title.value : this.title,
|
||||
description: description.present ? description.value : this.description,
|
||||
content: content.present ? content.value : this.content,
|
||||
visibility: visibility ?? this.visibility,
|
||||
type: type ?? this.type,
|
||||
lastModified: lastModified ?? this.lastModified,
|
||||
postData: postData ?? this.postData,
|
||||
);
|
||||
PostDraft copyWithCompanion(PostDraftsCompanion data) {
|
||||
return PostDraft(
|
||||
id: data.id.present ? data.id.value : this.id,
|
||||
post: data.post.present ? data.post.value : this.post,
|
||||
title: data.title.present ? data.title.value : this.title,
|
||||
description:
|
||||
data.description.present ? data.description.value : this.description,
|
||||
content: data.content.present ? data.content.value : this.content,
|
||||
visibility:
|
||||
data.visibility.present ? data.visibility.value : this.visibility,
|
||||
type: data.type.present ? data.type.value : this.type,
|
||||
lastModified:
|
||||
data.lastModified.present
|
||||
? data.lastModified.value
|
||||
: this.lastModified,
|
||||
postData: data.postData.present ? data.postData.value : this.postData,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -743,66 +925,120 @@ class PostDraft extends DataClass implements Insertable<PostDraft> {
|
||||
String toString() {
|
||||
return (StringBuffer('PostDraft(')
|
||||
..write('id: $id, ')
|
||||
..write('post: $post, ')
|
||||
..write('lastModified: $lastModified')
|
||||
..write('title: $title, ')
|
||||
..write('description: $description, ')
|
||||
..write('content: $content, ')
|
||||
..write('visibility: $visibility, ')
|
||||
..write('type: $type, ')
|
||||
..write('lastModified: $lastModified, ')
|
||||
..write('postData: $postData')
|
||||
..write(')'))
|
||||
.toString();
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(id, post, lastModified);
|
||||
int get hashCode => Object.hash(
|
||||
id,
|
||||
title,
|
||||
description,
|
||||
content,
|
||||
visibility,
|
||||
type,
|
||||
lastModified,
|
||||
postData,
|
||||
);
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
(other is PostDraft &&
|
||||
other.id == this.id &&
|
||||
other.post == this.post &&
|
||||
other.lastModified == this.lastModified);
|
||||
other.title == this.title &&
|
||||
other.description == this.description &&
|
||||
other.content == this.content &&
|
||||
other.visibility == this.visibility &&
|
||||
other.type == this.type &&
|
||||
other.lastModified == this.lastModified &&
|
||||
other.postData == this.postData);
|
||||
}
|
||||
|
||||
class PostDraftsCompanion extends UpdateCompanion<PostDraft> {
|
||||
final Value<String> id;
|
||||
final Value<String> post;
|
||||
final Value<String?> title;
|
||||
final Value<String?> description;
|
||||
final Value<String?> content;
|
||||
final Value<int> visibility;
|
||||
final Value<int> type;
|
||||
final Value<DateTime> lastModified;
|
||||
final Value<String> postData;
|
||||
final Value<int> rowid;
|
||||
const PostDraftsCompanion({
|
||||
this.id = const Value.absent(),
|
||||
this.post = const Value.absent(),
|
||||
this.title = const Value.absent(),
|
||||
this.description = const Value.absent(),
|
||||
this.content = const Value.absent(),
|
||||
this.visibility = const Value.absent(),
|
||||
this.type = const Value.absent(),
|
||||
this.lastModified = const Value.absent(),
|
||||
this.postData = const Value.absent(),
|
||||
this.rowid = const Value.absent(),
|
||||
});
|
||||
PostDraftsCompanion.insert({
|
||||
required String id,
|
||||
required String post,
|
||||
this.title = const Value.absent(),
|
||||
this.description = const Value.absent(),
|
||||
this.content = const Value.absent(),
|
||||
this.visibility = const Value.absent(),
|
||||
this.type = const Value.absent(),
|
||||
required DateTime lastModified,
|
||||
required String postData,
|
||||
this.rowid = const Value.absent(),
|
||||
}) : id = Value(id),
|
||||
post = Value(post),
|
||||
lastModified = Value(lastModified);
|
||||
lastModified = Value(lastModified),
|
||||
postData = Value(postData);
|
||||
static Insertable<PostDraft> custom({
|
||||
Expression<String>? id,
|
||||
Expression<String>? post,
|
||||
Expression<String>? title,
|
||||
Expression<String>? description,
|
||||
Expression<String>? content,
|
||||
Expression<int>? visibility,
|
||||
Expression<int>? type,
|
||||
Expression<DateTime>? lastModified,
|
||||
Expression<String>? postData,
|
||||
Expression<int>? rowid,
|
||||
}) {
|
||||
return RawValuesInsertable({
|
||||
if (id != null) 'id': id,
|
||||
if (post != null) 'post': post,
|
||||
if (title != null) 'title': title,
|
||||
if (description != null) 'description': description,
|
||||
if (content != null) 'content': content,
|
||||
if (visibility != null) 'visibility': visibility,
|
||||
if (type != null) 'type': type,
|
||||
if (lastModified != null) 'last_modified': lastModified,
|
||||
if (postData != null) 'post_data': postData,
|
||||
if (rowid != null) 'rowid': rowid,
|
||||
});
|
||||
}
|
||||
|
||||
PostDraftsCompanion copyWith({
|
||||
Value<String>? id,
|
||||
Value<String>? post,
|
||||
Value<String?>? title,
|
||||
Value<String?>? description,
|
||||
Value<String?>? content,
|
||||
Value<int>? visibility,
|
||||
Value<int>? type,
|
||||
Value<DateTime>? lastModified,
|
||||
Value<String>? postData,
|
||||
Value<int>? rowid,
|
||||
}) {
|
||||
return PostDraftsCompanion(
|
||||
id: id ?? this.id,
|
||||
post: post ?? this.post,
|
||||
title: title ?? this.title,
|
||||
description: description ?? this.description,
|
||||
content: content ?? this.content,
|
||||
visibility: visibility ?? this.visibility,
|
||||
type: type ?? this.type,
|
||||
lastModified: lastModified ?? this.lastModified,
|
||||
postData: postData ?? this.postData,
|
||||
rowid: rowid ?? this.rowid,
|
||||
);
|
||||
}
|
||||
@@ -813,12 +1049,27 @@ class PostDraftsCompanion extends UpdateCompanion<PostDraft> {
|
||||
if (id.present) {
|
||||
map['id'] = Variable<String>(id.value);
|
||||
}
|
||||
if (post.present) {
|
||||
map['post'] = Variable<String>(post.value);
|
||||
if (title.present) {
|
||||
map['title'] = Variable<String>(title.value);
|
||||
}
|
||||
if (description.present) {
|
||||
map['description'] = Variable<String>(description.value);
|
||||
}
|
||||
if (content.present) {
|
||||
map['content'] = Variable<String>(content.value);
|
||||
}
|
||||
if (visibility.present) {
|
||||
map['visibility'] = Variable<int>(visibility.value);
|
||||
}
|
||||
if (type.present) {
|
||||
map['type'] = Variable<int>(type.value);
|
||||
}
|
||||
if (lastModified.present) {
|
||||
map['last_modified'] = Variable<DateTime>(lastModified.value);
|
||||
}
|
||||
if (postData.present) {
|
||||
map['post_data'] = Variable<String>(postData.value);
|
||||
}
|
||||
if (rowid.present) {
|
||||
map['rowid'] = Variable<int>(rowid.value);
|
||||
}
|
||||
@@ -829,8 +1080,13 @@ class PostDraftsCompanion extends UpdateCompanion<PostDraft> {
|
||||
String toString() {
|
||||
return (StringBuffer('PostDraftsCompanion(')
|
||||
..write('id: $id, ')
|
||||
..write('post: $post, ')
|
||||
..write('title: $title, ')
|
||||
..write('description: $description, ')
|
||||
..write('content: $content, ')
|
||||
..write('visibility: $visibility, ')
|
||||
..write('type: $type, ')
|
||||
..write('lastModified: $lastModified, ')
|
||||
..write('postData: $postData, ')
|
||||
..write('rowid: $rowid')
|
||||
..write(')'))
|
||||
.toString();
|
||||
@@ -1140,15 +1396,25 @@ typedef $$ChatMessagesTableProcessedTableManager =
|
||||
typedef $$PostDraftsTableCreateCompanionBuilder =
|
||||
PostDraftsCompanion Function({
|
||||
required String id,
|
||||
required String post,
|
||||
Value<String?> title,
|
||||
Value<String?> description,
|
||||
Value<String?> content,
|
||||
Value<int> visibility,
|
||||
Value<int> type,
|
||||
required DateTime lastModified,
|
||||
required String postData,
|
||||
Value<int> rowid,
|
||||
});
|
||||
typedef $$PostDraftsTableUpdateCompanionBuilder =
|
||||
PostDraftsCompanion Function({
|
||||
Value<String> id,
|
||||
Value<String> post,
|
||||
Value<String?> title,
|
||||
Value<String?> description,
|
||||
Value<String?> content,
|
||||
Value<int> visibility,
|
||||
Value<int> type,
|
||||
Value<DateTime> lastModified,
|
||||
Value<String> postData,
|
||||
Value<int> rowid,
|
||||
});
|
||||
|
||||
@@ -1166,8 +1432,28 @@ class $$PostDraftsTableFilterComposer
|
||||
builder: (column) => ColumnFilters(column),
|
||||
);
|
||||
|
||||
ColumnFilters<String> get post => $composableBuilder(
|
||||
column: $table.post,
|
||||
ColumnFilters<String> get title => $composableBuilder(
|
||||
column: $table.title,
|
||||
builder: (column) => ColumnFilters(column),
|
||||
);
|
||||
|
||||
ColumnFilters<String> get description => $composableBuilder(
|
||||
column: $table.description,
|
||||
builder: (column) => ColumnFilters(column),
|
||||
);
|
||||
|
||||
ColumnFilters<String> get content => $composableBuilder(
|
||||
column: $table.content,
|
||||
builder: (column) => ColumnFilters(column),
|
||||
);
|
||||
|
||||
ColumnFilters<int> get visibility => $composableBuilder(
|
||||
column: $table.visibility,
|
||||
builder: (column) => ColumnFilters(column),
|
||||
);
|
||||
|
||||
ColumnFilters<int> get type => $composableBuilder(
|
||||
column: $table.type,
|
||||
builder: (column) => ColumnFilters(column),
|
||||
);
|
||||
|
||||
@@ -1175,6 +1461,11 @@ class $$PostDraftsTableFilterComposer
|
||||
column: $table.lastModified,
|
||||
builder: (column) => ColumnFilters(column),
|
||||
);
|
||||
|
||||
ColumnFilters<String> get postData => $composableBuilder(
|
||||
column: $table.postData,
|
||||
builder: (column) => ColumnFilters(column),
|
||||
);
|
||||
}
|
||||
|
||||
class $$PostDraftsTableOrderingComposer
|
||||
@@ -1191,8 +1482,28 @@ class $$PostDraftsTableOrderingComposer
|
||||
builder: (column) => ColumnOrderings(column),
|
||||
);
|
||||
|
||||
ColumnOrderings<String> get post => $composableBuilder(
|
||||
column: $table.post,
|
||||
ColumnOrderings<String> get title => $composableBuilder(
|
||||
column: $table.title,
|
||||
builder: (column) => ColumnOrderings(column),
|
||||
);
|
||||
|
||||
ColumnOrderings<String> get description => $composableBuilder(
|
||||
column: $table.description,
|
||||
builder: (column) => ColumnOrderings(column),
|
||||
);
|
||||
|
||||
ColumnOrderings<String> get content => $composableBuilder(
|
||||
column: $table.content,
|
||||
builder: (column) => ColumnOrderings(column),
|
||||
);
|
||||
|
||||
ColumnOrderings<int> get visibility => $composableBuilder(
|
||||
column: $table.visibility,
|
||||
builder: (column) => ColumnOrderings(column),
|
||||
);
|
||||
|
||||
ColumnOrderings<int> get type => $composableBuilder(
|
||||
column: $table.type,
|
||||
builder: (column) => ColumnOrderings(column),
|
||||
);
|
||||
|
||||
@@ -1200,6 +1511,11 @@ class $$PostDraftsTableOrderingComposer
|
||||
column: $table.lastModified,
|
||||
builder: (column) => ColumnOrderings(column),
|
||||
);
|
||||
|
||||
ColumnOrderings<String> get postData => $composableBuilder(
|
||||
column: $table.postData,
|
||||
builder: (column) => ColumnOrderings(column),
|
||||
);
|
||||
}
|
||||
|
||||
class $$PostDraftsTableAnnotationComposer
|
||||
@@ -1214,13 +1530,32 @@ class $$PostDraftsTableAnnotationComposer
|
||||
GeneratedColumn<String> get id =>
|
||||
$composableBuilder(column: $table.id, builder: (column) => column);
|
||||
|
||||
GeneratedColumn<String> get post =>
|
||||
$composableBuilder(column: $table.post, builder: (column) => column);
|
||||
GeneratedColumn<String> get title =>
|
||||
$composableBuilder(column: $table.title, builder: (column) => column);
|
||||
|
||||
GeneratedColumn<String> get description => $composableBuilder(
|
||||
column: $table.description,
|
||||
builder: (column) => column,
|
||||
);
|
||||
|
||||
GeneratedColumn<String> get content =>
|
||||
$composableBuilder(column: $table.content, builder: (column) => column);
|
||||
|
||||
GeneratedColumn<int> get visibility => $composableBuilder(
|
||||
column: $table.visibility,
|
||||
builder: (column) => column,
|
||||
);
|
||||
|
||||
GeneratedColumn<int> get type =>
|
||||
$composableBuilder(column: $table.type, builder: (column) => column);
|
||||
|
||||
GeneratedColumn<DateTime> get lastModified => $composableBuilder(
|
||||
column: $table.lastModified,
|
||||
builder: (column) => column,
|
||||
);
|
||||
|
||||
GeneratedColumn<String> get postData =>
|
||||
$composableBuilder(column: $table.postData, builder: (column) => column);
|
||||
}
|
||||
|
||||
class $$PostDraftsTableTableManager
|
||||
@@ -1255,25 +1590,45 @@ class $$PostDraftsTableTableManager
|
||||
updateCompanionCallback:
|
||||
({
|
||||
Value<String> id = const Value.absent(),
|
||||
Value<String> post = const Value.absent(),
|
||||
Value<String?> title = const Value.absent(),
|
||||
Value<String?> description = const Value.absent(),
|
||||
Value<String?> content = const Value.absent(),
|
||||
Value<int> visibility = const Value.absent(),
|
||||
Value<int> type = const Value.absent(),
|
||||
Value<DateTime> lastModified = const Value.absent(),
|
||||
Value<String> postData = const Value.absent(),
|
||||
Value<int> rowid = const Value.absent(),
|
||||
}) => PostDraftsCompanion(
|
||||
id: id,
|
||||
post: post,
|
||||
title: title,
|
||||
description: description,
|
||||
content: content,
|
||||
visibility: visibility,
|
||||
type: type,
|
||||
lastModified: lastModified,
|
||||
postData: postData,
|
||||
rowid: rowid,
|
||||
),
|
||||
createCompanionCallback:
|
||||
({
|
||||
required String id,
|
||||
required String post,
|
||||
Value<String?> title = const Value.absent(),
|
||||
Value<String?> description = const Value.absent(),
|
||||
Value<String?> content = const Value.absent(),
|
||||
Value<int> visibility = const Value.absent(),
|
||||
Value<int> type = const Value.absent(),
|
||||
required DateTime lastModified,
|
||||
required String postData,
|
||||
Value<int> rowid = const Value.absent(),
|
||||
}) => PostDraftsCompanion.insert(
|
||||
id: id,
|
||||
post: post,
|
||||
title: title,
|
||||
description: description,
|
||||
content: content,
|
||||
visibility: visibility,
|
||||
type: type,
|
||||
lastModified: lastModified,
|
||||
postData: postData,
|
||||
rowid: rowid,
|
||||
),
|
||||
withReferenceMapper:
|
||||
|
@@ -128,14 +128,6 @@ class ArticleComposeScreen extends HookConsumerWidget {
|
||||
return null;
|
||||
}, []);
|
||||
|
||||
// Auto-save cleanup
|
||||
useEffect(() {
|
||||
return () {
|
||||
state.stopAutoSave();
|
||||
ComposeLogic.dispose(state);
|
||||
};
|
||||
}, [state]);
|
||||
|
||||
// Helper methods
|
||||
void showSettingsSheet() {
|
||||
showModalBottomSheet(
|
||||
@@ -182,6 +174,12 @@ class ArticleComposeScreen extends HookConsumerWidget {
|
||||
MarkdownTextContent(
|
||||
content: contentValue.text,
|
||||
textStyle: theme.textTheme.bodyMedium,
|
||||
attachments:
|
||||
state.attachments.value
|
||||
.where((e) => e.isOnCloud)
|
||||
.map((e) => e.data)
|
||||
.cast<SnCloudFile>()
|
||||
.toList(),
|
||||
),
|
||||
],
|
||||
);
|
||||
@@ -268,7 +266,7 @@ class ArticleComposeScreen extends HookConsumerWidget {
|
||||
child: KeyboardListener(
|
||||
focusNode: FocusNode(),
|
||||
onKeyEvent:
|
||||
(event) => _handleKeyPress(
|
||||
(event) => ComposeLogic.handleKeyPress(
|
||||
event,
|
||||
state,
|
||||
ref,
|
||||
@@ -511,38 +509,4 @@ class ArticleComposeScreen extends HookConsumerWidget {
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// Helper method to handle keyboard shortcuts
|
||||
void _handleKeyPress(
|
||||
KeyEvent event,
|
||||
ComposeState state,
|
||||
WidgetRef ref,
|
||||
BuildContext context, {
|
||||
SnPost? originalPost,
|
||||
}) {
|
||||
if (event is! RawKeyDownEvent) return;
|
||||
|
||||
final isPaste = event.logicalKey == LogicalKeyboardKey.keyV;
|
||||
final isSave = event.logicalKey == LogicalKeyboardKey.keyS;
|
||||
final isModifierPressed =
|
||||
HardwareKeyboard.instance.isMetaPressed ||
|
||||
HardwareKeyboard.instance.isControlPressed;
|
||||
final isSubmit = event.logicalKey == LogicalKeyboardKey.enter;
|
||||
|
||||
if (isPaste && isModifierPressed) {
|
||||
ComposeLogic.handlePaste(state);
|
||||
} else if (isSave && isModifierPressed) {
|
||||
ComposeLogic.saveDraft(ref, state);
|
||||
ComposeLogic.saveDraft(ref, state);
|
||||
} else if (isSubmit && isModifierPressed && !state.submitting.value) {
|
||||
ComposeLogic.performAction(
|
||||
ref,
|
||||
state,
|
||||
context,
|
||||
originalPost: originalPost,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Helper method to save article draft
|
||||
}
|
||||
|
@@ -39,8 +39,13 @@ class ComposeStorageNotifier extends _$ComposeStorageNotifier {
|
||||
await database.addPostDraft(
|
||||
PostDraftsCompanion(
|
||||
id: Value(updatedDraft.id),
|
||||
post: Value(jsonEncode(updatedDraft.toJson())),
|
||||
title: Value(updatedDraft.title),
|
||||
description: Value(updatedDraft.description),
|
||||
content: Value(updatedDraft.content),
|
||||
visibility: Value(updatedDraft.visibility),
|
||||
type: Value(updatedDraft.type),
|
||||
lastModified: Value(updatedDraft.updatedAt ?? DateTime.now()),
|
||||
postData: Value(jsonEncode(updatedDraft.toJson())),
|
||||
),
|
||||
);
|
||||
} catch (e) {
|
||||
|
@@ -7,7 +7,7 @@ part of 'compose_storage_db.dart';
|
||||
// **************************************************************************
|
||||
|
||||
String _$composeStorageNotifierHash() =>
|
||||
r'4ab4dce85d0a961f096dc3b11505f8f0964dee9d';
|
||||
r'8baf17aa06b6f69641c20645ba8a3dfe01c97f8c';
|
||||
|
||||
/// See also [ComposeStorageNotifier].
|
||||
@ProviderFor(ComposeStorageNotifier)
|
||||
|
@@ -173,10 +173,6 @@ class ComposeLogic {
|
||||
}
|
||||
|
||||
try {
|
||||
if (state._autoSaveTimer == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Upload any local attachments first
|
||||
final baseUrl = ref.watch(serverUrlProvider);
|
||||
final token = await getToken(ref.watch(tokenProvider));
|
||||
@@ -284,10 +280,6 @@ class ComposeLogic {
|
||||
}
|
||||
|
||||
try {
|
||||
if (state._autoSaveTimer == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final draft = SnPost(
|
||||
id: state.draftId,
|
||||
title: state.titleController.text,
|
||||
|
@@ -34,7 +34,7 @@ class ComposeToolbar extends HookConsumerWidget {
|
||||
}
|
||||
|
||||
void saveDraft() {
|
||||
ComposeLogic.saveDraft(ref, state);
|
||||
ComposeLogic.saveDraftManually(ref, state, context);
|
||||
}
|
||||
|
||||
void pickPoll() {
|
||||
|
@@ -16,138 +16,145 @@ class DraftManagerSheet extends HookConsumerWidget {
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final theme = Theme.of(context);
|
||||
final colorScheme = theme.colorScheme;
|
||||
final isLoading = useState(true);
|
||||
final searchController = useTextEditingController();
|
||||
final searchQuery = useState('');
|
||||
|
||||
final drafts = ref.watch(composeStorageNotifierProvider);
|
||||
|
||||
// Track loading state based on drafts being loaded
|
||||
useEffect(() {
|
||||
// Set loading to false after drafts are loaded
|
||||
// We consider drafts loaded when the provider has been initialized
|
||||
Future.microtask(() {
|
||||
if (isLoading.value) {
|
||||
isLoading.value = false;
|
||||
}
|
||||
});
|
||||
return null;
|
||||
}, [drafts]);
|
||||
// Search functionality
|
||||
final filteredDrafts = useMemoized(() {
|
||||
if (searchQuery.value.isEmpty) {
|
||||
return drafts.values.toList()
|
||||
..sort((a, b) => b.updatedAt!.compareTo(a.updatedAt!));
|
||||
}
|
||||
|
||||
final sortedDrafts = useMemoized(
|
||||
() {
|
||||
final draftList = drafts.values.toList();
|
||||
draftList.sort((a, b) => b.updatedAt!.compareTo(a.updatedAt!));
|
||||
return draftList;
|
||||
},
|
||||
[
|
||||
drafts.length,
|
||||
drafts.values.map((e) => e.updatedAt!.millisecondsSinceEpoch).join(),
|
||||
],
|
||||
);
|
||||
final query = searchQuery.value.toLowerCase();
|
||||
return drafts.values.where((draft) {
|
||||
return (draft.title?.toLowerCase().contains(query) ?? false) ||
|
||||
(draft.description?.toLowerCase().contains(query) ?? false) ||
|
||||
(draft.content?.toLowerCase().contains(query) ?? false);
|
||||
}).toList()
|
||||
..sort((a, b) => b.updatedAt!.compareTo(a.updatedAt!));
|
||||
}, [drafts, searchQuery.value]);
|
||||
|
||||
return SheetScaffold(
|
||||
titleText: 'drafts'.tr(),
|
||||
child:
|
||||
isLoading.value
|
||||
? const Center(child: CircularProgressIndicator())
|
||||
: Column(
|
||||
children: [
|
||||
if (sortedDrafts.isEmpty)
|
||||
Expanded(
|
||||
child: Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Icon(
|
||||
Symbols.draft,
|
||||
size: 64,
|
||||
color: colorScheme.onSurface.withOpacity(0.3),
|
||||
),
|
||||
const Gap(16),
|
||||
Text(
|
||||
'noDrafts'.tr(),
|
||||
style: theme.textTheme.bodyLarge?.copyWith(
|
||||
color: colorScheme.onSurface.withOpacity(0.6),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
else
|
||||
Expanded(
|
||||
child: ListView.builder(
|
||||
itemCount: sortedDrafts.length,
|
||||
itemBuilder: (context, index) {
|
||||
final draft = sortedDrafts[index];
|
||||
return _DraftItem(
|
||||
draft: draft,
|
||||
onTap: () {
|
||||
Navigator.of(context).pop();
|
||||
onDraftSelected?.call(draft.id);
|
||||
},
|
||||
onDelete: () async {
|
||||
await ref
|
||||
.read(composeStorageNotifierProvider.notifier)
|
||||
.deleteDraft(draft.id);
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
if (sortedDrafts.isNotEmpty) ...[
|
||||
const Divider(),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: OutlinedButton.icon(
|
||||
onPressed: () async {
|
||||
final confirmed = await showDialog<bool>(
|
||||
context: context,
|
||||
builder:
|
||||
(context) => AlertDialog(
|
||||
title: Text('clearAllDrafts'.tr()),
|
||||
content: Text(
|
||||
'clearAllDraftsConfirm'.tr(),
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed:
|
||||
() => Navigator.of(
|
||||
context,
|
||||
).pop(false),
|
||||
child: Text('cancel'.tr()),
|
||||
),
|
||||
TextButton(
|
||||
onPressed:
|
||||
() => Navigator.of(
|
||||
context,
|
||||
).pop(true),
|
||||
child: Text('confirm'.tr()),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
child: Column(
|
||||
children: [
|
||||
// Search bar
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: TextField(
|
||||
controller: searchController,
|
||||
decoration: InputDecoration(
|
||||
hintText: 'searchDrafts'.tr(),
|
||||
prefixIcon: const Icon(Symbols.search),
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
contentPadding: const EdgeInsets.symmetric(
|
||||
horizontal: 16,
|
||||
vertical: 12,
|
||||
),
|
||||
),
|
||||
onChanged: (value) => searchQuery.value = value,
|
||||
),
|
||||
),
|
||||
|
||||
if (confirmed == true) {
|
||||
await ref
|
||||
.read(
|
||||
composeStorageNotifierProvider.notifier,
|
||||
)
|
||||
.clearAllDrafts();
|
||||
}
|
||||
},
|
||||
icon: const Icon(Symbols.delete_sweep),
|
||||
label: Text('clearAll'.tr()),
|
||||
),
|
||||
),
|
||||
],
|
||||
// Drafts list
|
||||
if (filteredDrafts.isEmpty)
|
||||
Expanded(
|
||||
child: Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Icon(
|
||||
Symbols.draft,
|
||||
size: 64,
|
||||
color: colorScheme.onSurface.withOpacity(0.3),
|
||||
),
|
||||
const Gap(16),
|
||||
Text(
|
||||
searchQuery.value.isEmpty
|
||||
? 'noDrafts'.tr()
|
||||
: 'noSearchResults'.tr(),
|
||||
style: theme.textTheme.bodyLarge?.copyWith(
|
||||
color: colorScheme.onSurface.withOpacity(0.6),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
else
|
||||
Expanded(
|
||||
child: ListView.builder(
|
||||
itemCount: filteredDrafts.length,
|
||||
itemBuilder: (context, index) {
|
||||
final draft = filteredDrafts[index];
|
||||
return _DraftItem(
|
||||
draft: draft,
|
||||
onTap: () {
|
||||
Navigator.of(context).pop();
|
||||
onDraftSelected?.call(draft.id);
|
||||
},
|
||||
onDelete: () async {
|
||||
await ref
|
||||
.read(composeStorageNotifierProvider.notifier)
|
||||
.deleteDraft(draft.id);
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
|
||||
// Clear all button
|
||||
if (filteredDrafts.isNotEmpty) ...[
|
||||
const Divider(),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: OutlinedButton.icon(
|
||||
onPressed: () async {
|
||||
final confirmed = await showDialog<bool>(
|
||||
context: context,
|
||||
builder:
|
||||
(context) => AlertDialog(
|
||||
title: Text('clearAllDrafts'.tr()),
|
||||
content: Text('clearAllDraftsConfirm'.tr()),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed:
|
||||
() => Navigator.of(context).pop(false),
|
||||
child: Text('cancel'.tr()),
|
||||
),
|
||||
TextButton(
|
||||
onPressed:
|
||||
() => Navigator.of(context).pop(true),
|
||||
child: Text('confirm'.tr()),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
if (confirmed == true) {
|
||||
await ref
|
||||
.read(composeStorageNotifierProvider.notifier)
|
||||
.clearAllDrafts();
|
||||
}
|
||||
},
|
||||
icon: const Icon(Symbols.delete_sweep),
|
||||
label: Text('clearAll'.tr()),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user