Compare commits

..

19 Commits

Author SHA1 Message Date
c9727e92b8 🚀 Launch 3.2.0+132 2025-09-10 01:32:38 +08:00
9b8768061d Award history 2025-09-10 01:23:50 +08:00
0949f0da54 ⬆️ Upgrade flutter and deps 2025-09-09 23:34:31 +08:00
215ca705ac Delete the poll 2025-09-09 01:03:42 +08:00
03457af04a 💄 Optimize poll editor 2025-09-09 01:01:28 +08:00
73c6a1febf Show account on poll feedback
💄 Optimize poll feedback
2025-09-09 01:00:21 +08:00
ba8d30bcde 🐛 Fix order didn't paid successfully 2025-09-09 00:45:31 +08:00
8449658b47 RPC now set remote status 2025-09-09 00:27:26 +08:00
c7f417234e Show awarded score 2025-09-08 23:55:50 +08:00
6c847ee1e1 👽 Remove order handle in stellar program purchase 2025-09-08 22:50:32 +08:00
18ad4d376e 💄 The payment now no longer auto procced 2025-09-08 22:48:46 +08:00
c4d5ba5c9d 🐛 Fix inline attachment didn't render properly 2025-09-08 22:43:41 +08:00
1069669049 🐛 Post visibility not readable 2025-09-08 22:26:44 +08:00
aa648fec62 Reworked post draft 2025-09-08 22:25:54 +08:00
541900673a 🐛 Disable unix socks completely on macOS 2025-09-08 21:49:23 +08:00
265502ffd0 🐛 Disable ipc rpc server on macos 2025-09-08 21:34:03 +08:00
3bd79350d1 🧱 Activity RPC server 2025-09-08 20:57:27 +08:00
5294d1fb23 💄 Make sure cloud file background fill entire space 2025-09-08 19:29:01 +08:00
ec1269dcf1 💄 Optimize check in widget and add today's countdown 2025-09-08 19:27:30 +08:00
35 changed files with 2372 additions and 501 deletions

View File

@@ -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",

View File

@@ -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};

View File

@@ -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();
}
}

View File

@@ -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:

View File

@@ -1,4 +1,5 @@
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:island/models/account.dart';
import 'package:island/models/publisher.dart';
part 'poll.freezed.dart';
@@ -101,6 +102,7 @@ sealed class SnPollAnswer with _$SnPollAnswer {
required DateTime createdAt,
required DateTime updatedAt,
required DateTime? deletedAt,
SnAccount? account,
}) = _SnPollAnswer;
factory SnPollAnswer.fromJson(Map<String, dynamic> json) =>

View File

@@ -1187,7 +1187,7 @@ as int,
/// @nodoc
mixin _$SnPollAnswer {
String get id; Map<String, dynamic> get answer; String get accountId; String get pollId; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt;
String get id; Map<String, dynamic> get answer; String get accountId; String get pollId; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt; SnAccount? get account;
/// Create a copy of SnPollAnswer
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@@ -1200,16 +1200,16 @@ $SnPollAnswerCopyWith<SnPollAnswer> get copyWith => _$SnPollAnswerCopyWithImpl<S
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnPollAnswer&&(identical(other.id, id) || other.id == id)&&const DeepCollectionEquality().equals(other.answer, answer)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.pollId, pollId) || other.pollId == pollId)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt));
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnPollAnswer&&(identical(other.id, id) || other.id == id)&&const DeepCollectionEquality().equals(other.answer, answer)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.pollId, pollId) || other.pollId == pollId)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)&&(identical(other.account, account) || other.account == account));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType,id,const DeepCollectionEquality().hash(answer),accountId,pollId,createdAt,updatedAt,deletedAt);
int get hashCode => Object.hash(runtimeType,id,const DeepCollectionEquality().hash(answer),accountId,pollId,createdAt,updatedAt,deletedAt,account);
@override
String toString() {
return 'SnPollAnswer(id: $id, answer: $answer, accountId: $accountId, pollId: $pollId, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
return 'SnPollAnswer(id: $id, answer: $answer, accountId: $accountId, pollId: $pollId, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, account: $account)';
}
@@ -1220,11 +1220,11 @@ abstract mixin class $SnPollAnswerCopyWith<$Res> {
factory $SnPollAnswerCopyWith(SnPollAnswer value, $Res Function(SnPollAnswer) _then) = _$SnPollAnswerCopyWithImpl;
@useResult
$Res call({
String id, Map<String, dynamic> answer, String accountId, String pollId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
String id, Map<String, dynamic> answer, String accountId, String pollId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, SnAccount? account
});
$SnAccountCopyWith<$Res>? get account;
}
/// @nodoc
@@ -1237,7 +1237,7 @@ class _$SnPollAnswerCopyWithImpl<$Res>
/// Create a copy of SnPollAnswer
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? answer = null,Object? accountId = null,Object? pollId = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? answer = null,Object? accountId = null,Object? pollId = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,Object? account = freezed,}) {
return _then(_self.copyWith(
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
as String,answer: null == answer ? _self.answer : answer // ignore: cast_nullable_to_non_nullable
@@ -1246,10 +1246,23 @@ as String,pollId: null == pollId ? _self.pollId : pollId // ignore: cast_nullabl
as String,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
as DateTime?,
as DateTime?,account: freezed == account ? _self.account : account // ignore: cast_nullable_to_non_nullable
as SnAccount?,
));
}
/// Create a copy of SnPollAnswer
/// with the given fields replaced by the non-null parameter values.
@override
@pragma('vm:prefer-inline')
$SnAccountCopyWith<$Res>? get account {
if (_self.account == null) {
return null;
}
return $SnAccountCopyWith<$Res>(_self.account!, (value) {
return _then(_self.copyWith(account: value));
});
}
}
@@ -1328,10 +1341,10 @@ return $default(_that);case _:
/// }
/// ```
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String id, Map<String, dynamic> answer, String accountId, String pollId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,{required TResult orElse(),}) {final _that = this;
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String id, Map<String, dynamic> answer, String accountId, String pollId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, SnAccount? account)? $default,{required TResult orElse(),}) {final _that = this;
switch (_that) {
case _SnPollAnswer() when $default != null:
return $default(_that.id,_that.answer,_that.accountId,_that.pollId,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
return $default(_that.id,_that.answer,_that.accountId,_that.pollId,_that.createdAt,_that.updatedAt,_that.deletedAt,_that.account);case _:
return orElse();
}
@@ -1349,10 +1362,10 @@ return $default(_that.id,_that.answer,_that.accountId,_that.pollId,_that.created
/// }
/// ```
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String id, Map<String, dynamic> answer, String accountId, String pollId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt) $default,) {final _that = this;
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String id, Map<String, dynamic> answer, String accountId, String pollId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, SnAccount? account) $default,) {final _that = this;
switch (_that) {
case _SnPollAnswer():
return $default(_that.id,_that.answer,_that.accountId,_that.pollId,_that.createdAt,_that.updatedAt,_that.deletedAt);}
return $default(_that.id,_that.answer,_that.accountId,_that.pollId,_that.createdAt,_that.updatedAt,_that.deletedAt,_that.account);}
}
/// A variant of `when` that fallback to returning `null`
///
@@ -1366,10 +1379,10 @@ return $default(_that.id,_that.answer,_that.accountId,_that.pollId,_that.created
/// }
/// ```
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String id, Map<String, dynamic> answer, String accountId, String pollId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,) {final _that = this;
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String id, Map<String, dynamic> answer, String accountId, String pollId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, SnAccount? account)? $default,) {final _that = this;
switch (_that) {
case _SnPollAnswer() when $default != null:
return $default(_that.id,_that.answer,_that.accountId,_that.pollId,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
return $default(_that.id,_that.answer,_that.accountId,_that.pollId,_that.createdAt,_that.updatedAt,_that.deletedAt,_that.account);case _:
return null;
}
@@ -1381,7 +1394,7 @@ return $default(_that.id,_that.answer,_that.accountId,_that.pollId,_that.created
@JsonSerializable()
class _SnPollAnswer implements SnPollAnswer {
const _SnPollAnswer({required this.id, required final Map<String, dynamic> answer, required this.accountId, required this.pollId, required this.createdAt, required this.updatedAt, required this.deletedAt}): _answer = answer;
const _SnPollAnswer({required this.id, required final Map<String, dynamic> answer, required this.accountId, required this.pollId, required this.createdAt, required this.updatedAt, required this.deletedAt, this.account}): _answer = answer;
factory _SnPollAnswer.fromJson(Map<String, dynamic> json) => _$SnPollAnswerFromJson(json);
@override final String id;
@@ -1397,6 +1410,7 @@ class _SnPollAnswer implements SnPollAnswer {
@override final DateTime createdAt;
@override final DateTime updatedAt;
@override final DateTime? deletedAt;
@override final SnAccount? account;
/// Create a copy of SnPollAnswer
/// with the given fields replaced by the non-null parameter values.
@@ -1411,16 +1425,16 @@ Map<String, dynamic> toJson() {
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnPollAnswer&&(identical(other.id, id) || other.id == id)&&const DeepCollectionEquality().equals(other._answer, _answer)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.pollId, pollId) || other.pollId == pollId)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt));
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnPollAnswer&&(identical(other.id, id) || other.id == id)&&const DeepCollectionEquality().equals(other._answer, _answer)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.pollId, pollId) || other.pollId == pollId)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)&&(identical(other.account, account) || other.account == account));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType,id,const DeepCollectionEquality().hash(_answer),accountId,pollId,createdAt,updatedAt,deletedAt);
int get hashCode => Object.hash(runtimeType,id,const DeepCollectionEquality().hash(_answer),accountId,pollId,createdAt,updatedAt,deletedAt,account);
@override
String toString() {
return 'SnPollAnswer(id: $id, answer: $answer, accountId: $accountId, pollId: $pollId, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
return 'SnPollAnswer(id: $id, answer: $answer, accountId: $accountId, pollId: $pollId, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, account: $account)';
}
@@ -1431,11 +1445,11 @@ abstract mixin class _$SnPollAnswerCopyWith<$Res> implements $SnPollAnswerCopyWi
factory _$SnPollAnswerCopyWith(_SnPollAnswer value, $Res Function(_SnPollAnswer) _then) = __$SnPollAnswerCopyWithImpl;
@override @useResult
$Res call({
String id, Map<String, dynamic> answer, String accountId, String pollId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
String id, Map<String, dynamic> answer, String accountId, String pollId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, SnAccount? account
});
@override $SnAccountCopyWith<$Res>? get account;
}
/// @nodoc
@@ -1448,7 +1462,7 @@ class __$SnPollAnswerCopyWithImpl<$Res>
/// Create a copy of SnPollAnswer
/// with the given fields replaced by the non-null parameter values.
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? answer = null,Object? accountId = null,Object? pollId = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? answer = null,Object? accountId = null,Object? pollId = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,Object? account = freezed,}) {
return _then(_SnPollAnswer(
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
as String,answer: null == answer ? _self._answer : answer // ignore: cast_nullable_to_non_nullable
@@ -1457,11 +1471,24 @@ as String,pollId: null == pollId ? _self.pollId : pollId // ignore: cast_nullabl
as String,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
as DateTime?,
as DateTime?,account: freezed == account ? _self.account : account // ignore: cast_nullable_to_non_nullable
as SnAccount?,
));
}
/// Create a copy of SnPollAnswer
/// with the given fields replaced by the non-null parameter values.
@override
@pragma('vm:prefer-inline')
$SnAccountCopyWith<$Res>? get account {
if (_self.account == null) {
return null;
}
return $SnAccountCopyWith<$Res>(_self.account!, (value) {
return _then(_self.copyWith(account: value));
});
}
}
// dart format on

View File

@@ -144,6 +144,10 @@ _SnPollAnswer _$SnPollAnswerFromJson(Map<String, dynamic> json) =>
json['deleted_at'] == null
? null
: DateTime.parse(json['deleted_at'] as String),
account:
json['account'] == null
? null
: SnAccount.fromJson(json['account'] as Map<String, dynamic>),
);
Map<String, dynamic> _$SnPollAnswerToJson(_SnPollAnswer instance) =>
@@ -155,4 +159,5 @@ Map<String, dynamic> _$SnPollAnswerToJson(_SnPollAnswer instance) =>
'created_at': instance.createdAt.toIso8601String(),
'updated_at': instance.updatedAt.toIso8601String(),
'deleted_at': instance.deletedAt?.toIso8601String(),
'account': instance.account?.toJson(),
};

View File

@@ -28,6 +28,7 @@ sealed class SnPost with _$SnPost {
@Default(0) int upvotes,
@Default(0) int downvotes,
@Default(0) int repliesCount,
@Default(0) int awardedScore,
int? pinMode,
String? threadedPostId,
SnPost? threadedPost,
@@ -123,3 +124,21 @@ sealed class SnPostEmbedView with _$SnPostEmbedView {
factory SnPostEmbedView.fromJson(Map<String, dynamic> json) =>
_$SnPostEmbedViewFromJson(json);
}
@freezed
sealed class SnPostAward with _$SnPostAward {
const factory SnPostAward({
required String id,
required double amount,
required int attitude,
String? message,
required String postId,
required String accountId,
@Default(null) DateTime? createdAt,
@Default(null) DateTime? updatedAt,
DateTime? deletedAt,
}) = _SnPostAward;
factory SnPostAward.fromJson(Map<String, dynamic> json) =>
_$SnPostAwardFromJson(json);
}

View File

@@ -15,7 +15,7 @@ T _$identity<T>(T value) => value;
/// @nodoc
mixin _$SnPost {
String get id; String? get title; String? get description; String? get language; DateTime? get editedAt; DateTime? get publishedAt; int get visibility; String? get content; String? get slug; int get type; Map<String, dynamic>? get meta; SnPostEmbedView? get embedView; int get viewsUnique; int get viewsTotal; int get upvotes; int get downvotes; int get repliesCount; int? get pinMode; String? get threadedPostId; SnPost? get threadedPost; String? get repliedPostId; SnPost? get repliedPost; String? get forwardedPostId; SnPost? get forwardedPost; String? get realmId; SnRealm? get realm; List<SnCloudFile> get attachments; SnPublisher get publisher; Map<String, int> get reactionsCount; Map<String, bool> get reactionsMade; List<dynamic> get reactions; List<SnPostTag> get tags; List<SnPostCategory> get categories; List<dynamic> get collections; DateTime? get createdAt; DateTime? get updatedAt; DateTime? get deletedAt; bool get isTruncated;
String get id; String? get title; String? get description; String? get language; DateTime? get editedAt; DateTime? get publishedAt; int get visibility; String? get content; String? get slug; int get type; Map<String, dynamic>? get meta; SnPostEmbedView? get embedView; int get viewsUnique; int get viewsTotal; int get upvotes; int get downvotes; int get repliesCount; int get awardedScore; int? get pinMode; String? get threadedPostId; SnPost? get threadedPost; String? get repliedPostId; SnPost? get repliedPost; String? get forwardedPostId; SnPost? get forwardedPost; String? get realmId; SnRealm? get realm; List<SnCloudFile> get attachments; SnPublisher get publisher; Map<String, int> get reactionsCount; Map<String, bool> get reactionsMade; List<dynamic> get reactions; List<SnPostTag> get tags; List<SnPostCategory> get categories; List<dynamic> get collections; DateTime? get createdAt; DateTime? get updatedAt; DateTime? get deletedAt; bool get isTruncated;
/// Create a copy of SnPost
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@@ -28,16 +28,16 @@ $SnPostCopyWith<SnPost> get copyWith => _$SnPostCopyWithImpl<SnPost>(this as SnP
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnPost&&(identical(other.id, id) || other.id == id)&&(identical(other.title, title) || other.title == title)&&(identical(other.description, description) || other.description == description)&&(identical(other.language, language) || other.language == language)&&(identical(other.editedAt, editedAt) || other.editedAt == editedAt)&&(identical(other.publishedAt, publishedAt) || other.publishedAt == publishedAt)&&(identical(other.visibility, visibility) || other.visibility == visibility)&&(identical(other.content, content) || other.content == content)&&(identical(other.slug, slug) || other.slug == slug)&&(identical(other.type, type) || other.type == type)&&const DeepCollectionEquality().equals(other.meta, meta)&&(identical(other.embedView, embedView) || other.embedView == embedView)&&(identical(other.viewsUnique, viewsUnique) || other.viewsUnique == viewsUnique)&&(identical(other.viewsTotal, viewsTotal) || other.viewsTotal == viewsTotal)&&(identical(other.upvotes, upvotes) || other.upvotes == upvotes)&&(identical(other.downvotes, downvotes) || other.downvotes == downvotes)&&(identical(other.repliesCount, repliesCount) || other.repliesCount == repliesCount)&&(identical(other.pinMode, pinMode) || other.pinMode == pinMode)&&(identical(other.threadedPostId, threadedPostId) || other.threadedPostId == threadedPostId)&&(identical(other.threadedPost, threadedPost) || other.threadedPost == threadedPost)&&(identical(other.repliedPostId, repliedPostId) || other.repliedPostId == repliedPostId)&&(identical(other.repliedPost, repliedPost) || other.repliedPost == repliedPost)&&(identical(other.forwardedPostId, forwardedPostId) || other.forwardedPostId == forwardedPostId)&&(identical(other.forwardedPost, forwardedPost) || other.forwardedPost == forwardedPost)&&(identical(other.realmId, realmId) || other.realmId == realmId)&&(identical(other.realm, realm) || other.realm == realm)&&const DeepCollectionEquality().equals(other.attachments, attachments)&&(identical(other.publisher, publisher) || other.publisher == publisher)&&const DeepCollectionEquality().equals(other.reactionsCount, reactionsCount)&&const DeepCollectionEquality().equals(other.reactionsMade, reactionsMade)&&const DeepCollectionEquality().equals(other.reactions, reactions)&&const DeepCollectionEquality().equals(other.tags, tags)&&const DeepCollectionEquality().equals(other.categories, categories)&&const DeepCollectionEquality().equals(other.collections, collections)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)&&(identical(other.isTruncated, isTruncated) || other.isTruncated == isTruncated));
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnPost&&(identical(other.id, id) || other.id == id)&&(identical(other.title, title) || other.title == title)&&(identical(other.description, description) || other.description == description)&&(identical(other.language, language) || other.language == language)&&(identical(other.editedAt, editedAt) || other.editedAt == editedAt)&&(identical(other.publishedAt, publishedAt) || other.publishedAt == publishedAt)&&(identical(other.visibility, visibility) || other.visibility == visibility)&&(identical(other.content, content) || other.content == content)&&(identical(other.slug, slug) || other.slug == slug)&&(identical(other.type, type) || other.type == type)&&const DeepCollectionEquality().equals(other.meta, meta)&&(identical(other.embedView, embedView) || other.embedView == embedView)&&(identical(other.viewsUnique, viewsUnique) || other.viewsUnique == viewsUnique)&&(identical(other.viewsTotal, viewsTotal) || other.viewsTotal == viewsTotal)&&(identical(other.upvotes, upvotes) || other.upvotes == upvotes)&&(identical(other.downvotes, downvotes) || other.downvotes == downvotes)&&(identical(other.repliesCount, repliesCount) || other.repliesCount == repliesCount)&&(identical(other.awardedScore, awardedScore) || other.awardedScore == awardedScore)&&(identical(other.pinMode, pinMode) || other.pinMode == pinMode)&&(identical(other.threadedPostId, threadedPostId) || other.threadedPostId == threadedPostId)&&(identical(other.threadedPost, threadedPost) || other.threadedPost == threadedPost)&&(identical(other.repliedPostId, repliedPostId) || other.repliedPostId == repliedPostId)&&(identical(other.repliedPost, repliedPost) || other.repliedPost == repliedPost)&&(identical(other.forwardedPostId, forwardedPostId) || other.forwardedPostId == forwardedPostId)&&(identical(other.forwardedPost, forwardedPost) || other.forwardedPost == forwardedPost)&&(identical(other.realmId, realmId) || other.realmId == realmId)&&(identical(other.realm, realm) || other.realm == realm)&&const DeepCollectionEquality().equals(other.attachments, attachments)&&(identical(other.publisher, publisher) || other.publisher == publisher)&&const DeepCollectionEquality().equals(other.reactionsCount, reactionsCount)&&const DeepCollectionEquality().equals(other.reactionsMade, reactionsMade)&&const DeepCollectionEquality().equals(other.reactions, reactions)&&const DeepCollectionEquality().equals(other.tags, tags)&&const DeepCollectionEquality().equals(other.categories, categories)&&const DeepCollectionEquality().equals(other.collections, collections)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)&&(identical(other.isTruncated, isTruncated) || other.isTruncated == isTruncated));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hashAll([runtimeType,id,title,description,language,editedAt,publishedAt,visibility,content,slug,type,const DeepCollectionEquality().hash(meta),embedView,viewsUnique,viewsTotal,upvotes,downvotes,repliesCount,pinMode,threadedPostId,threadedPost,repliedPostId,repliedPost,forwardedPostId,forwardedPost,realmId,realm,const DeepCollectionEquality().hash(attachments),publisher,const DeepCollectionEquality().hash(reactionsCount),const DeepCollectionEquality().hash(reactionsMade),const DeepCollectionEquality().hash(reactions),const DeepCollectionEquality().hash(tags),const DeepCollectionEquality().hash(categories),const DeepCollectionEquality().hash(collections),createdAt,updatedAt,deletedAt,isTruncated]);
int get hashCode => Object.hashAll([runtimeType,id,title,description,language,editedAt,publishedAt,visibility,content,slug,type,const DeepCollectionEquality().hash(meta),embedView,viewsUnique,viewsTotal,upvotes,downvotes,repliesCount,awardedScore,pinMode,threadedPostId,threadedPost,repliedPostId,repliedPost,forwardedPostId,forwardedPost,realmId,realm,const DeepCollectionEquality().hash(attachments),publisher,const DeepCollectionEquality().hash(reactionsCount),const DeepCollectionEquality().hash(reactionsMade),const DeepCollectionEquality().hash(reactions),const DeepCollectionEquality().hash(tags),const DeepCollectionEquality().hash(categories),const DeepCollectionEquality().hash(collections),createdAt,updatedAt,deletedAt,isTruncated]);
@override
String toString() {
return 'SnPost(id: $id, title: $title, description: $description, language: $language, editedAt: $editedAt, publishedAt: $publishedAt, visibility: $visibility, content: $content, slug: $slug, type: $type, meta: $meta, embedView: $embedView, viewsUnique: $viewsUnique, viewsTotal: $viewsTotal, upvotes: $upvotes, downvotes: $downvotes, repliesCount: $repliesCount, pinMode: $pinMode, threadedPostId: $threadedPostId, threadedPost: $threadedPost, repliedPostId: $repliedPostId, repliedPost: $repliedPost, forwardedPostId: $forwardedPostId, forwardedPost: $forwardedPost, realmId: $realmId, realm: $realm, attachments: $attachments, publisher: $publisher, reactionsCount: $reactionsCount, reactionsMade: $reactionsMade, reactions: $reactions, tags: $tags, categories: $categories, collections: $collections, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, isTruncated: $isTruncated)';
return 'SnPost(id: $id, title: $title, description: $description, language: $language, editedAt: $editedAt, publishedAt: $publishedAt, visibility: $visibility, content: $content, slug: $slug, type: $type, meta: $meta, embedView: $embedView, viewsUnique: $viewsUnique, viewsTotal: $viewsTotal, upvotes: $upvotes, downvotes: $downvotes, repliesCount: $repliesCount, awardedScore: $awardedScore, pinMode: $pinMode, threadedPostId: $threadedPostId, threadedPost: $threadedPost, repliedPostId: $repliedPostId, repliedPost: $repliedPost, forwardedPostId: $forwardedPostId, forwardedPost: $forwardedPost, realmId: $realmId, realm: $realm, attachments: $attachments, publisher: $publisher, reactionsCount: $reactionsCount, reactionsMade: $reactionsMade, reactions: $reactions, tags: $tags, categories: $categories, collections: $collections, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, isTruncated: $isTruncated)';
}
@@ -48,7 +48,7 @@ abstract mixin class $SnPostCopyWith<$Res> {
factory $SnPostCopyWith(SnPost value, $Res Function(SnPost) _then) = _$SnPostCopyWithImpl;
@useResult
$Res call({
String id, String? title, String? description, String? language, DateTime? editedAt, DateTime? publishedAt, int visibility, String? content, String? slug, int type, Map<String, dynamic>? meta, SnPostEmbedView? embedView, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, int? pinMode, String? threadedPostId, SnPost? threadedPost, String? repliedPostId, SnPost? repliedPost, String? forwardedPostId, SnPost? forwardedPost, String? realmId, SnRealm? realm, List<SnCloudFile> attachments, SnPublisher publisher, Map<String, int> reactionsCount, Map<String, bool> reactionsMade, List<dynamic> reactions, List<SnPostTag> tags, List<SnPostCategory> categories, List<dynamic> collections, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, bool isTruncated
String id, String? title, String? description, String? language, DateTime? editedAt, DateTime? publishedAt, int visibility, String? content, String? slug, int type, Map<String, dynamic>? meta, SnPostEmbedView? embedView, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, int awardedScore, int? pinMode, String? threadedPostId, SnPost? threadedPost, String? repliedPostId, SnPost? repliedPost, String? forwardedPostId, SnPost? forwardedPost, String? realmId, SnRealm? realm, List<SnCloudFile> attachments, SnPublisher publisher, Map<String, int> reactionsCount, Map<String, bool> reactionsMade, List<dynamic> reactions, List<SnPostTag> tags, List<SnPostCategory> categories, List<dynamic> collections, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, bool isTruncated
});
@@ -65,7 +65,7 @@ class _$SnPostCopyWithImpl<$Res>
/// Create a copy of SnPost
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? title = freezed,Object? description = freezed,Object? language = freezed,Object? editedAt = freezed,Object? publishedAt = freezed,Object? visibility = null,Object? content = freezed,Object? slug = freezed,Object? type = null,Object? meta = freezed,Object? embedView = freezed,Object? viewsUnique = null,Object? viewsTotal = null,Object? upvotes = null,Object? downvotes = null,Object? repliesCount = null,Object? pinMode = freezed,Object? threadedPostId = freezed,Object? threadedPost = freezed,Object? repliedPostId = freezed,Object? repliedPost = freezed,Object? forwardedPostId = freezed,Object? forwardedPost = freezed,Object? realmId = freezed,Object? realm = freezed,Object? attachments = null,Object? publisher = null,Object? reactionsCount = null,Object? reactionsMade = null,Object? reactions = null,Object? tags = null,Object? categories = null,Object? collections = null,Object? createdAt = freezed,Object? updatedAt = freezed,Object? deletedAt = freezed,Object? isTruncated = null,}) {
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? title = freezed,Object? description = freezed,Object? language = freezed,Object? editedAt = freezed,Object? publishedAt = freezed,Object? visibility = null,Object? content = freezed,Object? slug = freezed,Object? type = null,Object? meta = freezed,Object? embedView = freezed,Object? viewsUnique = null,Object? viewsTotal = null,Object? upvotes = null,Object? downvotes = null,Object? repliesCount = null,Object? awardedScore = null,Object? pinMode = freezed,Object? threadedPostId = freezed,Object? threadedPost = freezed,Object? repliedPostId = freezed,Object? repliedPost = freezed,Object? forwardedPostId = freezed,Object? forwardedPost = freezed,Object? realmId = freezed,Object? realm = freezed,Object? attachments = null,Object? publisher = null,Object? reactionsCount = null,Object? reactionsMade = null,Object? reactions = null,Object? tags = null,Object? categories = null,Object? collections = null,Object? createdAt = freezed,Object? updatedAt = freezed,Object? deletedAt = freezed,Object? isTruncated = null,}) {
return _then(_self.copyWith(
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
as String,title: freezed == title ? _self.title : title // ignore: cast_nullable_to_non_nullable
@@ -84,6 +84,7 @@ as int,viewsTotal: null == viewsTotal ? _self.viewsTotal : viewsTotal // ignore:
as int,upvotes: null == upvotes ? _self.upvotes : upvotes // ignore: cast_nullable_to_non_nullable
as int,downvotes: null == downvotes ? _self.downvotes : downvotes // ignore: cast_nullable_to_non_nullable
as int,repliesCount: null == repliesCount ? _self.repliesCount : repliesCount // ignore: cast_nullable_to_non_nullable
as int,awardedScore: null == awardedScore ? _self.awardedScore : awardedScore // ignore: cast_nullable_to_non_nullable
as int,pinMode: freezed == pinMode ? _self.pinMode : pinMode // ignore: cast_nullable_to_non_nullable
as int?,threadedPostId: freezed == threadedPostId ? _self.threadedPostId : threadedPostId // ignore: cast_nullable_to_non_nullable
as String?,threadedPost: freezed == threadedPost ? _self.threadedPost : threadedPost // ignore: cast_nullable_to_non_nullable
@@ -256,10 +257,10 @@ return $default(_that);case _:
/// }
/// ```
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String id, String? title, String? description, String? language, DateTime? editedAt, DateTime? publishedAt, int visibility, String? content, String? slug, int type, Map<String, dynamic>? meta, SnPostEmbedView? embedView, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, int? pinMode, String? threadedPostId, SnPost? threadedPost, String? repliedPostId, SnPost? repliedPost, String? forwardedPostId, SnPost? forwardedPost, String? realmId, SnRealm? realm, List<SnCloudFile> attachments, SnPublisher publisher, Map<String, int> reactionsCount, Map<String, bool> reactionsMade, List<dynamic> reactions, List<SnPostTag> tags, List<SnPostCategory> categories, List<dynamic> collections, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, bool isTruncated)? $default,{required TResult orElse(),}) {final _that = this;
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String id, String? title, String? description, String? language, DateTime? editedAt, DateTime? publishedAt, int visibility, String? content, String? slug, int type, Map<String, dynamic>? meta, SnPostEmbedView? embedView, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, int awardedScore, int? pinMode, String? threadedPostId, SnPost? threadedPost, String? repliedPostId, SnPost? repliedPost, String? forwardedPostId, SnPost? forwardedPost, String? realmId, SnRealm? realm, List<SnCloudFile> attachments, SnPublisher publisher, Map<String, int> reactionsCount, Map<String, bool> reactionsMade, List<dynamic> reactions, List<SnPostTag> tags, List<SnPostCategory> categories, List<dynamic> collections, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, bool isTruncated)? $default,{required TResult orElse(),}) {final _that = this;
switch (_that) {
case _SnPost() when $default != null:
return $default(_that.id,_that.title,_that.description,_that.language,_that.editedAt,_that.publishedAt,_that.visibility,_that.content,_that.slug,_that.type,_that.meta,_that.embedView,_that.viewsUnique,_that.viewsTotal,_that.upvotes,_that.downvotes,_that.repliesCount,_that.pinMode,_that.threadedPostId,_that.threadedPost,_that.repliedPostId,_that.repliedPost,_that.forwardedPostId,_that.forwardedPost,_that.realmId,_that.realm,_that.attachments,_that.publisher,_that.reactionsCount,_that.reactionsMade,_that.reactions,_that.tags,_that.categories,_that.collections,_that.createdAt,_that.updatedAt,_that.deletedAt,_that.isTruncated);case _:
return $default(_that.id,_that.title,_that.description,_that.language,_that.editedAt,_that.publishedAt,_that.visibility,_that.content,_that.slug,_that.type,_that.meta,_that.embedView,_that.viewsUnique,_that.viewsTotal,_that.upvotes,_that.downvotes,_that.repliesCount,_that.awardedScore,_that.pinMode,_that.threadedPostId,_that.threadedPost,_that.repliedPostId,_that.repliedPost,_that.forwardedPostId,_that.forwardedPost,_that.realmId,_that.realm,_that.attachments,_that.publisher,_that.reactionsCount,_that.reactionsMade,_that.reactions,_that.tags,_that.categories,_that.collections,_that.createdAt,_that.updatedAt,_that.deletedAt,_that.isTruncated);case _:
return orElse();
}
@@ -277,10 +278,10 @@ return $default(_that.id,_that.title,_that.description,_that.language,_that.edit
/// }
/// ```
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String id, String? title, String? description, String? language, DateTime? editedAt, DateTime? publishedAt, int visibility, String? content, String? slug, int type, Map<String, dynamic>? meta, SnPostEmbedView? embedView, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, int? pinMode, String? threadedPostId, SnPost? threadedPost, String? repliedPostId, SnPost? repliedPost, String? forwardedPostId, SnPost? forwardedPost, String? realmId, SnRealm? realm, List<SnCloudFile> attachments, SnPublisher publisher, Map<String, int> reactionsCount, Map<String, bool> reactionsMade, List<dynamic> reactions, List<SnPostTag> tags, List<SnPostCategory> categories, List<dynamic> collections, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, bool isTruncated) $default,) {final _that = this;
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String id, String? title, String? description, String? language, DateTime? editedAt, DateTime? publishedAt, int visibility, String? content, String? slug, int type, Map<String, dynamic>? meta, SnPostEmbedView? embedView, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, int awardedScore, int? pinMode, String? threadedPostId, SnPost? threadedPost, String? repliedPostId, SnPost? repliedPost, String? forwardedPostId, SnPost? forwardedPost, String? realmId, SnRealm? realm, List<SnCloudFile> attachments, SnPublisher publisher, Map<String, int> reactionsCount, Map<String, bool> reactionsMade, List<dynamic> reactions, List<SnPostTag> tags, List<SnPostCategory> categories, List<dynamic> collections, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, bool isTruncated) $default,) {final _that = this;
switch (_that) {
case _SnPost():
return $default(_that.id,_that.title,_that.description,_that.language,_that.editedAt,_that.publishedAt,_that.visibility,_that.content,_that.slug,_that.type,_that.meta,_that.embedView,_that.viewsUnique,_that.viewsTotal,_that.upvotes,_that.downvotes,_that.repliesCount,_that.pinMode,_that.threadedPostId,_that.threadedPost,_that.repliedPostId,_that.repliedPost,_that.forwardedPostId,_that.forwardedPost,_that.realmId,_that.realm,_that.attachments,_that.publisher,_that.reactionsCount,_that.reactionsMade,_that.reactions,_that.tags,_that.categories,_that.collections,_that.createdAt,_that.updatedAt,_that.deletedAt,_that.isTruncated);}
return $default(_that.id,_that.title,_that.description,_that.language,_that.editedAt,_that.publishedAt,_that.visibility,_that.content,_that.slug,_that.type,_that.meta,_that.embedView,_that.viewsUnique,_that.viewsTotal,_that.upvotes,_that.downvotes,_that.repliesCount,_that.awardedScore,_that.pinMode,_that.threadedPostId,_that.threadedPost,_that.repliedPostId,_that.repliedPost,_that.forwardedPostId,_that.forwardedPost,_that.realmId,_that.realm,_that.attachments,_that.publisher,_that.reactionsCount,_that.reactionsMade,_that.reactions,_that.tags,_that.categories,_that.collections,_that.createdAt,_that.updatedAt,_that.deletedAt,_that.isTruncated);}
}
/// A variant of `when` that fallback to returning `null`
///
@@ -294,10 +295,10 @@ return $default(_that.id,_that.title,_that.description,_that.language,_that.edit
/// }
/// ```
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String id, String? title, String? description, String? language, DateTime? editedAt, DateTime? publishedAt, int visibility, String? content, String? slug, int type, Map<String, dynamic>? meta, SnPostEmbedView? embedView, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, int? pinMode, String? threadedPostId, SnPost? threadedPost, String? repliedPostId, SnPost? repliedPost, String? forwardedPostId, SnPost? forwardedPost, String? realmId, SnRealm? realm, List<SnCloudFile> attachments, SnPublisher publisher, Map<String, int> reactionsCount, Map<String, bool> reactionsMade, List<dynamic> reactions, List<SnPostTag> tags, List<SnPostCategory> categories, List<dynamic> collections, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, bool isTruncated)? $default,) {final _that = this;
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String id, String? title, String? description, String? language, DateTime? editedAt, DateTime? publishedAt, int visibility, String? content, String? slug, int type, Map<String, dynamic>? meta, SnPostEmbedView? embedView, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, int awardedScore, int? pinMode, String? threadedPostId, SnPost? threadedPost, String? repliedPostId, SnPost? repliedPost, String? forwardedPostId, SnPost? forwardedPost, String? realmId, SnRealm? realm, List<SnCloudFile> attachments, SnPublisher publisher, Map<String, int> reactionsCount, Map<String, bool> reactionsMade, List<dynamic> reactions, List<SnPostTag> tags, List<SnPostCategory> categories, List<dynamic> collections, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, bool isTruncated)? $default,) {final _that = this;
switch (_that) {
case _SnPost() when $default != null:
return $default(_that.id,_that.title,_that.description,_that.language,_that.editedAt,_that.publishedAt,_that.visibility,_that.content,_that.slug,_that.type,_that.meta,_that.embedView,_that.viewsUnique,_that.viewsTotal,_that.upvotes,_that.downvotes,_that.repliesCount,_that.pinMode,_that.threadedPostId,_that.threadedPost,_that.repliedPostId,_that.repliedPost,_that.forwardedPostId,_that.forwardedPost,_that.realmId,_that.realm,_that.attachments,_that.publisher,_that.reactionsCount,_that.reactionsMade,_that.reactions,_that.tags,_that.categories,_that.collections,_that.createdAt,_that.updatedAt,_that.deletedAt,_that.isTruncated);case _:
return $default(_that.id,_that.title,_that.description,_that.language,_that.editedAt,_that.publishedAt,_that.visibility,_that.content,_that.slug,_that.type,_that.meta,_that.embedView,_that.viewsUnique,_that.viewsTotal,_that.upvotes,_that.downvotes,_that.repliesCount,_that.awardedScore,_that.pinMode,_that.threadedPostId,_that.threadedPost,_that.repliedPostId,_that.repliedPost,_that.forwardedPostId,_that.forwardedPost,_that.realmId,_that.realm,_that.attachments,_that.publisher,_that.reactionsCount,_that.reactionsMade,_that.reactions,_that.tags,_that.categories,_that.collections,_that.createdAt,_that.updatedAt,_that.deletedAt,_that.isTruncated);case _:
return null;
}
@@ -309,7 +310,7 @@ return $default(_that.id,_that.title,_that.description,_that.language,_that.edit
@JsonSerializable()
class _SnPost implements SnPost {
const _SnPost({required this.id, this.title, this.description, this.language, this.editedAt, this.publishedAt = null, this.visibility = 0, this.content, this.slug, this.type = 0, final Map<String, dynamic>? meta, this.embedView, this.viewsUnique = 0, this.viewsTotal = 0, this.upvotes = 0, this.downvotes = 0, this.repliesCount = 0, this.pinMode, this.threadedPostId, this.threadedPost, this.repliedPostId, this.repliedPost, this.forwardedPostId, this.forwardedPost, this.realmId, this.realm, final List<SnCloudFile> attachments = const [], required this.publisher, final Map<String, int> reactionsCount = const {}, final Map<String, bool> reactionsMade = const {}, final List<dynamic> reactions = const [], final List<SnPostTag> tags = const [], final List<SnPostCategory> categories = const [], final List<dynamic> collections = const [], this.createdAt = null, this.updatedAt = null, this.deletedAt, this.isTruncated = false}): _meta = meta,_attachments = attachments,_reactionsCount = reactionsCount,_reactionsMade = reactionsMade,_reactions = reactions,_tags = tags,_categories = categories,_collections = collections;
const _SnPost({required this.id, this.title, this.description, this.language, this.editedAt, this.publishedAt = null, this.visibility = 0, this.content, this.slug, this.type = 0, final Map<String, dynamic>? meta, this.embedView, this.viewsUnique = 0, this.viewsTotal = 0, this.upvotes = 0, this.downvotes = 0, this.repliesCount = 0, this.awardedScore = 0, this.pinMode, this.threadedPostId, this.threadedPost, this.repliedPostId, this.repliedPost, this.forwardedPostId, this.forwardedPost, this.realmId, this.realm, final List<SnCloudFile> attachments = const [], required this.publisher, final Map<String, int> reactionsCount = const {}, final Map<String, bool> reactionsMade = const {}, final List<dynamic> reactions = const [], final List<SnPostTag> tags = const [], final List<SnPostCategory> categories = const [], final List<dynamic> collections = const [], this.createdAt = null, this.updatedAt = null, this.deletedAt, this.isTruncated = false}): _meta = meta,_attachments = attachments,_reactionsCount = reactionsCount,_reactionsMade = reactionsMade,_reactions = reactions,_tags = tags,_categories = categories,_collections = collections;
factory _SnPost.fromJson(Map<String, dynamic> json) => _$SnPostFromJson(json);
@override final String id;
@@ -337,6 +338,7 @@ class _SnPost implements SnPost {
@override@JsonKey() final int upvotes;
@override@JsonKey() final int downvotes;
@override@JsonKey() final int repliesCount;
@override@JsonKey() final int awardedScore;
@override final int? pinMode;
@override final String? threadedPostId;
@override final SnPost? threadedPost;
@@ -414,16 +416,16 @@ Map<String, dynamic> toJson() {
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnPost&&(identical(other.id, id) || other.id == id)&&(identical(other.title, title) || other.title == title)&&(identical(other.description, description) || other.description == description)&&(identical(other.language, language) || other.language == language)&&(identical(other.editedAt, editedAt) || other.editedAt == editedAt)&&(identical(other.publishedAt, publishedAt) || other.publishedAt == publishedAt)&&(identical(other.visibility, visibility) || other.visibility == visibility)&&(identical(other.content, content) || other.content == content)&&(identical(other.slug, slug) || other.slug == slug)&&(identical(other.type, type) || other.type == type)&&const DeepCollectionEquality().equals(other._meta, _meta)&&(identical(other.embedView, embedView) || other.embedView == embedView)&&(identical(other.viewsUnique, viewsUnique) || other.viewsUnique == viewsUnique)&&(identical(other.viewsTotal, viewsTotal) || other.viewsTotal == viewsTotal)&&(identical(other.upvotes, upvotes) || other.upvotes == upvotes)&&(identical(other.downvotes, downvotes) || other.downvotes == downvotes)&&(identical(other.repliesCount, repliesCount) || other.repliesCount == repliesCount)&&(identical(other.pinMode, pinMode) || other.pinMode == pinMode)&&(identical(other.threadedPostId, threadedPostId) || other.threadedPostId == threadedPostId)&&(identical(other.threadedPost, threadedPost) || other.threadedPost == threadedPost)&&(identical(other.repliedPostId, repliedPostId) || other.repliedPostId == repliedPostId)&&(identical(other.repliedPost, repliedPost) || other.repliedPost == repliedPost)&&(identical(other.forwardedPostId, forwardedPostId) || other.forwardedPostId == forwardedPostId)&&(identical(other.forwardedPost, forwardedPost) || other.forwardedPost == forwardedPost)&&(identical(other.realmId, realmId) || other.realmId == realmId)&&(identical(other.realm, realm) || other.realm == realm)&&const DeepCollectionEquality().equals(other._attachments, _attachments)&&(identical(other.publisher, publisher) || other.publisher == publisher)&&const DeepCollectionEquality().equals(other._reactionsCount, _reactionsCount)&&const DeepCollectionEquality().equals(other._reactionsMade, _reactionsMade)&&const DeepCollectionEquality().equals(other._reactions, _reactions)&&const DeepCollectionEquality().equals(other._tags, _tags)&&const DeepCollectionEquality().equals(other._categories, _categories)&&const DeepCollectionEquality().equals(other._collections, _collections)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)&&(identical(other.isTruncated, isTruncated) || other.isTruncated == isTruncated));
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnPost&&(identical(other.id, id) || other.id == id)&&(identical(other.title, title) || other.title == title)&&(identical(other.description, description) || other.description == description)&&(identical(other.language, language) || other.language == language)&&(identical(other.editedAt, editedAt) || other.editedAt == editedAt)&&(identical(other.publishedAt, publishedAt) || other.publishedAt == publishedAt)&&(identical(other.visibility, visibility) || other.visibility == visibility)&&(identical(other.content, content) || other.content == content)&&(identical(other.slug, slug) || other.slug == slug)&&(identical(other.type, type) || other.type == type)&&const DeepCollectionEquality().equals(other._meta, _meta)&&(identical(other.embedView, embedView) || other.embedView == embedView)&&(identical(other.viewsUnique, viewsUnique) || other.viewsUnique == viewsUnique)&&(identical(other.viewsTotal, viewsTotal) || other.viewsTotal == viewsTotal)&&(identical(other.upvotes, upvotes) || other.upvotes == upvotes)&&(identical(other.downvotes, downvotes) || other.downvotes == downvotes)&&(identical(other.repliesCount, repliesCount) || other.repliesCount == repliesCount)&&(identical(other.awardedScore, awardedScore) || other.awardedScore == awardedScore)&&(identical(other.pinMode, pinMode) || other.pinMode == pinMode)&&(identical(other.threadedPostId, threadedPostId) || other.threadedPostId == threadedPostId)&&(identical(other.threadedPost, threadedPost) || other.threadedPost == threadedPost)&&(identical(other.repliedPostId, repliedPostId) || other.repliedPostId == repliedPostId)&&(identical(other.repliedPost, repliedPost) || other.repliedPost == repliedPost)&&(identical(other.forwardedPostId, forwardedPostId) || other.forwardedPostId == forwardedPostId)&&(identical(other.forwardedPost, forwardedPost) || other.forwardedPost == forwardedPost)&&(identical(other.realmId, realmId) || other.realmId == realmId)&&(identical(other.realm, realm) || other.realm == realm)&&const DeepCollectionEquality().equals(other._attachments, _attachments)&&(identical(other.publisher, publisher) || other.publisher == publisher)&&const DeepCollectionEquality().equals(other._reactionsCount, _reactionsCount)&&const DeepCollectionEquality().equals(other._reactionsMade, _reactionsMade)&&const DeepCollectionEquality().equals(other._reactions, _reactions)&&const DeepCollectionEquality().equals(other._tags, _tags)&&const DeepCollectionEquality().equals(other._categories, _categories)&&const DeepCollectionEquality().equals(other._collections, _collections)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)&&(identical(other.isTruncated, isTruncated) || other.isTruncated == isTruncated));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hashAll([runtimeType,id,title,description,language,editedAt,publishedAt,visibility,content,slug,type,const DeepCollectionEquality().hash(_meta),embedView,viewsUnique,viewsTotal,upvotes,downvotes,repliesCount,pinMode,threadedPostId,threadedPost,repliedPostId,repliedPost,forwardedPostId,forwardedPost,realmId,realm,const DeepCollectionEquality().hash(_attachments),publisher,const DeepCollectionEquality().hash(_reactionsCount),const DeepCollectionEquality().hash(_reactionsMade),const DeepCollectionEquality().hash(_reactions),const DeepCollectionEquality().hash(_tags),const DeepCollectionEquality().hash(_categories),const DeepCollectionEquality().hash(_collections),createdAt,updatedAt,deletedAt,isTruncated]);
int get hashCode => Object.hashAll([runtimeType,id,title,description,language,editedAt,publishedAt,visibility,content,slug,type,const DeepCollectionEquality().hash(_meta),embedView,viewsUnique,viewsTotal,upvotes,downvotes,repliesCount,awardedScore,pinMode,threadedPostId,threadedPost,repliedPostId,repliedPost,forwardedPostId,forwardedPost,realmId,realm,const DeepCollectionEquality().hash(_attachments),publisher,const DeepCollectionEquality().hash(_reactionsCount),const DeepCollectionEquality().hash(_reactionsMade),const DeepCollectionEquality().hash(_reactions),const DeepCollectionEquality().hash(_tags),const DeepCollectionEquality().hash(_categories),const DeepCollectionEquality().hash(_collections),createdAt,updatedAt,deletedAt,isTruncated]);
@override
String toString() {
return 'SnPost(id: $id, title: $title, description: $description, language: $language, editedAt: $editedAt, publishedAt: $publishedAt, visibility: $visibility, content: $content, slug: $slug, type: $type, meta: $meta, embedView: $embedView, viewsUnique: $viewsUnique, viewsTotal: $viewsTotal, upvotes: $upvotes, downvotes: $downvotes, repliesCount: $repliesCount, pinMode: $pinMode, threadedPostId: $threadedPostId, threadedPost: $threadedPost, repliedPostId: $repliedPostId, repliedPost: $repliedPost, forwardedPostId: $forwardedPostId, forwardedPost: $forwardedPost, realmId: $realmId, realm: $realm, attachments: $attachments, publisher: $publisher, reactionsCount: $reactionsCount, reactionsMade: $reactionsMade, reactions: $reactions, tags: $tags, categories: $categories, collections: $collections, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, isTruncated: $isTruncated)';
return 'SnPost(id: $id, title: $title, description: $description, language: $language, editedAt: $editedAt, publishedAt: $publishedAt, visibility: $visibility, content: $content, slug: $slug, type: $type, meta: $meta, embedView: $embedView, viewsUnique: $viewsUnique, viewsTotal: $viewsTotal, upvotes: $upvotes, downvotes: $downvotes, repliesCount: $repliesCount, awardedScore: $awardedScore, pinMode: $pinMode, threadedPostId: $threadedPostId, threadedPost: $threadedPost, repliedPostId: $repliedPostId, repliedPost: $repliedPost, forwardedPostId: $forwardedPostId, forwardedPost: $forwardedPost, realmId: $realmId, realm: $realm, attachments: $attachments, publisher: $publisher, reactionsCount: $reactionsCount, reactionsMade: $reactionsMade, reactions: $reactions, tags: $tags, categories: $categories, collections: $collections, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, isTruncated: $isTruncated)';
}
@@ -434,7 +436,7 @@ abstract mixin class _$SnPostCopyWith<$Res> implements $SnPostCopyWith<$Res> {
factory _$SnPostCopyWith(_SnPost value, $Res Function(_SnPost) _then) = __$SnPostCopyWithImpl;
@override @useResult
$Res call({
String id, String? title, String? description, String? language, DateTime? editedAt, DateTime? publishedAt, int visibility, String? content, String? slug, int type, Map<String, dynamic>? meta, SnPostEmbedView? embedView, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, int? pinMode, String? threadedPostId, SnPost? threadedPost, String? repliedPostId, SnPost? repliedPost, String? forwardedPostId, SnPost? forwardedPost, String? realmId, SnRealm? realm, List<SnCloudFile> attachments, SnPublisher publisher, Map<String, int> reactionsCount, Map<String, bool> reactionsMade, List<dynamic> reactions, List<SnPostTag> tags, List<SnPostCategory> categories, List<dynamic> collections, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, bool isTruncated
String id, String? title, String? description, String? language, DateTime? editedAt, DateTime? publishedAt, int visibility, String? content, String? slug, int type, Map<String, dynamic>? meta, SnPostEmbedView? embedView, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, int awardedScore, int? pinMode, String? threadedPostId, SnPost? threadedPost, String? repliedPostId, SnPost? repliedPost, String? forwardedPostId, SnPost? forwardedPost, String? realmId, SnRealm? realm, List<SnCloudFile> attachments, SnPublisher publisher, Map<String, int> reactionsCount, Map<String, bool> reactionsMade, List<dynamic> reactions, List<SnPostTag> tags, List<SnPostCategory> categories, List<dynamic> collections, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, bool isTruncated
});
@@ -451,7 +453,7 @@ class __$SnPostCopyWithImpl<$Res>
/// Create a copy of SnPost
/// with the given fields replaced by the non-null parameter values.
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? title = freezed,Object? description = freezed,Object? language = freezed,Object? editedAt = freezed,Object? publishedAt = freezed,Object? visibility = null,Object? content = freezed,Object? slug = freezed,Object? type = null,Object? meta = freezed,Object? embedView = freezed,Object? viewsUnique = null,Object? viewsTotal = null,Object? upvotes = null,Object? downvotes = null,Object? repliesCount = null,Object? pinMode = freezed,Object? threadedPostId = freezed,Object? threadedPost = freezed,Object? repliedPostId = freezed,Object? repliedPost = freezed,Object? forwardedPostId = freezed,Object? forwardedPost = freezed,Object? realmId = freezed,Object? realm = freezed,Object? attachments = null,Object? publisher = null,Object? reactionsCount = null,Object? reactionsMade = null,Object? reactions = null,Object? tags = null,Object? categories = null,Object? collections = null,Object? createdAt = freezed,Object? updatedAt = freezed,Object? deletedAt = freezed,Object? isTruncated = null,}) {
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? title = freezed,Object? description = freezed,Object? language = freezed,Object? editedAt = freezed,Object? publishedAt = freezed,Object? visibility = null,Object? content = freezed,Object? slug = freezed,Object? type = null,Object? meta = freezed,Object? embedView = freezed,Object? viewsUnique = null,Object? viewsTotal = null,Object? upvotes = null,Object? downvotes = null,Object? repliesCount = null,Object? awardedScore = null,Object? pinMode = freezed,Object? threadedPostId = freezed,Object? threadedPost = freezed,Object? repliedPostId = freezed,Object? repliedPost = freezed,Object? forwardedPostId = freezed,Object? forwardedPost = freezed,Object? realmId = freezed,Object? realm = freezed,Object? attachments = null,Object? publisher = null,Object? reactionsCount = null,Object? reactionsMade = null,Object? reactions = null,Object? tags = null,Object? categories = null,Object? collections = null,Object? createdAt = freezed,Object? updatedAt = freezed,Object? deletedAt = freezed,Object? isTruncated = null,}) {
return _then(_SnPost(
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
as String,title: freezed == title ? _self.title : title // ignore: cast_nullable_to_non_nullable
@@ -470,6 +472,7 @@ as int,viewsTotal: null == viewsTotal ? _self.viewsTotal : viewsTotal // ignore:
as int,upvotes: null == upvotes ? _self.upvotes : upvotes // ignore: cast_nullable_to_non_nullable
as int,downvotes: null == downvotes ? _self.downvotes : downvotes // ignore: cast_nullable_to_non_nullable
as int,repliesCount: null == repliesCount ? _self.repliesCount : repliesCount // ignore: cast_nullable_to_non_nullable
as int,awardedScore: null == awardedScore ? _self.awardedScore : awardedScore // ignore: cast_nullable_to_non_nullable
as int,pinMode: freezed == pinMode ? _self.pinMode : pinMode // ignore: cast_nullable_to_non_nullable
as int?,threadedPostId: freezed == threadedPostId ? _self.threadedPostId : threadedPostId // ignore: cast_nullable_to_non_nullable
as String?,threadedPost: freezed == threadedPost ? _self.threadedPost : threadedPost // ignore: cast_nullable_to_non_nullable
@@ -1614,6 +1617,287 @@ as PostEmbedViewRenderer,
}
}
/// @nodoc
mixin _$SnPostAward {
String get id; double get amount; int get attitude; String? get message; String get postId; String get accountId; DateTime? get createdAt; DateTime? get updatedAt; DateTime? get deletedAt;
/// Create a copy of SnPostAward
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
$SnPostAwardCopyWith<SnPostAward> get copyWith => _$SnPostAwardCopyWithImpl<SnPostAward>(this as SnPostAward, _$identity);
/// Serializes this SnPostAward to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnPostAward&&(identical(other.id, id) || other.id == id)&&(identical(other.amount, amount) || other.amount == amount)&&(identical(other.attitude, attitude) || other.attitude == attitude)&&(identical(other.message, message) || other.message == message)&&(identical(other.postId, postId) || other.postId == postId)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType,id,amount,attitude,message,postId,accountId,createdAt,updatedAt,deletedAt);
@override
String toString() {
return 'SnPostAward(id: $id, amount: $amount, attitude: $attitude, message: $message, postId: $postId, accountId: $accountId, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
}
}
/// @nodoc
abstract mixin class $SnPostAwardCopyWith<$Res> {
factory $SnPostAwardCopyWith(SnPostAward value, $Res Function(SnPostAward) _then) = _$SnPostAwardCopyWithImpl;
@useResult
$Res call({
String id, double amount, int attitude, String? message, String postId, String accountId, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt
});
}
/// @nodoc
class _$SnPostAwardCopyWithImpl<$Res>
implements $SnPostAwardCopyWith<$Res> {
_$SnPostAwardCopyWithImpl(this._self, this._then);
final SnPostAward _self;
final $Res Function(SnPostAward) _then;
/// Create a copy of SnPostAward
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? amount = null,Object? attitude = null,Object? message = freezed,Object? postId = null,Object? accountId = null,Object? createdAt = freezed,Object? updatedAt = freezed,Object? deletedAt = freezed,}) {
return _then(_self.copyWith(
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
as String,amount: null == amount ? _self.amount : amount // ignore: cast_nullable_to_non_nullable
as double,attitude: null == attitude ? _self.attitude : attitude // ignore: cast_nullable_to_non_nullable
as int,message: freezed == message ? _self.message : message // ignore: cast_nullable_to_non_nullable
as String?,postId: null == postId ? _self.postId : postId // ignore: cast_nullable_to_non_nullable
as String,accountId: null == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable
as String,createdAt: freezed == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
as DateTime?,updatedAt: freezed == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
as DateTime?,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
as DateTime?,
));
}
}
/// Adds pattern-matching-related methods to [SnPostAward].
extension SnPostAwardPatterns on SnPostAward {
/// A variant of `map` that fallback to returning `orElse`.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case _:
/// return orElse();
/// }
/// ```
@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _SnPostAward value)? $default,{required TResult orElse(),}){
final _that = this;
switch (_that) {
case _SnPostAward() when $default != null:
return $default(_that);case _:
return orElse();
}
}
/// A `switch`-like method, using callbacks.
///
/// Callbacks receives the raw object, upcasted.
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case final Subclass2 value:
/// return ...;
/// }
/// ```
@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _SnPostAward value) $default,){
final _that = this;
switch (_that) {
case _SnPostAward():
return $default(_that);}
}
/// A variant of `map` that fallback to returning `null`.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case _:
/// return null;
/// }
/// ```
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _SnPostAward value)? $default,){
final _that = this;
switch (_that) {
case _SnPostAward() when $default != null:
return $default(_that);case _:
return null;
}
}
/// A variant of `when` that fallback to an `orElse` callback.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case _:
/// return orElse();
/// }
/// ```
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String id, double amount, int attitude, String? message, String postId, String accountId, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt)? $default,{required TResult orElse(),}) {final _that = this;
switch (_that) {
case _SnPostAward() when $default != null:
return $default(_that.id,_that.amount,_that.attitude,_that.message,_that.postId,_that.accountId,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
return orElse();
}
}
/// A `switch`-like method, using callbacks.
///
/// As opposed to `map`, this offers destructuring.
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case Subclass2(:final field2):
/// return ...;
/// }
/// ```
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String id, double amount, int attitude, String? message, String postId, String accountId, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt) $default,) {final _that = this;
switch (_that) {
case _SnPostAward():
return $default(_that.id,_that.amount,_that.attitude,_that.message,_that.postId,_that.accountId,_that.createdAt,_that.updatedAt,_that.deletedAt);}
}
/// A variant of `when` that fallback to returning `null`
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case _:
/// return null;
/// }
/// ```
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String id, double amount, int attitude, String? message, String postId, String accountId, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt)? $default,) {final _that = this;
switch (_that) {
case _SnPostAward() when $default != null:
return $default(_that.id,_that.amount,_that.attitude,_that.message,_that.postId,_that.accountId,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
return null;
}
}
}
/// @nodoc
@JsonSerializable()
class _SnPostAward implements SnPostAward {
const _SnPostAward({required this.id, required this.amount, required this.attitude, this.message, required this.postId, required this.accountId, this.createdAt = null, this.updatedAt = null, this.deletedAt});
factory _SnPostAward.fromJson(Map<String, dynamic> json) => _$SnPostAwardFromJson(json);
@override final String id;
@override final double amount;
@override final int attitude;
@override final String? message;
@override final String postId;
@override final String accountId;
@override@JsonKey() final DateTime? createdAt;
@override@JsonKey() final DateTime? updatedAt;
@override final DateTime? deletedAt;
/// Create a copy of SnPostAward
/// with the given fields replaced by the non-null parameter values.
@override @JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
_$SnPostAwardCopyWith<_SnPostAward> get copyWith => __$SnPostAwardCopyWithImpl<_SnPostAward>(this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$SnPostAwardToJson(this, );
}
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnPostAward&&(identical(other.id, id) || other.id == id)&&(identical(other.amount, amount) || other.amount == amount)&&(identical(other.attitude, attitude) || other.attitude == attitude)&&(identical(other.message, message) || other.message == message)&&(identical(other.postId, postId) || other.postId == postId)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType,id,amount,attitude,message,postId,accountId,createdAt,updatedAt,deletedAt);
@override
String toString() {
return 'SnPostAward(id: $id, amount: $amount, attitude: $attitude, message: $message, postId: $postId, accountId: $accountId, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
}
}
/// @nodoc
abstract mixin class _$SnPostAwardCopyWith<$Res> implements $SnPostAwardCopyWith<$Res> {
factory _$SnPostAwardCopyWith(_SnPostAward value, $Res Function(_SnPostAward) _then) = __$SnPostAwardCopyWithImpl;
@override @useResult
$Res call({
String id, double amount, int attitude, String? message, String postId, String accountId, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt
});
}
/// @nodoc
class __$SnPostAwardCopyWithImpl<$Res>
implements _$SnPostAwardCopyWith<$Res> {
__$SnPostAwardCopyWithImpl(this._self, this._then);
final _SnPostAward _self;
final $Res Function(_SnPostAward) _then;
/// Create a copy of SnPostAward
/// with the given fields replaced by the non-null parameter values.
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? amount = null,Object? attitude = null,Object? message = freezed,Object? postId = null,Object? accountId = null,Object? createdAt = freezed,Object? updatedAt = freezed,Object? deletedAt = freezed,}) {
return _then(_SnPostAward(
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
as String,amount: null == amount ? _self.amount : amount // ignore: cast_nullable_to_non_nullable
as double,attitude: null == attitude ? _self.attitude : attitude // ignore: cast_nullable_to_non_nullable
as int,message: freezed == message ? _self.message : message // ignore: cast_nullable_to_non_nullable
as String?,postId: null == postId ? _self.postId : postId // ignore: cast_nullable_to_non_nullable
as String,accountId: null == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable
as String,createdAt: freezed == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
as DateTime?,updatedAt: freezed == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
as DateTime?,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
as DateTime?,
));
}
}
// dart format on

View File

@@ -35,6 +35,7 @@ _SnPost _$SnPostFromJson(Map<String, dynamic> json) => _SnPost(
upvotes: (json['upvotes'] as num?)?.toInt() ?? 0,
downvotes: (json['downvotes'] as num?)?.toInt() ?? 0,
repliesCount: (json['replies_count'] as num?)?.toInt() ?? 0,
awardedScore: (json['awarded_score'] as num?)?.toInt() ?? 0,
pinMode: (json['pin_mode'] as num?)?.toInt(),
threadedPostId: json['threaded_post_id'] as String?,
threadedPost:
@@ -117,6 +118,7 @@ Map<String, dynamic> _$SnPostToJson(_SnPost instance) => <String, dynamic>{
'upvotes': instance.upvotes,
'downvotes': instance.downvotes,
'replies_count': instance.repliesCount,
'awarded_score': instance.awardedScore,
'pin_mode': instance.pinMode,
'threaded_post_id': instance.threadedPostId,
'threaded_post': instance.threadedPost?.toJson(),
@@ -194,3 +196,37 @@ Map<String, dynamic> _$SnPostEmbedViewToJson(_SnPostEmbedView instance) =>
};
const _$PostEmbedViewRendererEnumMap = {PostEmbedViewRenderer.webView: 0};
_SnPostAward _$SnPostAwardFromJson(Map<String, dynamic> json) => _SnPostAward(
id: json['id'] as String,
amount: (json['amount'] as num).toDouble(),
attitude: (json['attitude'] as num).toInt(),
message: json['message'] as String?,
postId: json['post_id'] as String,
accountId: json['account_id'] as String,
createdAt:
json['created_at'] == null
? null
: DateTime.parse(json['created_at'] as String),
updatedAt:
json['updated_at'] == null
? null
: DateTime.parse(json['updated_at'] as String),
deletedAt:
json['deleted_at'] == null
? null
: DateTime.parse(json['deleted_at'] as String),
);
Map<String, dynamic> _$SnPostAwardToJson(_SnPostAward instance) =>
<String, dynamic>{
'id': instance.id,
'amount': instance.amount,
'attitude': instance.attitude,
'message': instance.message,
'post_id': instance.postId,
'account_id': instance.accountId,
'created_at': instance.createdAt?.toIso8601String(),
'updated_at': instance.updatedAt?.toIso8601String(),
'deleted_at': instance.deletedAt?.toIso8601String(),
};

View File

@@ -108,17 +108,14 @@ sealed class SnWalletOrder with _$SnWalletOrder {
required String id,
required int status,
required String currency,
required dynamic remarks,
required String? remarks,
required String appIdentifier,
@Default({}) Map<String, dynamic> meta,
required int amount,
required DateTime expiredAt,
required String? payeeWalletId,
required SnWallet? payeeWallet,
required String? transactionId,
required SnTransaction? transaction,
required String? issuerAppId,
required dynamic issuerApp,
required DateTime createdAt,
required DateTime updatedAt,
required DateTime? deletedAt,

View File

@@ -1554,7 +1554,7 @@ as String,
/// @nodoc
mixin _$SnWalletOrder {
String get id; int get status; String get currency; dynamic get remarks; String get appIdentifier; Map<String, dynamic> get meta; int get amount; DateTime get expiredAt; String? get payeeWalletId; SnWallet? get payeeWallet; String? get transactionId; SnTransaction? get transaction; String? get issuerAppId; dynamic get issuerApp; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt;
String get id; int get status; String get currency; String? get remarks; String get appIdentifier; Map<String, dynamic> get meta; int get amount; DateTime get expiredAt; String? get payeeWalletId; String? get transactionId; String? get issuerAppId; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt;
/// Create a copy of SnWalletOrder
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@@ -1567,16 +1567,16 @@ $SnWalletOrderCopyWith<SnWalletOrder> get copyWith => _$SnWalletOrderCopyWithImp
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnWalletOrder&&(identical(other.id, id) || other.id == id)&&(identical(other.status, status) || other.status == status)&&(identical(other.currency, currency) || other.currency == currency)&&const DeepCollectionEquality().equals(other.remarks, remarks)&&(identical(other.appIdentifier, appIdentifier) || other.appIdentifier == appIdentifier)&&const DeepCollectionEquality().equals(other.meta, meta)&&(identical(other.amount, amount) || other.amount == amount)&&(identical(other.expiredAt, expiredAt) || other.expiredAt == expiredAt)&&(identical(other.payeeWalletId, payeeWalletId) || other.payeeWalletId == payeeWalletId)&&(identical(other.payeeWallet, payeeWallet) || other.payeeWallet == payeeWallet)&&(identical(other.transactionId, transactionId) || other.transactionId == transactionId)&&(identical(other.transaction, transaction) || other.transaction == transaction)&&(identical(other.issuerAppId, issuerAppId) || other.issuerAppId == issuerAppId)&&const DeepCollectionEquality().equals(other.issuerApp, issuerApp)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt));
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnWalletOrder&&(identical(other.id, id) || other.id == id)&&(identical(other.status, status) || other.status == status)&&(identical(other.currency, currency) || other.currency == currency)&&(identical(other.remarks, remarks) || other.remarks == remarks)&&(identical(other.appIdentifier, appIdentifier) || other.appIdentifier == appIdentifier)&&const DeepCollectionEquality().equals(other.meta, meta)&&(identical(other.amount, amount) || other.amount == amount)&&(identical(other.expiredAt, expiredAt) || other.expiredAt == expiredAt)&&(identical(other.payeeWalletId, payeeWalletId) || other.payeeWalletId == payeeWalletId)&&(identical(other.transactionId, transactionId) || other.transactionId == transactionId)&&(identical(other.issuerAppId, issuerAppId) || other.issuerAppId == issuerAppId)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType,id,status,currency,const DeepCollectionEquality().hash(remarks),appIdentifier,const DeepCollectionEquality().hash(meta),amount,expiredAt,payeeWalletId,payeeWallet,transactionId,transaction,issuerAppId,const DeepCollectionEquality().hash(issuerApp),createdAt,updatedAt,deletedAt);
int get hashCode => Object.hash(runtimeType,id,status,currency,remarks,appIdentifier,const DeepCollectionEquality().hash(meta),amount,expiredAt,payeeWalletId,transactionId,issuerAppId,createdAt,updatedAt,deletedAt);
@override
String toString() {
return 'SnWalletOrder(id: $id, status: $status, currency: $currency, remarks: $remarks, appIdentifier: $appIdentifier, meta: $meta, amount: $amount, expiredAt: $expiredAt, payeeWalletId: $payeeWalletId, payeeWallet: $payeeWallet, transactionId: $transactionId, transaction: $transaction, issuerAppId: $issuerAppId, issuerApp: $issuerApp, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
return 'SnWalletOrder(id: $id, status: $status, currency: $currency, remarks: $remarks, appIdentifier: $appIdentifier, meta: $meta, amount: $amount, expiredAt: $expiredAt, payeeWalletId: $payeeWalletId, transactionId: $transactionId, issuerAppId: $issuerAppId, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
}
@@ -1587,11 +1587,11 @@ abstract mixin class $SnWalletOrderCopyWith<$Res> {
factory $SnWalletOrderCopyWith(SnWalletOrder value, $Res Function(SnWalletOrder) _then) = _$SnWalletOrderCopyWithImpl;
@useResult
$Res call({
String id, int status, String currency, dynamic remarks, String appIdentifier, Map<String, dynamic> meta, int amount, DateTime expiredAt, String? payeeWalletId, SnWallet? payeeWallet, String? transactionId, SnTransaction? transaction, String? issuerAppId, dynamic issuerApp, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
String id, int status, String currency, String? remarks, String appIdentifier, Map<String, dynamic> meta, int amount, DateTime expiredAt, String? payeeWalletId, String? transactionId, String? issuerAppId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
});
$SnWalletCopyWith<$Res>? get payeeWallet;$SnTransactionCopyWith<$Res>? get transaction;
}
/// @nodoc
@@ -1604,53 +1604,26 @@ class _$SnWalletOrderCopyWithImpl<$Res>
/// Create a copy of SnWalletOrder
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? status = null,Object? currency = null,Object? remarks = freezed,Object? appIdentifier = null,Object? meta = null,Object? amount = null,Object? expiredAt = null,Object? payeeWalletId = freezed,Object? payeeWallet = freezed,Object? transactionId = freezed,Object? transaction = freezed,Object? issuerAppId = freezed,Object? issuerApp = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? status = null,Object? currency = null,Object? remarks = freezed,Object? appIdentifier = null,Object? meta = null,Object? amount = null,Object? expiredAt = null,Object? payeeWalletId = freezed,Object? transactionId = freezed,Object? issuerAppId = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
return _then(_self.copyWith(
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
as String,status: null == status ? _self.status : status // ignore: cast_nullable_to_non_nullable
as int,currency: null == currency ? _self.currency : currency // ignore: cast_nullable_to_non_nullable
as String,remarks: freezed == remarks ? _self.remarks : remarks // ignore: cast_nullable_to_non_nullable
as dynamic,appIdentifier: null == appIdentifier ? _self.appIdentifier : appIdentifier // ignore: cast_nullable_to_non_nullable
as String?,appIdentifier: null == appIdentifier ? _self.appIdentifier : appIdentifier // ignore: cast_nullable_to_non_nullable
as String,meta: null == meta ? _self.meta : meta // ignore: cast_nullable_to_non_nullable
as Map<String, dynamic>,amount: null == amount ? _self.amount : amount // ignore: cast_nullable_to_non_nullable
as int,expiredAt: null == expiredAt ? _self.expiredAt : expiredAt // ignore: cast_nullable_to_non_nullable
as DateTime,payeeWalletId: freezed == payeeWalletId ? _self.payeeWalletId : payeeWalletId // ignore: cast_nullable_to_non_nullable
as String?,payeeWallet: freezed == payeeWallet ? _self.payeeWallet : payeeWallet // ignore: cast_nullable_to_non_nullable
as SnWallet?,transactionId: freezed == transactionId ? _self.transactionId : transactionId // ignore: cast_nullable_to_non_nullable
as String?,transaction: freezed == transaction ? _self.transaction : transaction // ignore: cast_nullable_to_non_nullable
as SnTransaction?,issuerAppId: freezed == issuerAppId ? _self.issuerAppId : issuerAppId // ignore: cast_nullable_to_non_nullable
as String?,issuerApp: freezed == issuerApp ? _self.issuerApp : issuerApp // ignore: cast_nullable_to_non_nullable
as dynamic,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
as String?,transactionId: freezed == transactionId ? _self.transactionId : transactionId // ignore: cast_nullable_to_non_nullable
as String?,issuerAppId: freezed == issuerAppId ? _self.issuerAppId : issuerAppId // ignore: cast_nullable_to_non_nullable
as String?,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
as DateTime?,
));
}
/// Create a copy of SnWalletOrder
/// with the given fields replaced by the non-null parameter values.
@override
@pragma('vm:prefer-inline')
$SnWalletCopyWith<$Res>? get payeeWallet {
if (_self.payeeWallet == null) {
return null;
}
return $SnWalletCopyWith<$Res>(_self.payeeWallet!, (value) {
return _then(_self.copyWith(payeeWallet: value));
});
}/// Create a copy of SnWalletOrder
/// with the given fields replaced by the non-null parameter values.
@override
@pragma('vm:prefer-inline')
$SnTransactionCopyWith<$Res>? get transaction {
if (_self.transaction == null) {
return null;
}
return $SnTransactionCopyWith<$Res>(_self.transaction!, (value) {
return _then(_self.copyWith(transaction: value));
});
}
}
@@ -1729,10 +1702,10 @@ return $default(_that);case _:
/// }
/// ```
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String id, int status, String currency, dynamic remarks, String appIdentifier, Map<String, dynamic> meta, int amount, DateTime expiredAt, String? payeeWalletId, SnWallet? payeeWallet, String? transactionId, SnTransaction? transaction, String? issuerAppId, dynamic issuerApp, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,{required TResult orElse(),}) {final _that = this;
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String id, int status, String currency, String? remarks, String appIdentifier, Map<String, dynamic> meta, int amount, DateTime expiredAt, String? payeeWalletId, String? transactionId, String? issuerAppId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,{required TResult orElse(),}) {final _that = this;
switch (_that) {
case _SnWalletOrder() when $default != null:
return $default(_that.id,_that.status,_that.currency,_that.remarks,_that.appIdentifier,_that.meta,_that.amount,_that.expiredAt,_that.payeeWalletId,_that.payeeWallet,_that.transactionId,_that.transaction,_that.issuerAppId,_that.issuerApp,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
return $default(_that.id,_that.status,_that.currency,_that.remarks,_that.appIdentifier,_that.meta,_that.amount,_that.expiredAt,_that.payeeWalletId,_that.transactionId,_that.issuerAppId,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
return orElse();
}
@@ -1750,10 +1723,10 @@ return $default(_that.id,_that.status,_that.currency,_that.remarks,_that.appIden
/// }
/// ```
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String id, int status, String currency, dynamic remarks, String appIdentifier, Map<String, dynamic> meta, int amount, DateTime expiredAt, String? payeeWalletId, SnWallet? payeeWallet, String? transactionId, SnTransaction? transaction, String? issuerAppId, dynamic issuerApp, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt) $default,) {final _that = this;
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String id, int status, String currency, String? remarks, String appIdentifier, Map<String, dynamic> meta, int amount, DateTime expiredAt, String? payeeWalletId, String? transactionId, String? issuerAppId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt) $default,) {final _that = this;
switch (_that) {
case _SnWalletOrder():
return $default(_that.id,_that.status,_that.currency,_that.remarks,_that.appIdentifier,_that.meta,_that.amount,_that.expiredAt,_that.payeeWalletId,_that.payeeWallet,_that.transactionId,_that.transaction,_that.issuerAppId,_that.issuerApp,_that.createdAt,_that.updatedAt,_that.deletedAt);}
return $default(_that.id,_that.status,_that.currency,_that.remarks,_that.appIdentifier,_that.meta,_that.amount,_that.expiredAt,_that.payeeWalletId,_that.transactionId,_that.issuerAppId,_that.createdAt,_that.updatedAt,_that.deletedAt);}
}
/// A variant of `when` that fallback to returning `null`
///
@@ -1767,10 +1740,10 @@ return $default(_that.id,_that.status,_that.currency,_that.remarks,_that.appIden
/// }
/// ```
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String id, int status, String currency, dynamic remarks, String appIdentifier, Map<String, dynamic> meta, int amount, DateTime expiredAt, String? payeeWalletId, SnWallet? payeeWallet, String? transactionId, SnTransaction? transaction, String? issuerAppId, dynamic issuerApp, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,) {final _that = this;
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String id, int status, String currency, String? remarks, String appIdentifier, Map<String, dynamic> meta, int amount, DateTime expiredAt, String? payeeWalletId, String? transactionId, String? issuerAppId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,) {final _that = this;
switch (_that) {
case _SnWalletOrder() when $default != null:
return $default(_that.id,_that.status,_that.currency,_that.remarks,_that.appIdentifier,_that.meta,_that.amount,_that.expiredAt,_that.payeeWalletId,_that.payeeWallet,_that.transactionId,_that.transaction,_that.issuerAppId,_that.issuerApp,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
return $default(_that.id,_that.status,_that.currency,_that.remarks,_that.appIdentifier,_that.meta,_that.amount,_that.expiredAt,_that.payeeWalletId,_that.transactionId,_that.issuerAppId,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
return null;
}
@@ -1782,13 +1755,13 @@ return $default(_that.id,_that.status,_that.currency,_that.remarks,_that.appIden
@JsonSerializable()
class _SnWalletOrder implements SnWalletOrder {
const _SnWalletOrder({required this.id, required this.status, required this.currency, required this.remarks, required this.appIdentifier, final Map<String, dynamic> meta = const {}, required this.amount, required this.expiredAt, required this.payeeWalletId, required this.payeeWallet, required this.transactionId, required this.transaction, required this.issuerAppId, required this.issuerApp, required this.createdAt, required this.updatedAt, required this.deletedAt}): _meta = meta;
const _SnWalletOrder({required this.id, required this.status, required this.currency, required this.remarks, required this.appIdentifier, final Map<String, dynamic> meta = const {}, required this.amount, required this.expiredAt, required this.payeeWalletId, required this.transactionId, required this.issuerAppId, required this.createdAt, required this.updatedAt, required this.deletedAt}): _meta = meta;
factory _SnWalletOrder.fromJson(Map<String, dynamic> json) => _$SnWalletOrderFromJson(json);
@override final String id;
@override final int status;
@override final String currency;
@override final dynamic remarks;
@override final String? remarks;
@override final String appIdentifier;
final Map<String, dynamic> _meta;
@override@JsonKey() Map<String, dynamic> get meta {
@@ -1800,11 +1773,8 @@ class _SnWalletOrder implements SnWalletOrder {
@override final int amount;
@override final DateTime expiredAt;
@override final String? payeeWalletId;
@override final SnWallet? payeeWallet;
@override final String? transactionId;
@override final SnTransaction? transaction;
@override final String? issuerAppId;
@override final dynamic issuerApp;
@override final DateTime createdAt;
@override final DateTime updatedAt;
@override final DateTime? deletedAt;
@@ -1822,16 +1792,16 @@ Map<String, dynamic> toJson() {
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnWalletOrder&&(identical(other.id, id) || other.id == id)&&(identical(other.status, status) || other.status == status)&&(identical(other.currency, currency) || other.currency == currency)&&const DeepCollectionEquality().equals(other.remarks, remarks)&&(identical(other.appIdentifier, appIdentifier) || other.appIdentifier == appIdentifier)&&const DeepCollectionEquality().equals(other._meta, _meta)&&(identical(other.amount, amount) || other.amount == amount)&&(identical(other.expiredAt, expiredAt) || other.expiredAt == expiredAt)&&(identical(other.payeeWalletId, payeeWalletId) || other.payeeWalletId == payeeWalletId)&&(identical(other.payeeWallet, payeeWallet) || other.payeeWallet == payeeWallet)&&(identical(other.transactionId, transactionId) || other.transactionId == transactionId)&&(identical(other.transaction, transaction) || other.transaction == transaction)&&(identical(other.issuerAppId, issuerAppId) || other.issuerAppId == issuerAppId)&&const DeepCollectionEquality().equals(other.issuerApp, issuerApp)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt));
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnWalletOrder&&(identical(other.id, id) || other.id == id)&&(identical(other.status, status) || other.status == status)&&(identical(other.currency, currency) || other.currency == currency)&&(identical(other.remarks, remarks) || other.remarks == remarks)&&(identical(other.appIdentifier, appIdentifier) || other.appIdentifier == appIdentifier)&&const DeepCollectionEquality().equals(other._meta, _meta)&&(identical(other.amount, amount) || other.amount == amount)&&(identical(other.expiredAt, expiredAt) || other.expiredAt == expiredAt)&&(identical(other.payeeWalletId, payeeWalletId) || other.payeeWalletId == payeeWalletId)&&(identical(other.transactionId, transactionId) || other.transactionId == transactionId)&&(identical(other.issuerAppId, issuerAppId) || other.issuerAppId == issuerAppId)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType,id,status,currency,const DeepCollectionEquality().hash(remarks),appIdentifier,const DeepCollectionEquality().hash(_meta),amount,expiredAt,payeeWalletId,payeeWallet,transactionId,transaction,issuerAppId,const DeepCollectionEquality().hash(issuerApp),createdAt,updatedAt,deletedAt);
int get hashCode => Object.hash(runtimeType,id,status,currency,remarks,appIdentifier,const DeepCollectionEquality().hash(_meta),amount,expiredAt,payeeWalletId,transactionId,issuerAppId,createdAt,updatedAt,deletedAt);
@override
String toString() {
return 'SnWalletOrder(id: $id, status: $status, currency: $currency, remarks: $remarks, appIdentifier: $appIdentifier, meta: $meta, amount: $amount, expiredAt: $expiredAt, payeeWalletId: $payeeWalletId, payeeWallet: $payeeWallet, transactionId: $transactionId, transaction: $transaction, issuerAppId: $issuerAppId, issuerApp: $issuerApp, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
return 'SnWalletOrder(id: $id, status: $status, currency: $currency, remarks: $remarks, appIdentifier: $appIdentifier, meta: $meta, amount: $amount, expiredAt: $expiredAt, payeeWalletId: $payeeWalletId, transactionId: $transactionId, issuerAppId: $issuerAppId, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
}
@@ -1842,11 +1812,11 @@ abstract mixin class _$SnWalletOrderCopyWith<$Res> implements $SnWalletOrderCopy
factory _$SnWalletOrderCopyWith(_SnWalletOrder value, $Res Function(_SnWalletOrder) _then) = __$SnWalletOrderCopyWithImpl;
@override @useResult
$Res call({
String id, int status, String currency, dynamic remarks, String appIdentifier, Map<String, dynamic> meta, int amount, DateTime expiredAt, String? payeeWalletId, SnWallet? payeeWallet, String? transactionId, SnTransaction? transaction, String? issuerAppId, dynamic issuerApp, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
String id, int status, String currency, String? remarks, String appIdentifier, Map<String, dynamic> meta, int amount, DateTime expiredAt, String? payeeWalletId, String? transactionId, String? issuerAppId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
});
@override $SnWalletCopyWith<$Res>? get payeeWallet;@override $SnTransactionCopyWith<$Res>? get transaction;
}
/// @nodoc
@@ -1859,54 +1829,27 @@ class __$SnWalletOrderCopyWithImpl<$Res>
/// Create a copy of SnWalletOrder
/// with the given fields replaced by the non-null parameter values.
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? status = null,Object? currency = null,Object? remarks = freezed,Object? appIdentifier = null,Object? meta = null,Object? amount = null,Object? expiredAt = null,Object? payeeWalletId = freezed,Object? payeeWallet = freezed,Object? transactionId = freezed,Object? transaction = freezed,Object? issuerAppId = freezed,Object? issuerApp = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? status = null,Object? currency = null,Object? remarks = freezed,Object? appIdentifier = null,Object? meta = null,Object? amount = null,Object? expiredAt = null,Object? payeeWalletId = freezed,Object? transactionId = freezed,Object? issuerAppId = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
return _then(_SnWalletOrder(
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
as String,status: null == status ? _self.status : status // ignore: cast_nullable_to_non_nullable
as int,currency: null == currency ? _self.currency : currency // ignore: cast_nullable_to_non_nullable
as String,remarks: freezed == remarks ? _self.remarks : remarks // ignore: cast_nullable_to_non_nullable
as dynamic,appIdentifier: null == appIdentifier ? _self.appIdentifier : appIdentifier // ignore: cast_nullable_to_non_nullable
as String?,appIdentifier: null == appIdentifier ? _self.appIdentifier : appIdentifier // ignore: cast_nullable_to_non_nullable
as String,meta: null == meta ? _self._meta : meta // ignore: cast_nullable_to_non_nullable
as Map<String, dynamic>,amount: null == amount ? _self.amount : amount // ignore: cast_nullable_to_non_nullable
as int,expiredAt: null == expiredAt ? _self.expiredAt : expiredAt // ignore: cast_nullable_to_non_nullable
as DateTime,payeeWalletId: freezed == payeeWalletId ? _self.payeeWalletId : payeeWalletId // ignore: cast_nullable_to_non_nullable
as String?,payeeWallet: freezed == payeeWallet ? _self.payeeWallet : payeeWallet // ignore: cast_nullable_to_non_nullable
as SnWallet?,transactionId: freezed == transactionId ? _self.transactionId : transactionId // ignore: cast_nullable_to_non_nullable
as String?,transaction: freezed == transaction ? _self.transaction : transaction // ignore: cast_nullable_to_non_nullable
as SnTransaction?,issuerAppId: freezed == issuerAppId ? _self.issuerAppId : issuerAppId // ignore: cast_nullable_to_non_nullable
as String?,issuerApp: freezed == issuerApp ? _self.issuerApp : issuerApp // ignore: cast_nullable_to_non_nullable
as dynamic,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
as String?,transactionId: freezed == transactionId ? _self.transactionId : transactionId // ignore: cast_nullable_to_non_nullable
as String?,issuerAppId: freezed == issuerAppId ? _self.issuerAppId : issuerAppId // ignore: cast_nullable_to_non_nullable
as String?,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
as DateTime?,
));
}
/// Create a copy of SnWalletOrder
/// with the given fields replaced by the non-null parameter values.
@override
@pragma('vm:prefer-inline')
$SnWalletCopyWith<$Res>? get payeeWallet {
if (_self.payeeWallet == null) {
return null;
}
return $SnWalletCopyWith<$Res>(_self.payeeWallet!, (value) {
return _then(_self.copyWith(payeeWallet: value));
});
}/// Create a copy of SnWalletOrder
/// with the given fields replaced by the non-null parameter values.
@override
@pragma('vm:prefer-inline')
$SnTransactionCopyWith<$Res>? get transaction {
if (_self.transaction == null) {
return null;
}
return $SnTransactionCopyWith<$Res>(_self.transaction!, (value) {
return _then(_self.copyWith(transaction: value));
});
}
}
// dart format on

View File

@@ -195,25 +195,14 @@ _SnWalletOrder _$SnWalletOrderFromJson(Map<String, dynamic> json) =>
id: json['id'] as String,
status: (json['status'] as num).toInt(),
currency: json['currency'] as String,
remarks: json['remarks'],
remarks: json['remarks'] as String?,
appIdentifier: json['app_identifier'] as String,
meta: json['meta'] as Map<String, dynamic>? ?? const {},
amount: (json['amount'] as num).toInt(),
expiredAt: DateTime.parse(json['expired_at'] as String),
payeeWalletId: json['payee_wallet_id'] as String?,
payeeWallet:
json['payee_wallet'] == null
? null
: SnWallet.fromJson(json['payee_wallet'] as Map<String, dynamic>),
transactionId: json['transaction_id'] as String?,
transaction:
json['transaction'] == null
? null
: SnTransaction.fromJson(
json['transaction'] as Map<String, dynamic>,
),
issuerAppId: json['issuer_app_id'] as String?,
issuerApp: json['issuer_app'],
createdAt: DateTime.parse(json['created_at'] as String),
updatedAt: DateTime.parse(json['updated_at'] as String),
deletedAt:
@@ -233,11 +222,8 @@ Map<String, dynamic> _$SnWalletOrderToJson(_SnWalletOrder instance) =>
'amount': instance.amount,
'expired_at': instance.expiredAt.toIso8601String(),
'payee_wallet_id': instance.payeeWalletId,
'payee_wallet': instance.payeeWallet?.toJson(),
'transaction_id': instance.transactionId,
'transaction': instance.transaction?.toJson(),
'issuer_app_id': instance.issuerAppId,
'issuer_app': instance.issuerApp,
'created_at': instance.createdAt.toIso8601String(),
'updated_at': instance.updatedAt.toIso8601String(),
'deleted_at': instance.deletedAt?.toIso8601String(),

651
lib/pods/activity_rpc.dart Normal file
View File

@@ -0,0 +1,651 @@
import 'dart:async';
import 'dart:convert';
import 'dart:developer' as developer;
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:island/pods/network.dart';
import 'package:shelf/shelf.dart';
import 'package:shelf/shelf_io.dart' as shelf_io;
import 'package:shelf_web_socket/shelf_web_socket.dart';
import 'package:web_socket_channel/web_socket_channel.dart';
import 'package:path/path.dart' as path;
const String kRpcLogPrefix = 'arRPC.websocket';
const String kRpcIpcLogPrefix = 'arRPC.ipc';
// IPC Constants
const String kIpcBasePath = 'discord-ipc';
// IPC Packet Types
class IpcTypes {
static const int handshake = 0;
static const int frame = 1;
static const int close = 2;
static const int ping = 3;
static const int pong = 4;
}
// IPC Close Codes
class IpcCloseCodes {
static const int closeNormal = 1000;
static const int closeUnsupported = 1003;
static const int closeAbnormal = 1006;
}
// IPC Error Codes
class IpcErrorCodes {
static const int invalidClientId = 4000;
static const int invalidOrigin = 4001;
static const int rateLimited = 4002;
static const int tokenRevoked = 4003;
static const int invalidVersion = 4004;
static const int invalidEncoding = 4005;
}
class ActivityRpcServer {
static const List<int> portRange = [6463, 6472]; // Ports 64636472
Map<String, Function>
handlers; // {connection: (socket), message: (socket, data), close: (socket)}
HttpServer? _httpServer;
ServerSocket? _ipcServer;
final List<WebSocketChannel> _wsSockets = [];
final List<_IpcSocketWrapper> _ipcSockets = [];
ActivityRpcServer(this.handlers);
void updateHandlers(Map<String, Function> newHandlers) {
handlers = newHandlers;
}
// Encode IPC packet
static Uint8List encodeIpcPacket(int type, Map<String, dynamic> data) {
final jsonData = jsonEncode(data);
final dataBytes = utf8.encode(jsonData);
final dataSize = dataBytes.length;
final buffer = ByteData(8 + dataSize);
buffer.setInt32(0, type, Endian.little);
buffer.setInt32(4, dataSize, Endian.little);
buffer.buffer.asUint8List().setRange(8, 8 + dataSize, dataBytes);
return buffer.buffer.asUint8List();
}
Future<String> _getMacOsSystemTmpDir() async {
final result = await Process.run('getconf', ['DARWIN_USER_TEMP_DIR']);
return (result.stdout as String).trim();
}
// Find available IPC socket path
Future<String> _findAvailableIpcPath() async {
// Build list of directories to try, with macOS-specific handling
final baseDirs = <String>[];
if (Platform.isMacOS) {
try {
final macTempDir = await _getMacOsSystemTmpDir();
if (macTempDir.isNotEmpty) {
baseDirs.add(macTempDir);
}
} catch (e) {
developer.log(
'Failed to get macOS system temp dir: $e',
name: kRpcIpcLogPrefix,
);
}
}
// Add other standard directories
final otherDirs = [
Platform.environment['XDG_RUNTIME_DIR'], // User runtime directory
Platform.environment['TMPDIR'], // App container temp (fallback)
Platform.environment['TMP'],
Platform.environment['TEMP'],
'/tmp', // System temp directory - most compatible
];
baseDirs.addAll(
otherDirs.where((dir) => dir != null && dir.isNotEmpty).cast<String>(),
);
for (final baseDir in baseDirs) {
for (int i = 0; i < 10; i++) {
final socketPath = path.join(baseDir, '$kIpcBasePath-$i');
try {
final socket = await ServerSocket.bind(
InternetAddress(socketPath, type: InternetAddressType.unix),
0,
);
socket.close();
// Clean up the test socket
try {
await File(socketPath).delete();
} catch (_) {}
developer.log(
'IPC socket will be created at: $socketPath',
name: kRpcIpcLogPrefix,
);
return socketPath;
} catch (e) {
// Path not available, try next
if (i == 0) {
// Log only for the first attempt per directory
developer.log(
'IPC path $socketPath not available: $e',
name: kRpcIpcLogPrefix,
);
}
continue;
}
}
}
throw Exception(
'No available IPC socket paths found in any temp directory',
);
}
// Start the WebSocket server
Future<void> start() async {
int port = portRange[0];
bool wsSuccess = false;
// Start WebSocket server
while (port <= portRange[1]) {
developer.log('trying port $port', name: kRpcLogPrefix);
try {
// Start HTTP server
_httpServer = await HttpServer.bind(InternetAddress.loopbackIPv4, port);
developer.log('listening on $port', name: kRpcLogPrefix);
// Handle WebSocket upgrades
shelf_io.serveRequests(_httpServer!, (Request request) async {
developer.log('new request', name: kRpcLogPrefix);
if (request.headers['upgrade']?.toLowerCase() == 'websocket') {
final handler = webSocketHandler((WebSocketChannel channel, _) {
_wsSockets.add(channel);
_onWsConnection(channel, request);
});
return handler(request);
}
developer.log(
'new request disposed due to not websocket',
name: kRpcLogPrefix,
);
return Response.notFound('Not a WebSocket request');
});
wsSuccess = true;
break;
} catch (e) {
if (e is SocketException && e.osError?.errorCode == 98) {
// EADDRINUSE
developer.log('$port in use!', name: kRpcLogPrefix);
} else {
developer.log('http error: $e', name: kRpcLogPrefix);
}
port++;
}
}
if (!wsSuccess) {
throw Exception(
'Failed to bind to any port in range ${portRange[0]}${portRange[1]}',
);
}
// Start IPC server (skip on macOS due to sandboxing)
final shouldStartIpc = !Platform.isMacOS;
if (shouldStartIpc) {
try {
final ipcPath = await _findAvailableIpcPath();
_ipcServer = await ServerSocket.bind(
InternetAddress(ipcPath, type: InternetAddressType.unix),
0,
);
developer.log('IPC listening at $ipcPath', name: kRpcIpcLogPrefix);
_ipcServer!.listen((Socket socket) {
_onIpcConnection(socket);
});
} catch (e) {
developer.log('IPC server error: $e', name: kRpcIpcLogPrefix);
// Continue without IPC if it fails
}
} else {
developer.log(
'IPC server disabled on macOS in production mode due to sandboxing',
name: kRpcIpcLogPrefix,
);
}
}
// Stop the server
Future<void> stop() async {
// Stop WebSocket server
for (var socket in _wsSockets) {
await socket.sink.close();
}
_wsSockets.clear();
await _httpServer?.close();
// Stop IPC server
for (var socket in _ipcSockets) {
socket.close();
}
_ipcSockets.clear();
await _ipcServer?.close();
developer.log('servers stopped', name: kRpcLogPrefix);
}
// Handle new WebSocket connection
void _onWsConnection(WebSocketChannel socket, Request request) {
// Parse query parameters
final uri = request.url;
final params = uri.queryParameters;
final ver = int.tryParse(params['v'] ?? '1') ?? 1;
final encoding = params['encoding'] ?? 'json';
final clientId = params['client_id'] ?? '';
final origin = request.headers['origin'] ?? '';
developer.log(
'new WS connection! origin: $origin, params: $params',
name: kRpcLogPrefix,
);
// Validate origin
if (origin.isNotEmpty &&
![
'https://discord.com',
'https://ptb.discord.com',
'https://canary.discord.com',
].contains(origin)) {
developer.log('disallowed origin: $origin', name: kRpcLogPrefix);
socket.sink.close();
return;
}
// Validate encoding
if (encoding != 'json') {
developer.log(
'unsupported encoding requested: $encoding',
name: kRpcLogPrefix,
);
socket.sink.close();
return;
}
// Validate version
if (ver != 1) {
developer.log('unsupported version requested: $ver', name: kRpcLogPrefix);
socket.sink.close();
return;
}
// Store client info on socket
final socketWithMeta = _WsSocketWrapper(socket, clientId, encoding);
// Set up event listeners
socket.stream.listen(
(data) => _onWsMessage(socketWithMeta, data),
onError: (e) {
developer.log('WS socket error: $e', name: kRpcLogPrefix);
},
onDone: () {
developer.log('WS socket closed', name: kRpcLogPrefix);
handlers['close']?.call(socketWithMeta);
_wsSockets.remove(socket);
},
);
// Notify handler of new connection
handlers['connection']?.call(socketWithMeta);
}
// Handle new IPC connection
void _onIpcConnection(Socket socket) {
developer.log('new IPC connection!', name: kRpcIpcLogPrefix);
final socketWrapper = _IpcSocketWrapper(socket);
_ipcSockets.add(socketWrapper);
// Set up event listeners
socket.listen(
(data) => _onIpcData(socketWrapper, data),
onError: (e) {
developer.log('IPC socket error: $e', name: kRpcIpcLogPrefix);
socket.close();
},
onDone: () {
developer.log('IPC socket closed', name: kRpcIpcLogPrefix);
handlers['close']?.call(socketWrapper);
_ipcSockets.remove(socketWrapper);
},
);
}
// Handle incoming WebSocket message
void _onWsMessage(_WsSocketWrapper socket, dynamic data) {
try {
final jsonData = jsonDecode(data as String);
developer.log('WS message: $jsonData', name: kRpcLogPrefix);
handlers['message']?.call(socket, jsonData);
} catch (e) {
developer.log('WS message parse error: $e', name: kRpcLogPrefix);
}
}
// Handle incoming IPC data
void _onIpcData(_IpcSocketWrapper socket, List<int> data) {
try {
socket.addData(data);
final packets = socket.readPackets();
for (final packet in packets) {
_handleIpcPacket(socket, packet);
}
} catch (e) {
developer.log('IPC data error: $e', name: kRpcIpcLogPrefix);
socket.closeWithCode(IpcCloseCodes.closeUnsupported, e.toString());
}
}
// Handle IPC packet
void _handleIpcPacket(_IpcSocketWrapper socket, _IpcPacket packet) {
switch (packet.type) {
case IpcTypes.ping:
developer.log('IPC ping received', name: kRpcIpcLogPrefix);
socket.sendPong(packet.data);
break;
case IpcTypes.pong:
developer.log('IPC pong received', name: kRpcIpcLogPrefix);
// Handle pong if needed
break;
case IpcTypes.handshake:
if (socket.handshook) {
throw Exception('Already handshook');
}
socket.handshook = true;
_onIpcHandshake(socket, packet.data);
break;
case IpcTypes.frame:
if (!socket.handshook) {
throw Exception('Need to handshake first');
}
developer.log('IPC frame: ${packet.data}', name: kRpcIpcLogPrefix);
handlers['message']?.call(socket, packet.data);
break;
case IpcTypes.close:
socket.close();
break;
default:
throw Exception('Invalid packet type: ${packet.type}');
}
}
// Handle IPC handshake
void _onIpcHandshake(_IpcSocketWrapper socket, Map<String, dynamic> params) {
developer.log('IPC handshake: $params', name: kRpcIpcLogPrefix);
final ver = int.tryParse(params['v']?.toString() ?? '1') ?? 1;
final clientId = params['client_id']?.toString() ?? '';
// Validate version
if (ver != 1) {
developer.log(
'IPC unsupported version requested: $ver',
name: kRpcIpcLogPrefix,
);
socket.closeWithCode(IpcErrorCodes.invalidVersion);
return;
}
// Validate client ID
if (clientId.isEmpty) {
developer.log('IPC client ID required', name: kRpcIpcLogPrefix);
socket.closeWithCode(IpcErrorCodes.invalidClientId);
return;
}
socket.clientId = clientId;
// Notify handler of new connection
handlers['connection']?.call(socket);
}
}
// WebSocket wrapper
class _WsSocketWrapper {
final WebSocketChannel channel;
final String clientId;
final String encoding;
_WsSocketWrapper(this.channel, this.clientId, this.encoding);
void send(Map<String, dynamic> msg) {
developer.log('WS sending: $msg', name: kRpcLogPrefix);
channel.sink.add(jsonEncode(msg));
}
}
// IPC wrapper
class _IpcSocketWrapper {
final Socket socket;
String clientId = '';
bool handshook = false;
final List<int> _buffer = [];
_IpcSocketWrapper(this.socket);
void addData(List<int> data) {
_buffer.addAll(data);
}
void send(Map<String, dynamic> msg) {
developer.log('IPC sending: $msg', name: kRpcIpcLogPrefix);
final packet = ActivityRpcServer.encodeIpcPacket(IpcTypes.frame, msg);
socket.add(packet);
}
void sendPong(dynamic data) {
final packet = ActivityRpcServer.encodeIpcPacket(IpcTypes.pong, data ?? {});
socket.add(packet);
}
void close() {
socket.close();
}
void closeWithCode(int code, [String message = '']) {
final closeData = {'code': code, 'message': message};
final packet = ActivityRpcServer.encodeIpcPacket(IpcTypes.close, closeData);
socket.add(packet);
socket.close();
}
List<_IpcPacket> readPackets() {
final packets = <_IpcPacket>[];
while (_buffer.length >= 8) {
final buffer = Uint8List.fromList(_buffer);
final byteData = ByteData.view(buffer.buffer);
final type = byteData.getInt32(0, Endian.little);
final dataSize = byteData.getInt32(4, Endian.little);
if (_buffer.length < 8 + dataSize) break;
final dataBytes = _buffer.sublist(8, 8 + dataSize);
final jsonStr = utf8.decode(dataBytes);
final jsonData = jsonDecode(jsonStr);
packets.add(_IpcPacket(type, jsonData));
_buffer.removeRange(0, 8 + dataSize);
}
return packets;
}
}
// IPC Packet structure
class _IpcPacket {
final int type;
final Map<String, dynamic> data;
_IpcPacket(this.type, this.data);
}
// State management for server status and activities
class ServerState {
final String status;
final List<String> activities;
ServerState({required this.status, this.activities = const []});
ServerState copyWith({String? status, List<String>? activities}) {
return ServerState(
status: status ?? this.status,
activities: activities ?? this.activities,
);
}
}
class ServerStateNotifier extends StateNotifier<ServerState> {
final ActivityRpcServer server;
ServerStateNotifier(this.server)
: super(ServerState(status: 'Server not started'));
Future<void> start() async {
// Only start server on desktop platforms
if (!Platform.isAndroid && !Platform.isIOS && !kIsWeb) {
try {
await server.start();
state = state.copyWith(status: 'Server running');
} catch (e) {
state = state.copyWith(status: 'Server failed: $e');
}
} else {
state = state.copyWith(status: 'Server disabled on mobile/web');
}
}
void updateStatus(String status) {
state = state.copyWith(status: status);
}
void addActivity(String activity) {
state = state.copyWith(activities: [...state.activities, activity]);
}
}
// Providers
final rpcServerStateProvider =
StateNotifierProvider<ServerStateNotifier, ServerState>((ref) {
final server = ActivityRpcServer({});
final notifier = ServerStateNotifier(server);
server.updateHandlers({
'connection': (socket) {
final clientId =
socket is _WsSocketWrapper
? socket.clientId
: (socket as _IpcSocketWrapper).clientId;
notifier.updateStatus('Client connected (ID: $clientId)');
// Send READY event
socket.send({
'cmd': 'DISPATCH',
'data': {
'v': 1,
'config': {
'cdn_host': 'fake.cdn',
'api_endpoint': '//fake.api',
'environment': 'dev',
},
'user': {
'id': 'fake_user_id',
'username': 'FakeUser',
'discriminator': '0001',
'avatar': null,
'bot': false,
},
},
'evt': 'READY',
'nonce': '12345', // Should be dynamic
});
},
'message': (socket, dynamic data) async {
if (data['cmd'] == 'SET_ACTIVITY') {
notifier.addActivity(
'Activity: ${data['args']['activity']['details'] ?? 'Unknown'}',
);
// Call setRemoteActivityStatus
final label = data['args']['activity']['details'] ?? 'Unknown';
final appId = socket.clientId;
try {
await setRemoteActivityStatus(ref, label, appId);
} catch (e) {
developer.log(
'Failed to set remote activity status: $e',
name: kRpcLogPrefix,
);
}
// Echo back success
socket.send({
'cmd': 'SET_ACTIVITY',
'data': data['args']['activity'],
'evt': null,
'nonce': data['nonce'],
});
}
},
'close': (socket) async {
notifier.updateStatus('Client disconnected');
final appId = socket.clientId;
try {
await unsetRemoteActivityStatus(ref, appId);
} catch (e) {
developer.log(
'Failed to unset remote activity status: $e',
name: kRpcLogPrefix,
);
}
},
});
return notifier;
});
final rpcServerProvider = Provider<ActivityRpcServer>((ref) {
final notifier = ref.watch(rpcServerStateProvider.notifier);
return notifier.server;
});
Future<void> setRemoteActivityStatus(
Ref ref,
String label,
String appId,
) async {
final apiClient = ref.read(apiClientProvider);
await apiClient.post(
'/id/accounts/me/statuses',
data: {
'is_invisible': false,
'is_not_disturb': false,
'is_automated': true,
'label': label,
'app_identifier': appId,
},
);
}
Future<void> unsetRemoteActivityStatus(Ref ref, String appId) async {
final apiClient = ref.read(apiClientProvider);
await apiClient.delete(
'/id/accounts/me/statuses',
queryParameters: {'app': appId},
);
}

View File

@@ -789,11 +789,8 @@ class LevelingScreen extends HookConsumerWidget {
if (context.mounted) showLoadingModal(context);
if (paidOrder != null) {
await client.post(
'/id/subscriptions/order/handle',
data: {'order_id': paidOrder.id},
);
// Wait for server to handle order
await Future.delayed(const Duration(seconds: 1));
ref.invalidate(accountStellarSubscriptionProvider);
ref.read(userInfoProvider.notifier).fetchUser();
if (context.mounted) {

View File

@@ -1,3 +1,4 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:gap/gap.dart';
import 'package:go_router/go_router.dart';
@@ -10,6 +11,7 @@ import 'package:material_symbols_icons/symbols.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:riverpod_paging_utils/riverpod_paging_utils.dart';
import 'package:island/widgets/extended_refresh_indicator.dart';
import 'package:styled_widget/styled_widget.dart';
part 'poll_list.g.dart';
@@ -117,14 +119,14 @@ class CreatorPollListScreen extends HookConsumerWidget {
}
}
class _CreatorPollItem extends StatelessWidget {
class _CreatorPollItem extends HookConsumerWidget {
final String pubName;
const _CreatorPollItem({required this.pollWithStats, required this.pubName});
final SnPollWithStats pollWithStats;
@override
Widget build(BuildContext context) {
Widget build(BuildContext context, WidgetRef ref) {
final theme = Theme.of(context);
final ended = pollWithStats.endedAt;
final endedText =
@@ -167,7 +169,7 @@ class _CreatorPollItem extends StatelessWidget {
children: [
const Icon(Symbols.edit),
const Gap(16),
Text('Edit'),
Text('edit').tr(),
],
),
onTap: () {
@@ -177,6 +179,61 @@ class _CreatorPollItem extends StatelessWidget {
);
},
),
PopupMenuItem(
child: Row(
children: [
const Icon(Symbols.delete, color: Colors.red),
const Gap(16),
Text('delete').tr().textColor(Colors.red),
],
),
onTap: () async {
final confirmed = await showDialog<bool>(
context: context,
builder:
(context) => AlertDialog(
title: Text('Delete Poll'),
content: Text(
'Are you sure you want to delete this poll?',
),
actions: [
TextButton(
onPressed:
() => Navigator.of(context).pop(false),
child: Text('Cancel'),
),
TextButton(
onPressed:
() => Navigator.of(context).pop(true),
child: Text('Delete'),
),
],
),
);
if (confirmed == true) {
try {
final client = ref.read(apiClientProvider);
await client.delete(
'/sphere/polls/${pollWithStats.id}',
);
ref.invalidate(pollListNotifierProvider(pubName));
if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Poll deleted successfully'),
),
);
}
} catch (e) {
if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Failed to delete poll')),
);
}
}
}
},
),
],
),
onTap: () {

View File

@@ -10,6 +10,7 @@ import 'package:island/pods/network.dart';
import 'package:island/widgets/alert.dart';
import 'package:island/models/poll.dart';
import 'package:island/widgets/app_scaffold.dart';
import 'package:styled_widget/styled_widget.dart';
import 'package:uuid/uuid.dart';
import 'package:easy_localization/easy_localization.dart';
@@ -516,8 +517,7 @@ class PollEditorScreen extends ConsumerWidget {
if (model.questions.isEmpty)
_EmptyState(
title: 'pollNoQuestionsYet'.tr(),
subtitle:
'pollNoQuestionsHint'.tr(),
subtitle: 'pollNoQuestionsHint'.tr(),
)
else
ReorderableListView.builder(
@@ -579,24 +579,32 @@ class PollEditorScreen extends ConsumerWidget {
),
),
),
Row(
children: [
OutlinedButton.icon(
onPressed: () {
Navigator.of(context).maybePop();
},
icon: const Icon(Icons.close),
label: Text('cancel'.tr()),
),
const Spacer(),
FilledButton.icon(
onPressed: () {
_submitPoll(context, ref);
},
icon: const Icon(Icons.cloud_upload_outlined),
label: Text(model.id == null ? 'create'.tr() : 'update'.tr()),
),
],
Material(
elevation: 2,
color: Theme.of(context).colorScheme.surfaceContainer,
child: Row(
children: [
OutlinedButton.icon(
onPressed: () {
Navigator.of(context).maybePop();
},
icon: const Icon(Icons.close),
label: Text('cancel'.tr()),
),
const Spacer(),
FilledButton.icon(
onPressed: () {
_submitPoll(context, ref);
},
icon: const Icon(Icons.cloud_upload_outlined),
label: Text(model.id == null ? 'create'.tr() : 'update'.tr()),
),
],
).padding(
horizontal: 24,
top: 16,
bottom: MediaQuery.of(context).padding.bottom + 16,
),
),
],
),
@@ -1049,7 +1057,9 @@ class _TextAnswerPreview extends StatelessWidget {
maxLines: long ? 4 : 1,
decoration: InputDecoration(
labelText:
long ? 'pollLongTextAnswerPreview'.tr() : 'pollShortTextAnswerPreview'.tr(),
long
? 'pollLongTextAnswerPreview'.tr()
: 'pollShortTextAnswerPreview'.tr(),
border: const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(16)),
),
@@ -1083,9 +1093,15 @@ class _EmptyState extends StatelessWidget {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('pollNoQuestionsYet'.tr(), style: Theme.of(context).textTheme.titleMedium),
Text(
'pollNoQuestionsYet'.tr(),
style: Theme.of(context).textTheme.titleMedium,
),
const Gap(4),
Text('pollNoQuestionsHint'.tr(), style: Theme.of(context).textTheme.bodyMedium),
Text(
'pollNoQuestionsHint'.tr(),
style: Theme.of(context).textTheme.bodyMedium,
),
],
),
),

View File

@@ -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
}

View File

@@ -13,6 +13,7 @@ import 'package:island/widgets/alert.dart';
import 'package:island/widgets/app_scaffold.dart';
import 'package:island/widgets/extended_refresh_indicator.dart';
import 'package:island/widgets/post/post_item.dart';
import 'package:island/widgets/post/post_award_history_sheet.dart';
import 'package:island/widgets/post/post_pin_sheet.dart';
import 'package:island/widgets/post/post_quick_reply.dart';
import 'package:island/widgets/post/post_replies.dart';
@@ -77,6 +78,22 @@ class PostActionButtons extends HookConsumerWidget {
final isAuthor =
user.value != null && user.value?.id == post.publisher.accountId;
String formatScore(int score) {
if (score >= 1000000) {
double value = score / 1000000;
return value % 1 == 0
? '${value.toInt()}m'
: '${value.toStringAsFixed(1)}m';
} else if (score >= 1000) {
double value = score / 1000;
return value % 1 == 0
? '${value.toInt()}k'
: '${value.toStringAsFixed(1)}k';
} else {
return score.toString();
}
}
final actions = <Widget>[];
const kButtonHeight = 40.0;
@@ -254,6 +271,24 @@ class PostActionButtons extends HookConsumerWidget {
),
];
actions.add(
FilledButton.tonalIcon(
onPressed: () {},
onLongPress: () {
showModalBottomSheet(
context: context,
isScrollControlled: true,
builder: (context) => PostAwardHistorySheet(postId: post.id),
);
},
icon: const Icon(Symbols.star),
label:
post.awardedScore > 0
? Text('${formatScore(post.awardedScore)} pts')
: Text('award').tr(),
),
);
actions.add(
Row(
mainAxisSize: MainAxisSize.min,

View File

@@ -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) {

View File

@@ -7,7 +7,7 @@ part of 'compose_storage_db.dart';
// **************************************************************************
String _$composeStorageNotifierHash() =>
r'4ab4dce85d0a961f096dc3b11505f8f0964dee9d';
r'8baf17aa06b6f69641c20645ba8a3dfe01c97f8c';
/// See also [ComposeStorageNotifier].
@ProviderFor(ComposeStorageNotifier)

View File

@@ -3,6 +3,7 @@ import 'package:bitsdojo_window/bitsdojo_window.dart';
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:island/pods/activity_rpc.dart';
import 'package:island/pods/websocket.dart';
import 'package:island/screens/tray_manager.dart';
import 'package:island/services/notify.dart';
@@ -31,7 +32,10 @@ class AppWrapper extends HookConsumerWidget with TrayListener {
TrayService.instance.initialize(this);
ref.read(rpcServerStateProvider.notifier).start();
return () {
ref.read(rpcServerProvider).stop();
TrayService.instance.dispose(this);
sharingService.dispose();
ntySubs?.cancel();

View File

@@ -1,3 +1,4 @@
import 'dart:async';
import 'dart:convert';
import 'package:dio/dio.dart';
@@ -57,11 +58,21 @@ class CheckInWidget extends HookConsumerWidget {
final todayResult = ref.watch(checkInResultTodayProvider);
final nextNotableDay = ref.watch(nextNotableDayProvider);
// Update time every second for live progress
final currentTime = useState(DateTime.now());
useEffect(() {
final timer = Timer.periodic(const Duration(seconds: 1), (_) {
currentTime.value = DateTime.now();
});
return timer.cancel;
}, []);
final now = currentTime.value;
final userinfo = ref.watch(userInfoProvider);
final isAdult = useMemoized(() {
final birthday = userinfo.value?.profile.birthday;
if (birthday == null) return false;
final now = DateTime.now();
final age =
now.year -
birthday.year -
@@ -72,6 +83,12 @@ class CheckInWidget extends HookConsumerWidget {
return age >= 18;
}, [userinfo]);
final progress = (now.hour * 60.0 + now.minute) / (24 * 60);
final endOfDay = DateTime(now.year, now.month, now.day, 23, 59, 59);
final timeLeft = endOfDay.difference(now);
final timeLeftFormatted =
'${timeLeft.inHours.toString().padLeft(2, '0')}:${(timeLeft.inMinutes % 60).toString().padLeft(2, '0')}:${(timeLeft.inSeconds % 60).toString().padLeft(2, '0')}';
Future<void> checkIn({String? captchatTk}) async {
final client = ref.read(apiClientProvider);
try {
@@ -119,37 +136,22 @@ class CheckInWidget extends HookConsumerWidget {
fill: 1,
size: 16,
).padding(right: 2),
Text(DateFormat('EEE').format(DateTime.now()))
.fontSize(16)
.bold()
.textColor(
Theme.of(context).colorScheme.onSecondaryContainer,
Text(
DateFormat('EEE').format(DateTime.now()),
).fontSize(16).bold(),
Text(
DateFormat('MM/dd').format(DateTime.now()),
).fontSize(16),
Tooltip(
message: timeLeftFormatted,
child: SizedBox(
width: 20,
height: 20,
child: CircularProgressIndicator(
value: progress,
strokeWidth: 2,
),
Text(DateFormat('MM/dd').format(DateTime.now()))
.fontSize(16)
.textColor(
Theme.of(context).colorScheme.onSecondaryContainer,
),
Expanded(
child: AnimatedSwitcher(
duration: const Duration(milliseconds: 300),
child: todayResult.when(
data: (result) {
return Text(
result == null
? 'checkInNone'
: 'checkInResultLevel${result.level}',
textAlign: TextAlign.start,
).tr().fontSize(15).bold();
},
loading:
() =>
Text('checkInNone').tr().fontSize(15).bold(),
error:
(err, stack) =>
Text('error').tr().fontSize(15).bold(),
),
).alignment(Alignment.centerLeft),
),
),
],
),
@@ -171,7 +173,7 @@ class CheckInWidget extends HookConsumerWidget {
),
],
),
const Gap(6),
const Gap(2),
AnimatedSwitcher(
duration: const Duration(milliseconds: 300),
child: todayResult.when(
@@ -224,31 +226,57 @@ class CheckInWidget extends HookConsumerWidget {
],
),
),
IconButton.outlined(
onPressed: () {
if (todayResult.valueOrNull == null) {
checkIn();
} else {
context.pushNamed(
'accountCalendar',
pathParameters: {'name': 'me'},
);
}
},
icon: AnimatedSwitcher(
duration: const Duration(milliseconds: 300),
child: todayResult.when(
data:
(result) => Icon(
Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
spacing: 3,
children: [
AnimatedSwitcher(
duration: const Duration(milliseconds: 300),
child: todayResult.when(
data: (result) {
return Text(
result == null
? Symbols.local_fire_department
: Symbols.event,
key: ValueKey(result != null),
),
loading: () => const Icon(Symbols.refresh),
error: (_, _) => const Icon(Symbols.error),
? 'checkInNone'
: 'checkInResultLevel${result.level}',
textAlign: TextAlign.start,
).tr().fontSize(15).bold();
},
loading: () => Text('checkInNone').tr().fontSize(15).bold(),
error: (err, stack) => Text('error').tr().fontSize(15).bold(),
),
),
),
IconButton.outlined(
iconSize: 16,
visualDensity: const VisualDensity(
horizontal: -3,
vertical: -2,
),
onPressed: () {
if (todayResult.valueOrNull == null) {
checkIn();
} else {
context.pushNamed(
'accountCalendar',
pathParameters: {'name': 'me'},
);
}
},
icon: AnimatedSwitcher(
duration: const Duration(milliseconds: 300),
child: todayResult.when(
data:
(result) => Icon(
result == null
? Symbols.local_fire_department
: Symbols.event,
key: ValueKey(result != null),
),
loading: () => const Icon(Symbols.refresh),
error: (_, _) => const Icon(Symbols.error),
),
),
),
],
),
],
).padding(horizontal: 16, vertical: 12),

View File

@@ -830,7 +830,7 @@ class _CloudFileListEntry extends HookConsumerWidget {
bg = ImageFiltered(
imageFilter: ImageFilter.blur(sigmaX: 10, sigmaY: 10),
child: CloudFileWidget(
fit: fit,
fit: BoxFit.cover,
item: file,
noBlurhash: true,
useInternalGate: false,

View File

@@ -142,10 +142,6 @@ class _PaymentContentState extends ConsumerState<_PaymentContent> {
// Set initial mode based on stored PIN and biometric support
if (_hasStoredPin && _hasBiometricSupport && widget.enableBiometric) {
_isPinMode = false;
// Automatically trigger biometric authentication
WidgetsBinding.instance.addPostFrameCallback((_) {
_authenticateWithBiometric();
});
} else {
_isPinMode = true;
}

View File

@@ -6,6 +6,8 @@ import 'package:island/models/poll.dart';
import 'package:island/pods/network.dart';
import 'package:island/screens/creators/poll/poll_list.dart';
import 'package:island/services/time.dart';
import 'package:island/widgets/account/account_pfc.dart';
import 'package:island/widgets/content/cloud_files.dart';
import 'package:island/widgets/content/sheet.dart';
import 'package:island/widgets/poll/poll_stats_widget.dart';
import 'package:island/widgets/response.dart';
@@ -134,19 +136,27 @@ class _PollHeader extends StatelessWidget {
),
),
],
),
Text('pollQuestions').tr().fontSize(17).bold(),
for (final q in poll.questions)
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (q.title.isNotEmpty) Text(q.title).bold(),
if (q.description?.isNotEmpty ?? false) Text(q.description!),
PollStatsWidget(question: q, stats: poll.stats),
],
),
).padding(horizontal: 20, top: 16),
ExpansionTile(
title: Text('pollQuestions').tr().fontSize(17).bold(),
tilePadding: EdgeInsets.symmetric(horizontal: 20),
children:
poll.questions
.map(
(q) => Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
if (q.title.isNotEmpty) Text(q.title).bold(),
if (q.description?.isNotEmpty ?? false)
Text(q.description!),
PollStatsWidget(question: q, stats: poll.stats),
],
).padding(horizontal: 20, top: 8, bottom: 16),
)
.toList(),
),
],
).padding(horizontal: 20, vertical: 16);
);
}
}
@@ -207,7 +217,10 @@ class _PollAnswerTile extends StatelessWidget {
@override
Widget build(BuildContext context) {
// Submit date/time (title)
final submitText = answer.createdAt.formatSystem();
final submitText =
answer.account == null
? answer.createdAt.formatSystem()
: '${answer.account!.nick} · ${answer.createdAt.formatSystem()}';
// Compose content from poll questions if provided, otherwise fallback to joined key-values
String content;
@@ -244,10 +257,18 @@ class _PollAnswerTile extends StatelessWidget {
return ListTile(
contentPadding: const EdgeInsets.symmetric(horizontal: 20),
isThreeLine: true,
leading: const CircleAvatar(
radius: 16,
child: Icon(Icons.how_to_vote, size: 16),
),
leading:
answer.account == null
? const CircleAvatar(
radius: 16,
child: Icon(Icons.how_to_vote, size: 16),
)
: AccountPfcGestureDetector(
uname: answer.account!.name,
child: ProfilePictureWidget(
file: answer.account!.profile.picture,
),
),
title: Text(submitText),
subtitle: Text(content),
trailing: null,

View File

@@ -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,

View File

@@ -34,7 +34,7 @@ class ComposeToolbar extends HookConsumerWidget {
}
void saveDraft() {
ComposeLogic.saveDraft(ref, state);
ComposeLogic.saveDraftManually(ref, state, context);
}
void pickPoll() {

View File

@@ -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()),
),
),
],
),
),
],
],
),
);
}
}
@@ -169,7 +176,7 @@ class _DraftItem extends StatelessWidget {
final preview =
content.length > 100 ? '${content.substring(0, 100)}...' : content;
final timeAgo = _formatTimeAgo(draft.updatedAt!);
final visibility = _parseVisibility(draft.visibility);
final visibility = _parseVisibility(draft.visibility).tr();
return Card(
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 4),

View File

@@ -0,0 +1,164 @@
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:island/models/post.dart';
import 'package:island/pods/network.dart';
import 'package:island/widgets/content/sheet.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:riverpod_paging_utils/riverpod_paging_utils.dart';
part 'post_award_history_sheet.g.dart';
@riverpod
class PostAwardListNotifier extends _$PostAwardListNotifier
with CursorPagingNotifierMixin<SnPostAward> {
static const int _pageSize = 20;
@override
Future<CursorPagingData<SnPostAward>> build({required String postId}) {
return fetch(cursor: null);
}
@override
Future<CursorPagingData<SnPostAward>> fetch({required String? cursor}) async {
final client = ref.read(apiClientProvider);
final offset = cursor == null ? 0 : int.parse(cursor);
final queryParams = {'offset': offset, 'take': _pageSize};
final response = await client.get(
'/sphere/posts/$postId/awards',
queryParameters: queryParams,
);
final total = int.parse(response.headers.value('X-Total') ?? '0');
final List<dynamic> data = response.data;
final awards = data.map((json) => SnPostAward.fromJson(json)).toList();
final hasMore = offset + awards.length < total;
final nextCursor = hasMore ? (offset + awards.length).toString() : null;
return CursorPagingData(
items: awards,
hasMore: hasMore,
nextCursor: nextCursor,
);
}
}
class PostAwardHistorySheet extends HookConsumerWidget {
final String postId;
const PostAwardHistorySheet({super.key, required this.postId});
@override
Widget build(BuildContext context, WidgetRef ref) {
final provider = postAwardListNotifierProvider(postId: postId);
return SheetScaffold(
titleText: 'Award History',
child: PagingHelperView(
provider: provider,
futureRefreshable: provider.future,
notifierRefreshable: provider.notifier,
contentBuilder:
(data, widgetCount, endItemView) => ListView.builder(
itemCount: widgetCount,
itemBuilder: (context, index) {
if (index == widgetCount - 1) {
return endItemView;
}
final award = data.items[index];
return Column(
children: [
PostAwardItem(award: award),
const Divider(height: 1),
],
);
},
),
),
);
}
}
class PostAwardItem extends StatelessWidget {
final SnPostAward award;
const PostAwardItem({super.key, required this.award});
String _getAttitudeText(int attitude) {
switch (attitude) {
case 0:
return 'Positive';
case 2:
return 'Negative';
default:
return 'Neutral';
}
}
Color _getAttitudeColor(int attitude, BuildContext context) {
switch (attitude) {
case 0:
return Colors.green;
case 2:
return Colors.red;
default:
return Theme.of(context).colorScheme.onSurfaceVariant;
}
}
@override
Widget build(BuildContext context) {
return ListTile(
leading: CircleAvatar(
backgroundColor: _getAttitudeColor(
award.attitude,
context,
).withOpacity(0.1),
child: Icon(
award.attitude == 0
? Icons.thumb_up
: award.attitude == 2
? Icons.thumb_down
: Icons.thumbs_up_down,
color: _getAttitudeColor(award.attitude, context),
),
),
title: Text(
'${award.amount} pts',
style: Theme.of(
context,
).textTheme.titleMedium?.copyWith(fontWeight: FontWeight.w600),
),
subtitle: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
_getAttitudeText(award.attitude),
style: TextStyle(
color: _getAttitudeColor(award.attitude, context),
fontWeight: FontWeight.w500,
),
),
if (award.message != null && award.message!.isNotEmpty) ...[
const SizedBox(height: 4),
Text(award.message!, style: Theme.of(context).textTheme.bodyMedium),
],
const SizedBox(height: 2),
if (award.createdAt != null) ...[
const SizedBox(height: 2),
Text(
award.createdAt!.toLocal().toString().split('.')[0],
style: Theme.of(context).textTheme.bodySmall?.copyWith(
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
),
],
],
),
isThreeLine: award.message != null && award.message!.isNotEmpty,
contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
);
}
}

View File

@@ -0,0 +1,180 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'post_award_history_sheet.dart';
// **************************************************************************
// RiverpodGenerator
// **************************************************************************
String _$postAwardListNotifierHash() =>
r'492ae59a5dbbfb5c98f863f036023193b6e08668';
/// Copied from Dart SDK
class _SystemHash {
_SystemHash._();
static int combine(int hash, int value) {
// ignore: parameter_assignments
hash = 0x1fffffff & (hash + value);
// ignore: parameter_assignments
hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10));
return hash ^ (hash >> 6);
}
static int finish(int hash) {
// ignore: parameter_assignments
hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3));
// ignore: parameter_assignments
hash = hash ^ (hash >> 11);
return 0x1fffffff & (hash + ((0x00003fff & hash) << 15));
}
}
abstract class _$PostAwardListNotifier
extends BuildlessAutoDisposeAsyncNotifier<CursorPagingData<SnPostAward>> {
late final String postId;
FutureOr<CursorPagingData<SnPostAward>> build({required String postId});
}
/// See also [PostAwardListNotifier].
@ProviderFor(PostAwardListNotifier)
const postAwardListNotifierProvider = PostAwardListNotifierFamily();
/// See also [PostAwardListNotifier].
class PostAwardListNotifierFamily
extends Family<AsyncValue<CursorPagingData<SnPostAward>>> {
/// See also [PostAwardListNotifier].
const PostAwardListNotifierFamily();
/// See also [PostAwardListNotifier].
PostAwardListNotifierProvider call({required String postId}) {
return PostAwardListNotifierProvider(postId: postId);
}
@override
PostAwardListNotifierProvider getProviderOverride(
covariant PostAwardListNotifierProvider provider,
) {
return call(postId: provider.postId);
}
static const Iterable<ProviderOrFamily>? _dependencies = null;
@override
Iterable<ProviderOrFamily>? get dependencies => _dependencies;
static const Iterable<ProviderOrFamily>? _allTransitiveDependencies = null;
@override
Iterable<ProviderOrFamily>? get allTransitiveDependencies =>
_allTransitiveDependencies;
@override
String? get name => r'postAwardListNotifierProvider';
}
/// See also [PostAwardListNotifier].
class PostAwardListNotifierProvider
extends
AutoDisposeAsyncNotifierProviderImpl<
PostAwardListNotifier,
CursorPagingData<SnPostAward>
> {
/// See also [PostAwardListNotifier].
PostAwardListNotifierProvider({required String postId})
: this._internal(
() => PostAwardListNotifier()..postId = postId,
from: postAwardListNotifierProvider,
name: r'postAwardListNotifierProvider',
debugGetCreateSourceHash:
const bool.fromEnvironment('dart.vm.product')
? null
: _$postAwardListNotifierHash,
dependencies: PostAwardListNotifierFamily._dependencies,
allTransitiveDependencies:
PostAwardListNotifierFamily._allTransitiveDependencies,
postId: postId,
);
PostAwardListNotifierProvider._internal(
super._createNotifier, {
required super.name,
required super.dependencies,
required super.allTransitiveDependencies,
required super.debugGetCreateSourceHash,
required super.from,
required this.postId,
}) : super.internal();
final String postId;
@override
FutureOr<CursorPagingData<SnPostAward>> runNotifierBuild(
covariant PostAwardListNotifier notifier,
) {
return notifier.build(postId: postId);
}
@override
Override overrideWith(PostAwardListNotifier Function() create) {
return ProviderOverride(
origin: this,
override: PostAwardListNotifierProvider._internal(
() => create()..postId = postId,
from: from,
name: null,
dependencies: null,
allTransitiveDependencies: null,
debugGetCreateSourceHash: null,
postId: postId,
),
);
}
@override
AutoDisposeAsyncNotifierProviderElement<
PostAwardListNotifier,
CursorPagingData<SnPostAward>
>
createElement() {
return _PostAwardListNotifierProviderElement(this);
}
@override
bool operator ==(Object other) {
return other is PostAwardListNotifierProvider && other.postId == postId;
}
@override
int get hashCode {
var hash = _SystemHash.combine(0, runtimeType.hashCode);
hash = _SystemHash.combine(hash, postId.hashCode);
return _SystemHash.finish(hash);
}
}
@Deprecated('Will be removed in 3.0. Use Ref instead')
// ignore: unused_element
mixin PostAwardListNotifierRef
on AutoDisposeAsyncNotifierProviderRef<CursorPagingData<SnPostAward>> {
/// The parameter `postId` of this provider.
String get postId;
}
class _PostAwardListNotifierProviderElement
extends
AutoDisposeAsyncNotifierProviderElement<
PostAwardListNotifier,
CursorPagingData<SnPostAward>
>
with PostAwardListNotifierRef {
_PostAwardListNotifierProviderElement(super.provider);
@override
String get postId => (origin as PostAwardListNotifierProvider).postId;
}
// ignore_for_file: type=lint
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package

View File

@@ -436,6 +436,7 @@ class PostItem extends HookConsumerWidget {
MarkdownTextContent(
content: translatedText.value!,
isSelectable: isTextSelectable,
attachments: item.attachments,
),
],
)

View File

@@ -141,6 +141,7 @@ class PostReplyPreview extends HookConsumerWidget {
Expanded(
child: MarkdownTextContent(
content: post.content!,
attachments: post.attachments,
).padding(top: 2),
)
else
@@ -210,6 +211,7 @@ class PostReplyPreview extends HookConsumerWidget {
Expanded(
child: MarkdownTextContent(
content: data.value!.content!,
attachments: data.value!.attachments,
),
)
else
@@ -745,7 +747,10 @@ class PostBody extends ConsumerWidget {
style: Theme.of(context).textTheme.bodyMedium,
)
else
MarkdownTextContent(content: '${item.content!}...'),
MarkdownTextContent(
content: '${item.content!}...',
attachments: item.attachments,
),
],
),
)
@@ -784,6 +789,7 @@ class PostBody extends ConsumerWidget {
? '${item.content!}...'
: item.content ?? '',
isSelectable: isTextSelectable,
attachments: item.attachments,
),
if (translationSection != null) translationSection!,
],

View File

@@ -485,10 +485,10 @@ packages:
dependency: "direct main"
description:
name: drift_flutter
sha256: ccfb42bc942e59f81500b16228df59cf8eb40d2fbd96637ff677df923350af7b
sha256: b52bd710f809db11e25259d429d799d034ba1c5224ce6a73fe8419feb980d44c
url: "https://pub.dev"
source: hosted
version: "0.2.5"
version: "0.2.6"
dropdown_button2:
dependency: "direct main"
description:
@@ -2206,7 +2206,7 @@ packages:
source: hosted
version: "2.4.1"
shelf:
dependency: transitive
dependency: "direct main"
description:
name: shelf
sha256: e7dd780a7ffb623c57850b33f43309312fc863fb6aa3d276a754bb299839ef12
@@ -2214,7 +2214,7 @@ packages:
source: hosted
version: "1.4.2"
shelf_web_socket:
dependency: transitive
dependency: "direct main"
description:
name: shelf_web_socket
sha256: "3632775c8e90d6c9712f883e633716432a27758216dfb61bd86a8321c0580925"
@@ -2760,10 +2760,10 @@ packages:
dependency: transitive
description:
name: webrtc_interface
sha256: "86fe3afc81a08481dfb25cf14a5a94e27062ecef25544783f352c914e0bbc1ca"
sha256: "2e604a31703ad26781782fb14fa8a4ee621154ee2c513d2b9938e486fa695233"
url: "https://pub.dev"
source: hosted
version: "1.2.2+hotfix.2"
version: "1.3.0"
win32:
dependency: transitive
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
# 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.
version: 3.2.0+131
version: 3.2.0+132
environment:
sdk: ^3.7.2
@@ -85,7 +85,7 @@ dependencies:
web_socket_channel: ^3.0.3
material_symbols_icons: ^4.2872.0
drift: ^2.28.1
drift_flutter: ^0.2.5
drift_flutter: ^0.2.6
path: ^1.9.1
collection: ^1.19.1
markdown_editor_plus: ^0.2.15
@@ -133,7 +133,7 @@ dependencies:
waveform_flutter: ^1.2.0
flutter_app_update: ^3.2.2
archive: ^4.0.7
process_run: ^1.2.0
process_run: ^1.2.4
firebase_crashlytics: ^5.0.1
firebase_analytics: ^12.0.1
material_color_utilities: ^0.11.1
@@ -145,6 +145,8 @@ dependencies:
flutter_local_notifications: ^19.4.1
wakelock_plus: ^1.3.2
slide_countdown: ^2.0.2
shelf: ^1.4.2
shelf_web_socket: ^3.0.0
dev_dependencies:
flutter_test: