Compare commits
55 Commits
3.2.0+125
...
9e40ed4600
Author | SHA1 | Date | |
---|---|---|---|
|
9e40ed4600 | ||
|
c90e6fe661 | ||
|
569483300d | ||
|
bab602d98b | ||
|
b4f2bb803a | ||
|
03bfed6f46 | ||
|
f98e5a0aec | ||
|
3d473e2fec | ||
|
0b6efa373a | ||
|
9b60e96cde | ||
|
81cd9b2082 | ||
|
923d5d7514 | ||
|
7169aff841 | ||
|
fac3efb50c | ||
|
e809aadaea | ||
|
f33b569221 | ||
|
e5f2e2d146 | ||
|
11368d064f | ||
|
246b163aec | ||
|
10e0d2fe5f | ||
|
99e10cb612 | ||
|
1db6941431 | ||
|
8370da4fe3 | ||
|
2bdf7029e9 | ||
|
86682a3a9a | ||
|
c3925e81b5 | ||
|
6f1f488490 | ||
|
31b2de2e46 | ||
|
412dcfa62a | ||
|
ffdc7e81ae | ||
|
1d3357803d | ||
|
6c48aa2356 | ||
|
466e354679 | ||
|
5d4b896f70 | ||
|
a04dffdfe8 | ||
|
ff871943cf | ||
|
1a892ab227 | ||
|
af1b303211 | ||
|
6fd702eba8 | ||
|
d220d43cd2 | ||
|
6892afb974 | ||
|
007b46b080 | ||
|
67d130dc34 | ||
|
7e923c77fe | ||
|
a593b52812 | ||
|
520dc80303 | ||
|
001897bbcd | ||
|
bab29c23e3 | ||
|
76b39f2df3 | ||
|
509b3e145b | ||
|
2b80ebc2d0 | ||
|
0ab908dd2a | ||
|
6007467e7a | ||
|
3745157c42 | ||
|
94481ec7bd |
Binary file not shown.
Before Width: | Height: | Size: 70 KiB |
41
android/app/src/main/res/drawable/ic_notification.xml
Normal file
41
android/app/src/main/res/drawable/ic_notification.xml
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="192dp"
|
||||||
|
android:height="192dp"
|
||||||
|
android:viewportWidth="192"
|
||||||
|
android:viewportHeight="192">
|
||||||
|
<path
|
||||||
|
android:pathData="M54,147h86"
|
||||||
|
android:strokeLineJoin="round"
|
||||||
|
android:strokeWidth="12"
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:strokeColor="#000"
|
||||||
|
android:strokeLineCap="round"/>
|
||||||
|
<path
|
||||||
|
android:pathData="M57,111s-2,-4.5 -2,-10m22,22s-4,7 -11,4m9,-22s-2,-4.5 -2,-10"
|
||||||
|
android:strokeLineJoin="round"
|
||||||
|
android:strokeWidth="10"
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:strokeColor="#000"
|
||||||
|
android:strokeLineCap="round"/>
|
||||||
|
<path
|
||||||
|
android:pathData="M54,147a32,32 0,0 1,-12 -61.67A39,39 0,0 1,81 46m59,101a30,30 0,0 0,29.93 -28"
|
||||||
|
android:strokeLineJoin="round"
|
||||||
|
android:strokeWidth="12"
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:strokeColor="#000"
|
||||||
|
android:strokeLineCap="round"/>
|
||||||
|
<path
|
||||||
|
android:pathData="M132,75m-4,0a4,4 0,1 1,8 0a4,4 0,1 1,-8 0"
|
||||||
|
android:strokeLineJoin="round"
|
||||||
|
android:strokeWidth="8"
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:strokeColor="#000"
|
||||||
|
android:strokeLineCap="round"/>
|
||||||
|
<path
|
||||||
|
android:pathData="M112.5,41.22C100.84,47.96 93,60.56 93,75c0,6.38 1.53,12.39 4.24,17.71m69.51,-35.42A38.84,38.84 0,0 1,171 75c0,14.43 -7.84,27.03 -19.49,33.78m-0.79,-43.32A20.9,20.9 0,0 1,153 75c0,7.77 -4.22,14.56 -10.49,18.19m-21,-36.38C115.22,60.44 111,67.23 111,75a20.9,20.9 0,0 0,2.28 9.53"
|
||||||
|
android:strokeLineJoin="round"
|
||||||
|
android:strokeWidth="10"
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:strokeColor="#000"
|
||||||
|
android:strokeLineCap="round"/>
|
||||||
|
</vector>
|
@@ -334,6 +334,7 @@
|
|||||||
"walletCreate": "Create a Wallet",
|
"walletCreate": "Create a Wallet",
|
||||||
"settingsServerUrl": "Server URL",
|
"settingsServerUrl": "Server URL",
|
||||||
"settingsApplied": "The settings has been applied.",
|
"settingsApplied": "The settings has been applied.",
|
||||||
|
"settingsCustomFontsHelper": "Use comma to seprate.",
|
||||||
"notifications": "Notifications",
|
"notifications": "Notifications",
|
||||||
"posts": "Posts",
|
"posts": "Posts",
|
||||||
"settingsBackgroundImage": "Background Image",
|
"settingsBackgroundImage": "Background Image",
|
||||||
@@ -836,5 +837,36 @@
|
|||||||
"pollAddOption": "Add option",
|
"pollAddOption": "Add option",
|
||||||
"pollOptionLabel": "Option label",
|
"pollOptionLabel": "Option label",
|
||||||
"pollLongTextAnswerPreview": "Long text answer (preview)",
|
"pollLongTextAnswerPreview": "Long text answer (preview)",
|
||||||
"pollShortTextAnswerPreview": "Short text answer (preview)"
|
"pollShortTextAnswerPreview": "Short text answer (preview)",
|
||||||
}
|
"messageJumpNotLoaded": "The referenced message was not loaded, unable to jump to it.",
|
||||||
|
"postUnlinkRealm": "No linked realm",
|
||||||
|
"postSlug": "Slug",
|
||||||
|
"postSlugHint": "The slug can be used to access your post via URL in the webpage, it should be publisher-wide unique.",
|
||||||
|
"attachmentOnDevice": "On-device",
|
||||||
|
"attachmentOnCloud": "On-cloud",
|
||||||
|
"attachments": "Attachments",
|
||||||
|
"publisherCollabInvitation": "Collabration invitations",
|
||||||
|
"publisherCollabInvitationCount": {
|
||||||
|
"zero": "No invitation",
|
||||||
|
"one": "{} available invitation",
|
||||||
|
"other": "{} available invitations"
|
||||||
|
},
|
||||||
|
"failedToLoadUserInfo": "Failed to load user info",
|
||||||
|
"failedToLoadUserInfoNetwork": "It seems be network issue, you can tap the button below to try again.",
|
||||||
|
"failedToLoadUserInfoUnauthorized": "It seems your session has been logged out or not available anymore, you can still try agian to fetch the user info if you want.",
|
||||||
|
"okay": "Okay",
|
||||||
|
"postDetails": "Post Details",
|
||||||
|
"postCount": {
|
||||||
|
"zero": "No posts",
|
||||||
|
"one": "{} post",
|
||||||
|
"other": "{} posts"
|
||||||
|
},
|
||||||
|
"mimeType": "MIME Type",
|
||||||
|
"fileSize": "File Size",
|
||||||
|
"fileHash": "File Hash",
|
||||||
|
"exifData": "EXIF Data",
|
||||||
|
"postShuffle": "Shuffle Posts",
|
||||||
|
"leveling": "Leveling",
|
||||||
|
"levelingHistory": "Leveling History",
|
||||||
|
"stellarProgram": "Stellar Program"
|
||||||
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
BIN
assets/images/media-offline.png
Normal file
BIN
assets/images/media-offline.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 307 KiB |
@@ -245,7 +245,7 @@ PODS:
|
|||||||
- PromisesObjC (= 2.4.0)
|
- PromisesObjC (= 2.4.0)
|
||||||
- receive_sharing_intent (1.8.1):
|
- receive_sharing_intent (1.8.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- record_ios (1.0.0):
|
- record_ios (1.1.0):
|
||||||
- Flutter
|
- Flutter
|
||||||
- SAMKeychain (1.5.3)
|
- SAMKeychain (1.5.3)
|
||||||
- SDWebImage (5.21.1):
|
- SDWebImage (5.21.1):
|
||||||
@@ -510,7 +510,7 @@ SPEC CHECKSUMS:
|
|||||||
PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47
|
PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47
|
||||||
PromisesSwift: 9d77319bbe72ebf6d872900551f7eeba9bce2851
|
PromisesSwift: 9d77319bbe72ebf6d872900551f7eeba9bce2851
|
||||||
receive_sharing_intent: 222384f00ffe7e952bbfabaa9e3967cb87e5fe00
|
receive_sharing_intent: 222384f00ffe7e952bbfabaa9e3967cb87e5fe00
|
||||||
record_ios: fee1c924aa4879b882ebca2b4bce6011bcfc3d8b
|
record_ios: f75fa1d57f840012775c0e93a38a7f3ceea1a374
|
||||||
SAMKeychain: 483e1c9f32984d50ca961e26818a534283b4cd5c
|
SAMKeychain: 483e1c9f32984d50ca961e26818a534283b4cd5c
|
||||||
SDWebImage: f29024626962457f3470184232766516dee8dfea
|
SDWebImage: f29024626962457f3470184232766516dee8dfea
|
||||||
share_plus: 50da8cb520a8f0f65671c6c6a99b3617ed10a58a
|
share_plus: 50da8cb520a8f0f65671c6c6a99b3617ed10a58a
|
||||||
|
@@ -1,484 +0,0 @@
|
|||||||
import 'package:dio/dio.dart';
|
|
||||||
import 'package:island/database/drift_db.dart';
|
|
||||||
import 'package:island/database/message.dart';
|
|
||||||
import 'package:island/models/chat.dart';
|
|
||||||
import 'package:island/models/file.dart';
|
|
||||||
import 'package:island/services/file.dart';
|
|
||||||
import 'package:island/widgets/alert.dart';
|
|
||||||
import 'package:uuid/uuid.dart';
|
|
||||||
|
|
||||||
class MessageRepository {
|
|
||||||
final SnChatRoom room;
|
|
||||||
final SnChatMember identity;
|
|
||||||
final Dio _apiClient;
|
|
||||||
final AppDatabase _database;
|
|
||||||
|
|
||||||
final Map<String, LocalChatMessage> pendingMessages = {};
|
|
||||||
final Map<String, Map<int, double>> fileUploadProgress = {};
|
|
||||||
int? _totalCount;
|
|
||||||
|
|
||||||
MessageRepository(this.room, this.identity, this._apiClient, this._database);
|
|
||||||
|
|
||||||
Future<LocalChatMessage?> getLastMessages() async {
|
|
||||||
final dbMessages = await _database.getMessagesForRoom(
|
|
||||||
room.id,
|
|
||||||
offset: 0,
|
|
||||||
limit: 1,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (dbMessages.isEmpty) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return _database.companionToMessage(dbMessages.first);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<bool> syncMessages() async {
|
|
||||||
final lastMessage = await getLastMessages();
|
|
||||||
if (lastMessage == null) return false;
|
|
||||||
try {
|
|
||||||
final resp = await _apiClient.post(
|
|
||||||
'/sphere/chat/${room.id}/sync',
|
|
||||||
data: {
|
|
||||||
'last_sync_timestamp':
|
|
||||||
lastMessage.toRemoteMessage().updatedAt.millisecondsSinceEpoch,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
final response = MessageSyncResponse.fromJson(resp.data);
|
|
||||||
for (final change in response.changes) {
|
|
||||||
switch (change.action) {
|
|
||||||
case MessageChangeAction.create:
|
|
||||||
await receiveMessage(change.message!);
|
|
||||||
break;
|
|
||||||
case MessageChangeAction.update:
|
|
||||||
await receiveMessageUpdate(change.message!);
|
|
||||||
break;
|
|
||||||
case MessageChangeAction.delete:
|
|
||||||
await receiveMessageDeletion(change.messageId.toString());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
showErrorAlert(err);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<List<LocalChatMessage>> listMessages({
|
|
||||||
int offset = 0,
|
|
||||||
int take = 20,
|
|
||||||
bool synced = false,
|
|
||||||
}) async {
|
|
||||||
try {
|
|
||||||
// For initial load, fetch latest messages in the background to sync.
|
|
||||||
if (offset == 0 && !synced) {
|
|
||||||
// Not awaiting this is intentional, for a quicker UI response.
|
|
||||||
// The UI should rely on a stream from the database to get updates.
|
|
||||||
_fetchAndCacheMessages(room.id, offset: 0, take: take).catchError((_) {
|
|
||||||
// Best effort, errors will be handled by later fetches.
|
|
||||||
return <LocalChatMessage>[];
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
final localMessages = await _getCachedMessages(
|
|
||||||
room.id,
|
|
||||||
offset: offset,
|
|
||||||
take: take,
|
|
||||||
);
|
|
||||||
|
|
||||||
// If local cache has messages, return them. This is the common case for scrolling up.
|
|
||||||
if (localMessages.isNotEmpty) {
|
|
||||||
return localMessages;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If local cache is empty, we've probably reached the end of cached history.
|
|
||||||
// Fetch from remote. This will also be hit on first load if cache is empty.
|
|
||||||
return await _fetchAndCacheMessages(room.id, offset: offset, take: take);
|
|
||||||
} catch (e) {
|
|
||||||
// Final fallback to cache in case of network errors during fetch.
|
|
||||||
final localMessages = await _getCachedMessages(
|
|
||||||
room.id,
|
|
||||||
offset: offset,
|
|
||||||
take: take,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (localMessages.isNotEmpty) {
|
|
||||||
return localMessages;
|
|
||||||
}
|
|
||||||
rethrow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<List<LocalChatMessage>> _getCachedMessages(
|
|
||||||
String roomId, {
|
|
||||||
int offset = 0,
|
|
||||||
int take = 20,
|
|
||||||
}) async {
|
|
||||||
// Get messages from local database
|
|
||||||
final dbMessages = await _database.getMessagesForRoom(
|
|
||||||
roomId,
|
|
||||||
offset: offset,
|
|
||||||
limit: take,
|
|
||||||
);
|
|
||||||
final dbLocalMessages =
|
|
||||||
dbMessages.map(_database.companionToMessage).toList();
|
|
||||||
|
|
||||||
// Combine with pending messages for the first page
|
|
||||||
if (offset == 0) {
|
|
||||||
final pendingForRoom =
|
|
||||||
pendingMessages.values.where((msg) => msg.roomId == roomId).toList();
|
|
||||||
|
|
||||||
final allMessages = [...pendingForRoom, ...dbLocalMessages];
|
|
||||||
allMessages.sort((a, b) => b.createdAt.compareTo(a.createdAt));
|
|
||||||
|
|
||||||
// Remove duplicates by ID, preserving the order
|
|
||||||
final uniqueMessages = <LocalChatMessage>[];
|
|
||||||
final seenIds = <String>{};
|
|
||||||
for (final message in allMessages) {
|
|
||||||
if (seenIds.add(message.id)) {
|
|
||||||
uniqueMessages.add(message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return uniqueMessages;
|
|
||||||
}
|
|
||||||
|
|
||||||
return dbLocalMessages;
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<List<LocalChatMessage>> _fetchAndCacheMessages(
|
|
||||||
String roomId, {
|
|
||||||
int offset = 0,
|
|
||||||
int take = 20,
|
|
||||||
}) async {
|
|
||||||
// Use cached total count if available, otherwise fetch it
|
|
||||||
if (_totalCount == null) {
|
|
||||||
final response = await _apiClient.get(
|
|
||||||
'/sphere/chat/$roomId/messages',
|
|
||||||
queryParameters: {'offset': 0, 'take': 1},
|
|
||||||
);
|
|
||||||
_totalCount = int.parse(response.headers['x-total']?.firstOrNull ?? '0');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (offset >= _totalCount!) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
final response = await _apiClient.get(
|
|
||||||
'/sphere/chat/$roomId/messages',
|
|
||||||
queryParameters: {'offset': offset, 'take': take},
|
|
||||||
);
|
|
||||||
|
|
||||||
final List<dynamic> data = response.data;
|
|
||||||
// Update total count from response headers
|
|
||||||
_totalCount = int.parse(response.headers['x-total']?.firstOrNull ?? '0');
|
|
||||||
|
|
||||||
final messages =
|
|
||||||
data.map((json) {
|
|
||||||
final remoteMessage = SnChatMessage.fromJson(json);
|
|
||||||
return LocalChatMessage.fromRemoteMessage(
|
|
||||||
remoteMessage,
|
|
||||||
MessageStatus.sent,
|
|
||||||
);
|
|
||||||
}).toList();
|
|
||||||
|
|
||||||
for (final message in messages) {
|
|
||||||
await _database.saveMessage(_database.messageToCompanion(message));
|
|
||||||
if (message.nonce != null) {
|
|
||||||
pendingMessages.removeWhere(
|
|
||||||
(_, pendingMsg) => pendingMsg.nonce == message.nonce,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return messages;
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<LocalChatMessage> sendMessage(
|
|
||||||
String token,
|
|
||||||
String baseUrl,
|
|
||||||
String roomId,
|
|
||||||
String content,
|
|
||||||
String nonce, {
|
|
||||||
required List<UniversalFile> attachments,
|
|
||||||
Map<String, dynamic>? meta,
|
|
||||||
SnChatMessage? replyingTo,
|
|
||||||
SnChatMessage? forwardingTo,
|
|
||||||
SnChatMessage? editingTo,
|
|
||||||
Function(LocalChatMessage)? onPending,
|
|
||||||
Function(String, Map<int, double>)? onProgress,
|
|
||||||
}) async {
|
|
||||||
// Generate a unique nonce for this message
|
|
||||||
final nonce = const Uuid().v4();
|
|
||||||
|
|
||||||
// Create a local message with pending status
|
|
||||||
final mockMessage = SnChatMessage(
|
|
||||||
id: 'pending_$nonce',
|
|
||||||
chatRoomId: roomId,
|
|
||||||
senderId: identity.id,
|
|
||||||
content: content,
|
|
||||||
createdAt: DateTime.now(),
|
|
||||||
updatedAt: DateTime.now(),
|
|
||||||
nonce: nonce,
|
|
||||||
sender: identity,
|
|
||||||
);
|
|
||||||
|
|
||||||
final localMessage = LocalChatMessage.fromRemoteMessage(
|
|
||||||
mockMessage,
|
|
||||||
MessageStatus.pending,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Store in memory and database
|
|
||||||
pendingMessages[localMessage.id] = localMessage;
|
|
||||||
fileUploadProgress[localMessage.id] = {};
|
|
||||||
await _database.saveMessage(_database.messageToCompanion(localMessage));
|
|
||||||
onPending?.call(localMessage);
|
|
||||||
|
|
||||||
try {
|
|
||||||
var cloudAttachments = List.empty(growable: true);
|
|
||||||
// Upload files
|
|
||||||
for (var idx = 0; idx < attachments.length; idx++) {
|
|
||||||
final cloudFile =
|
|
||||||
await putMediaToCloud(
|
|
||||||
fileData: attachments[idx],
|
|
||||||
atk: token,
|
|
||||||
baseUrl: baseUrl,
|
|
||||||
filename: attachments[idx].data.name ?? 'Post media',
|
|
||||||
mimetype:
|
|
||||||
attachments[idx].data.mimeType ??
|
|
||||||
switch (attachments[idx].type) {
|
|
||||||
UniversalFileType.image => 'image/unknown',
|
|
||||||
UniversalFileType.video => 'video/unknown',
|
|
||||||
UniversalFileType.audio => 'audio/unknown',
|
|
||||||
UniversalFileType.file => 'application/octet-stream',
|
|
||||||
},
|
|
||||||
onProgress: (progress, _) {
|
|
||||||
fileUploadProgress[localMessage.id]?[idx] = progress;
|
|
||||||
onProgress?.call(
|
|
||||||
localMessage.id,
|
|
||||||
fileUploadProgress[localMessage.id] ?? {},
|
|
||||||
);
|
|
||||||
},
|
|
||||||
).future;
|
|
||||||
if (cloudFile == null) {
|
|
||||||
throw ArgumentError('Failed to upload the file...');
|
|
||||||
}
|
|
||||||
cloudAttachments.add(cloudFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send to server
|
|
||||||
final response = await _apiClient.request(
|
|
||||||
editingTo == null
|
|
||||||
? '/sphere/chat/$roomId/messages'
|
|
||||||
: '/sphere/chat/$roomId/messages/${editingTo.id}',
|
|
||||||
data: {
|
|
||||||
'content': content,
|
|
||||||
'attachments_id': cloudAttachments.map((e) => e.id).toList(),
|
|
||||||
'replied_message_id': replyingTo?.id,
|
|
||||||
'forwarded_message_id': forwardingTo?.id,
|
|
||||||
'meta': meta,
|
|
||||||
'nonce': nonce,
|
|
||||||
},
|
|
||||||
options: Options(method: editingTo == null ? 'POST' : 'PATCH'),
|
|
||||||
);
|
|
||||||
|
|
||||||
// Update with server response
|
|
||||||
final remoteMessage = SnChatMessage.fromJson(response.data);
|
|
||||||
final updatedMessage = LocalChatMessage.fromRemoteMessage(
|
|
||||||
remoteMessage,
|
|
||||||
MessageStatus.sent,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Remove from pending and update in database
|
|
||||||
pendingMessages.remove(localMessage.id);
|
|
||||||
await _database.deleteMessage(localMessage.id);
|
|
||||||
await _database.saveMessage(_database.messageToCompanion(updatedMessage));
|
|
||||||
|
|
||||||
return updatedMessage;
|
|
||||||
} catch (e) {
|
|
||||||
// Update status to failed
|
|
||||||
localMessage.status = MessageStatus.failed;
|
|
||||||
pendingMessages[localMessage.id] = localMessage;
|
|
||||||
await _database.updateMessageStatus(
|
|
||||||
localMessage.id,
|
|
||||||
MessageStatus.failed,
|
|
||||||
);
|
|
||||||
rethrow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<LocalChatMessage> retryMessage(String pendingMessageId) async {
|
|
||||||
final message = await getMessageById(pendingMessageId);
|
|
||||||
if (message == null) {
|
|
||||||
throw Exception('Message not found');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update status back to pending
|
|
||||||
message.status = MessageStatus.pending;
|
|
||||||
pendingMessages[pendingMessageId] = message;
|
|
||||||
await _database.updateMessageStatus(
|
|
||||||
pendingMessageId,
|
|
||||||
MessageStatus.pending,
|
|
||||||
);
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Send to server
|
|
||||||
var remoteMessage = message.toRemoteMessage();
|
|
||||||
final response = await _apiClient.post(
|
|
||||||
'/sphere/chat/${message.roomId}/messages',
|
|
||||||
data: {
|
|
||||||
'content': remoteMessage.content,
|
|
||||||
'attachments_id': remoteMessage.attachments,
|
|
||||||
'meta': remoteMessage.meta,
|
|
||||||
'nonce': message.nonce,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
// Update with server response
|
|
||||||
remoteMessage = SnChatMessage.fromJson(response.data);
|
|
||||||
final updatedMessage = LocalChatMessage.fromRemoteMessage(
|
|
||||||
remoteMessage,
|
|
||||||
MessageStatus.sent,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Remove from pending and update in database
|
|
||||||
pendingMessages.remove(pendingMessageId);
|
|
||||||
await _database.deleteMessage(pendingMessageId);
|
|
||||||
await _database.saveMessage(_database.messageToCompanion(updatedMessage));
|
|
||||||
|
|
||||||
return updatedMessage;
|
|
||||||
} catch (e) {
|
|
||||||
// Update status to failed
|
|
||||||
message.status = MessageStatus.failed;
|
|
||||||
pendingMessages[pendingMessageId] = message;
|
|
||||||
await _database.updateMessageStatus(
|
|
||||||
pendingMessageId,
|
|
||||||
MessageStatus.failed,
|
|
||||||
);
|
|
||||||
rethrow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<LocalChatMessage> receiveMessage(SnChatMessage remoteMessage) async {
|
|
||||||
final localMessage = LocalChatMessage.fromRemoteMessage(
|
|
||||||
remoteMessage,
|
|
||||||
MessageStatus.sent,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (remoteMessage.nonce != null) {
|
|
||||||
pendingMessages.removeWhere(
|
|
||||||
(_, pendingMsg) => pendingMsg.nonce == remoteMessage.nonce,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
await _database.saveMessage(_database.messageToCompanion(localMessage));
|
|
||||||
return localMessage;
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<LocalChatMessage> receiveMessageUpdate(
|
|
||||||
SnChatMessage remoteMessage,
|
|
||||||
) async {
|
|
||||||
final localMessage = LocalChatMessage.fromRemoteMessage(
|
|
||||||
remoteMessage,
|
|
||||||
MessageStatus.sent,
|
|
||||||
);
|
|
||||||
|
|
||||||
await _database.updateMessage(_database.messageToCompanion(localMessage));
|
|
||||||
return localMessage;
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> receiveMessageDeletion(String messageId) async {
|
|
||||||
// Remove from pending messages if exists
|
|
||||||
pendingMessages.remove(messageId);
|
|
||||||
|
|
||||||
// Delete from local database
|
|
||||||
await _database.deleteMessage(messageId);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<LocalChatMessage> updateMessage(
|
|
||||||
String messageId,
|
|
||||||
String content, {
|
|
||||||
List<SnCloudFile>? attachments,
|
|
||||||
Map<String, dynamic>? meta,
|
|
||||||
}) async {
|
|
||||||
final message = pendingMessages[messageId];
|
|
||||||
if (message != null) {
|
|
||||||
// Update pending message
|
|
||||||
final rmMessage = message.toRemoteMessage();
|
|
||||||
final updatedRemoteMessage = rmMessage.copyWith(
|
|
||||||
content: content,
|
|
||||||
meta: meta ?? rmMessage.meta,
|
|
||||||
);
|
|
||||||
final updatedLocalMessage = LocalChatMessage.fromRemoteMessage(
|
|
||||||
updatedRemoteMessage,
|
|
||||||
MessageStatus.pending,
|
|
||||||
);
|
|
||||||
pendingMessages[messageId] = updatedLocalMessage;
|
|
||||||
await _database.updateMessage(
|
|
||||||
_database.messageToCompanion(updatedLocalMessage),
|
|
||||||
);
|
|
||||||
return message;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Update on server
|
|
||||||
final response = await _apiClient.put(
|
|
||||||
'/sphere/chat/${room.id}/messages/$messageId',
|
|
||||||
data: {'content': content, 'attachments': attachments, 'meta': meta},
|
|
||||||
);
|
|
||||||
|
|
||||||
// Update local copy
|
|
||||||
final remoteMessage = SnChatMessage.fromJson(response.data);
|
|
||||||
final updatedMessage = LocalChatMessage.fromRemoteMessage(
|
|
||||||
remoteMessage,
|
|
||||||
MessageStatus.sent,
|
|
||||||
);
|
|
||||||
await _database.updateMessage(
|
|
||||||
_database.messageToCompanion(updatedMessage),
|
|
||||||
);
|
|
||||||
return updatedMessage;
|
|
||||||
} catch (e) {
|
|
||||||
rethrow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> deleteMessage(String messageId) async {
|
|
||||||
try {
|
|
||||||
await _apiClient.delete('/sphere/chat/${room.id}/messages/$messageId');
|
|
||||||
pendingMessages.remove(messageId);
|
|
||||||
await _database.deleteMessage(messageId);
|
|
||||||
} catch (e) {
|
|
||||||
rethrow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<LocalChatMessage?> getMessageById(String messageId) async {
|
|
||||||
try {
|
|
||||||
// Attempt to get the message from the local database
|
|
||||||
final localMessage =
|
|
||||||
await (_database.select(_database.chatMessages)
|
|
||||||
..where((tbl) => tbl.id.equals(messageId))).getSingleOrNull();
|
|
||||||
if (localMessage != null) {
|
|
||||||
return _database.companionToMessage(localMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If not found locally, fetch from the server
|
|
||||||
final response = await _apiClient.get(
|
|
||||||
'/sphere/chat/${room.id}/messages/$messageId',
|
|
||||||
);
|
|
||||||
final remoteMessage = SnChatMessage.fromJson(response.data);
|
|
||||||
final message = LocalChatMessage.fromRemoteMessage(
|
|
||||||
remoteMessage,
|
|
||||||
MessageStatus.sent,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Save the fetched message to the local database
|
|
||||||
await _database.saveMessage(_database.messageToCompanion(message));
|
|
||||||
return message;
|
|
||||||
} catch (e) {
|
|
||||||
if (e is DioException) return null;
|
|
||||||
// Handle errors
|
|
||||||
rethrow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -208,3 +208,20 @@ sealed class SnAuthDeviceWithChallenge with _$SnAuthDeviceWithChallenge {
|
|||||||
factory SnAuthDeviceWithChallenge.fromJson(Map<String, dynamic> json) =>
|
factory SnAuthDeviceWithChallenge.fromJson(Map<String, dynamic> json) =>
|
||||||
_$SnAuthDeviceWithChallengeFromJson(json);
|
_$SnAuthDeviceWithChallengeFromJson(json);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
sealed class SnExperienceRecord with _$SnExperienceRecord {
|
||||||
|
const factory SnExperienceRecord({
|
||||||
|
required String id,
|
||||||
|
required int delta,
|
||||||
|
required String reasonType,
|
||||||
|
required String reason,
|
||||||
|
@Default(1.0) double? bonusMultiplier,
|
||||||
|
required DateTime createdAt,
|
||||||
|
required DateTime updatedAt,
|
||||||
|
required DateTime? deletedAt,
|
||||||
|
}) = _SnExperienceRecord;
|
||||||
|
|
||||||
|
factory SnExperienceRecord.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$SnExperienceRecordFromJson(json);
|
||||||
|
}
|
||||||
|
@@ -3018,6 +3018,284 @@ as bool,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
mixin _$SnExperienceRecord {
|
||||||
|
|
||||||
|
String get id; int get delta; String get reasonType; String get reason; double? get bonusMultiplier; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt;
|
||||||
|
/// Create a copy of SnExperienceRecord
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$SnExperienceRecordCopyWith<SnExperienceRecord> get copyWith => _$SnExperienceRecordCopyWithImpl<SnExperienceRecord>(this as SnExperienceRecord, _$identity);
|
||||||
|
|
||||||
|
/// Serializes this SnExperienceRecord to a JSON map.
|
||||||
|
Map<String, dynamic> toJson();
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnExperienceRecord&&(identical(other.id, id) || other.id == id)&&(identical(other.delta, delta) || other.delta == delta)&&(identical(other.reasonType, reasonType) || other.reasonType == reasonType)&&(identical(other.reason, reason) || other.reason == reason)&&(identical(other.bonusMultiplier, bonusMultiplier) || other.bonusMultiplier == bonusMultiplier)&&(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,delta,reasonType,reason,bonusMultiplier,createdAt,updatedAt,deletedAt);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'SnExperienceRecord(id: $id, delta: $delta, reasonType: $reasonType, reason: $reason, bonusMultiplier: $bonusMultiplier, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract mixin class $SnExperienceRecordCopyWith<$Res> {
|
||||||
|
factory $SnExperienceRecordCopyWith(SnExperienceRecord value, $Res Function(SnExperienceRecord) _then) = _$SnExperienceRecordCopyWithImpl;
|
||||||
|
@useResult
|
||||||
|
$Res call({
|
||||||
|
String id, int delta, String reasonType, String reason, double? bonusMultiplier, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
/// @nodoc
|
||||||
|
class _$SnExperienceRecordCopyWithImpl<$Res>
|
||||||
|
implements $SnExperienceRecordCopyWith<$Res> {
|
||||||
|
_$SnExperienceRecordCopyWithImpl(this._self, this._then);
|
||||||
|
|
||||||
|
final SnExperienceRecord _self;
|
||||||
|
final $Res Function(SnExperienceRecord) _then;
|
||||||
|
|
||||||
|
/// Create a copy of SnExperienceRecord
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? delta = null,Object? reasonType = null,Object? reason = null,Object? bonusMultiplier = 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,delta: null == delta ? _self.delta : delta // ignore: cast_nullable_to_non_nullable
|
||||||
|
as int,reasonType: null == reasonType ? _self.reasonType : reasonType // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,reason: null == reason ? _self.reason : reason // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,bonusMultiplier: freezed == bonusMultiplier ? _self.bonusMultiplier : bonusMultiplier // ignore: cast_nullable_to_non_nullable
|
||||||
|
as double?,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?,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Adds pattern-matching-related methods to [SnExperienceRecord].
|
||||||
|
extension SnExperienceRecordPatterns on SnExperienceRecord {
|
||||||
|
/// 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( _SnExperienceRecord value)? $default,{required TResult orElse(),}){
|
||||||
|
final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _SnExperienceRecord() 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( _SnExperienceRecord value) $default,){
|
||||||
|
final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _SnExperienceRecord():
|
||||||
|
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( _SnExperienceRecord value)? $default,){
|
||||||
|
final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _SnExperienceRecord() 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, int delta, String reasonType, String reason, double? bonusMultiplier, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,{required TResult orElse(),}) {final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _SnExperienceRecord() when $default != null:
|
||||||
|
return $default(_that.id,_that.delta,_that.reasonType,_that.reason,_that.bonusMultiplier,_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, int delta, String reasonType, String reason, double? bonusMultiplier, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt) $default,) {final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _SnExperienceRecord():
|
||||||
|
return $default(_that.id,_that.delta,_that.reasonType,_that.reason,_that.bonusMultiplier,_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, int delta, String reasonType, String reason, double? bonusMultiplier, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,) {final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _SnExperienceRecord() when $default != null:
|
||||||
|
return $default(_that.id,_that.delta,_that.reasonType,_that.reason,_that.bonusMultiplier,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
@JsonSerializable()
|
||||||
|
|
||||||
|
class _SnExperienceRecord implements SnExperienceRecord {
|
||||||
|
const _SnExperienceRecord({required this.id, required this.delta, required this.reasonType, required this.reason, this.bonusMultiplier = 1.0, required this.createdAt, required this.updatedAt, required this.deletedAt});
|
||||||
|
factory _SnExperienceRecord.fromJson(Map<String, dynamic> json) => _$SnExperienceRecordFromJson(json);
|
||||||
|
|
||||||
|
@override final String id;
|
||||||
|
@override final int delta;
|
||||||
|
@override final String reasonType;
|
||||||
|
@override final String reason;
|
||||||
|
@override@JsonKey() final double? bonusMultiplier;
|
||||||
|
@override final DateTime createdAt;
|
||||||
|
@override final DateTime updatedAt;
|
||||||
|
@override final DateTime? deletedAt;
|
||||||
|
|
||||||
|
/// Create a copy of SnExperienceRecord
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
_$SnExperienceRecordCopyWith<_SnExperienceRecord> get copyWith => __$SnExperienceRecordCopyWithImpl<_SnExperienceRecord>(this, _$identity);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
return _$SnExperienceRecordToJson(this, );
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnExperienceRecord&&(identical(other.id, id) || other.id == id)&&(identical(other.delta, delta) || other.delta == delta)&&(identical(other.reasonType, reasonType) || other.reasonType == reasonType)&&(identical(other.reason, reason) || other.reason == reason)&&(identical(other.bonusMultiplier, bonusMultiplier) || other.bonusMultiplier == bonusMultiplier)&&(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,delta,reasonType,reason,bonusMultiplier,createdAt,updatedAt,deletedAt);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'SnExperienceRecord(id: $id, delta: $delta, reasonType: $reasonType, reason: $reason, bonusMultiplier: $bonusMultiplier, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract mixin class _$SnExperienceRecordCopyWith<$Res> implements $SnExperienceRecordCopyWith<$Res> {
|
||||||
|
factory _$SnExperienceRecordCopyWith(_SnExperienceRecord value, $Res Function(_SnExperienceRecord) _then) = __$SnExperienceRecordCopyWithImpl;
|
||||||
|
@override @useResult
|
||||||
|
$Res call({
|
||||||
|
String id, int delta, String reasonType, String reason, double? bonusMultiplier, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
/// @nodoc
|
||||||
|
class __$SnExperienceRecordCopyWithImpl<$Res>
|
||||||
|
implements _$SnExperienceRecordCopyWith<$Res> {
|
||||||
|
__$SnExperienceRecordCopyWithImpl(this._self, this._then);
|
||||||
|
|
||||||
|
final _SnExperienceRecord _self;
|
||||||
|
final $Res Function(_SnExperienceRecord) _then;
|
||||||
|
|
||||||
|
/// Create a copy of SnExperienceRecord
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? delta = null,Object? reasonType = null,Object? reason = null,Object? bonusMultiplier = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
||||||
|
return _then(_SnExperienceRecord(
|
||||||
|
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,delta: null == delta ? _self.delta : delta // ignore: cast_nullable_to_non_nullable
|
||||||
|
as int,reasonType: null == reasonType ? _self.reasonType : reasonType // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,reason: null == reason ? _self.reason : reason // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,bonusMultiplier: freezed == bonusMultiplier ? _self.bonusMultiplier : bonusMultiplier // ignore: cast_nullable_to_non_nullable
|
||||||
|
as double?,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?,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// dart format on
|
// dart format on
|
||||||
|
@@ -348,3 +348,30 @@ Map<String, dynamic> _$SnAuthDeviceWithChallengeeToJson(
|
|||||||
'challenges': instance.challenges.map((e) => e.toJson()).toList(),
|
'challenges': instance.challenges.map((e) => e.toJson()).toList(),
|
||||||
'is_current': instance.isCurrent,
|
'is_current': instance.isCurrent,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
_SnExperienceRecord _$SnExperienceRecordFromJson(Map<String, dynamic> json) =>
|
||||||
|
_SnExperienceRecord(
|
||||||
|
id: json['id'] as String,
|
||||||
|
delta: (json['delta'] as num).toInt(),
|
||||||
|
reasonType: json['reason_type'] as String,
|
||||||
|
reason: json['reason'] as String,
|
||||||
|
bonusMultiplier: (json['bonus_multiplier'] as num?)?.toDouble() ?? 1.0,
|
||||||
|
createdAt: DateTime.parse(json['created_at'] as String),
|
||||||
|
updatedAt: DateTime.parse(json['updated_at'] as String),
|
||||||
|
deletedAt:
|
||||||
|
json['deleted_at'] == null
|
||||||
|
? null
|
||||||
|
: DateTime.parse(json['deleted_at'] as String),
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$SnExperienceRecordToJson(_SnExperienceRecord instance) =>
|
||||||
|
<String, dynamic>{
|
||||||
|
'id': instance.id,
|
||||||
|
'delta': instance.delta,
|
||||||
|
'reason_type': instance.reasonType,
|
||||||
|
'reason': instance.reason,
|
||||||
|
'bonus_multiplier': instance.bonusMultiplier,
|
||||||
|
'created_at': instance.createdAt.toIso8601String(),
|
||||||
|
'updated_at': instance.updatedAt.toIso8601String(),
|
||||||
|
'deleted_at': instance.deletedAt?.toIso8601String(),
|
||||||
|
};
|
||||||
|
@@ -91,6 +91,7 @@ sealed class SnChatMember with _$SnChatMember {
|
|||||||
required DateTime? breakUntil,
|
required DateTime? breakUntil,
|
||||||
required DateTime? timeoutUntil,
|
required DateTime? timeoutUntil,
|
||||||
required bool isBot,
|
required bool isBot,
|
||||||
|
required SnAccountStatus? status,
|
||||||
// Frontend data
|
// Frontend data
|
||||||
DateTime? lastTyped,
|
DateTime? lastTyped,
|
||||||
}) = _SnChatMember;
|
}) = _SnChatMember;
|
||||||
|
@@ -1037,7 +1037,7 @@ $SnChatMemberCopyWith<$Res> get sender {
|
|||||||
/// @nodoc
|
/// @nodoc
|
||||||
mixin _$SnChatMember {
|
mixin _$SnChatMember {
|
||||||
|
|
||||||
DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt; String get id; String get chatRoomId; SnChatRoom? get chatRoom; String get accountId; SnAccount get account; String? get nick; int get role; int get notify; DateTime? get joinedAt; DateTime? get breakUntil; DateTime? get timeoutUntil; bool get isBot;// Frontend data
|
DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt; String get id; String get chatRoomId; SnChatRoom? get chatRoom; String get accountId; SnAccount get account; String? get nick; int get role; int get notify; DateTime? get joinedAt; DateTime? get breakUntil; DateTime? get timeoutUntil; bool get isBot; SnAccountStatus? get status;// Frontend data
|
||||||
DateTime? get lastTyped;
|
DateTime? get lastTyped;
|
||||||
/// Create a copy of SnChatMember
|
/// Create a copy of SnChatMember
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@@ -1051,16 +1051,16 @@ $SnChatMemberCopyWith<SnChatMember> get copyWith => _$SnChatMemberCopyWithImpl<S
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnChatMember&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)&&(identical(other.id, id) || other.id == id)&&(identical(other.chatRoomId, chatRoomId) || other.chatRoomId == chatRoomId)&&(identical(other.chatRoom, chatRoom) || other.chatRoom == chatRoom)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.account, account) || other.account == account)&&(identical(other.nick, nick) || other.nick == nick)&&(identical(other.role, role) || other.role == role)&&(identical(other.notify, notify) || other.notify == notify)&&(identical(other.joinedAt, joinedAt) || other.joinedAt == joinedAt)&&(identical(other.breakUntil, breakUntil) || other.breakUntil == breakUntil)&&(identical(other.timeoutUntil, timeoutUntil) || other.timeoutUntil == timeoutUntil)&&(identical(other.isBot, isBot) || other.isBot == isBot)&&(identical(other.lastTyped, lastTyped) || other.lastTyped == lastTyped));
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnChatMember&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)&&(identical(other.id, id) || other.id == id)&&(identical(other.chatRoomId, chatRoomId) || other.chatRoomId == chatRoomId)&&(identical(other.chatRoom, chatRoom) || other.chatRoom == chatRoom)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.account, account) || other.account == account)&&(identical(other.nick, nick) || other.nick == nick)&&(identical(other.role, role) || other.role == role)&&(identical(other.notify, notify) || other.notify == notify)&&(identical(other.joinedAt, joinedAt) || other.joinedAt == joinedAt)&&(identical(other.breakUntil, breakUntil) || other.breakUntil == breakUntil)&&(identical(other.timeoutUntil, timeoutUntil) || other.timeoutUntil == timeoutUntil)&&(identical(other.isBot, isBot) || other.isBot == isBot)&&(identical(other.status, status) || other.status == status)&&(identical(other.lastTyped, lastTyped) || other.lastTyped == lastTyped));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType,createdAt,updatedAt,deletedAt,id,chatRoomId,chatRoom,accountId,account,nick,role,notify,joinedAt,breakUntil,timeoutUntil,isBot,lastTyped);
|
int get hashCode => Object.hash(runtimeType,createdAt,updatedAt,deletedAt,id,chatRoomId,chatRoom,accountId,account,nick,role,notify,joinedAt,breakUntil,timeoutUntil,isBot,status,lastTyped);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'SnChatMember(createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, id: $id, chatRoomId: $chatRoomId, chatRoom: $chatRoom, accountId: $accountId, account: $account, nick: $nick, role: $role, notify: $notify, joinedAt: $joinedAt, breakUntil: $breakUntil, timeoutUntil: $timeoutUntil, isBot: $isBot, lastTyped: $lastTyped)';
|
return 'SnChatMember(createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, id: $id, chatRoomId: $chatRoomId, chatRoom: $chatRoom, accountId: $accountId, account: $account, nick: $nick, role: $role, notify: $notify, joinedAt: $joinedAt, breakUntil: $breakUntil, timeoutUntil: $timeoutUntil, isBot: $isBot, status: $status, lastTyped: $lastTyped)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1071,11 +1071,11 @@ abstract mixin class $SnChatMemberCopyWith<$Res> {
|
|||||||
factory $SnChatMemberCopyWith(SnChatMember value, $Res Function(SnChatMember) _then) = _$SnChatMemberCopyWithImpl;
|
factory $SnChatMemberCopyWith(SnChatMember value, $Res Function(SnChatMember) _then) = _$SnChatMemberCopyWithImpl;
|
||||||
@useResult
|
@useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, String id, String chatRoomId, SnChatRoom? chatRoom, String accountId, SnAccount account, String? nick, int role, int notify, DateTime? joinedAt, DateTime? breakUntil, DateTime? timeoutUntil, bool isBot, DateTime? lastTyped
|
DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, String id, String chatRoomId, SnChatRoom? chatRoom, String accountId, SnAccount account, String? nick, int role, int notify, DateTime? joinedAt, DateTime? breakUntil, DateTime? timeoutUntil, bool isBot, SnAccountStatus? status, DateTime? lastTyped
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
$SnChatRoomCopyWith<$Res>? get chatRoom;$SnAccountCopyWith<$Res> get account;
|
$SnChatRoomCopyWith<$Res>? get chatRoom;$SnAccountCopyWith<$Res> get account;$SnAccountStatusCopyWith<$Res>? get status;
|
||||||
|
|
||||||
}
|
}
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
@@ -1088,7 +1088,7 @@ class _$SnChatMemberCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of SnChatMember
|
/// Create a copy of SnChatMember
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@pragma('vm:prefer-inline') @override $Res call({Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,Object? id = null,Object? chatRoomId = null,Object? chatRoom = freezed,Object? accountId = null,Object? account = null,Object? nick = freezed,Object? role = null,Object? notify = null,Object? joinedAt = freezed,Object? breakUntil = freezed,Object? timeoutUntil = freezed,Object? isBot = null,Object? lastTyped = freezed,}) {
|
@pragma('vm:prefer-inline') @override $Res call({Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,Object? id = null,Object? chatRoomId = null,Object? chatRoom = freezed,Object? accountId = null,Object? account = null,Object? nick = freezed,Object? role = null,Object? notify = null,Object? joinedAt = freezed,Object? breakUntil = freezed,Object? timeoutUntil = freezed,Object? isBot = null,Object? status = freezed,Object? lastTyped = freezed,}) {
|
||||||
return _then(_self.copyWith(
|
return _then(_self.copyWith(
|
||||||
createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
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,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
|
||||||
@@ -1105,7 +1105,8 @@ as int,joinedAt: freezed == joinedAt ? _self.joinedAt : joinedAt // ignore: cast
|
|||||||
as DateTime?,breakUntil: freezed == breakUntil ? _self.breakUntil : breakUntil // ignore: cast_nullable_to_non_nullable
|
as DateTime?,breakUntil: freezed == breakUntil ? _self.breakUntil : breakUntil // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime?,timeoutUntil: freezed == timeoutUntil ? _self.timeoutUntil : timeoutUntil // ignore: cast_nullable_to_non_nullable
|
as DateTime?,timeoutUntil: freezed == timeoutUntil ? _self.timeoutUntil : timeoutUntil // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime?,isBot: null == isBot ? _self.isBot : isBot // ignore: cast_nullable_to_non_nullable
|
as DateTime?,isBot: null == isBot ? _self.isBot : isBot // ignore: cast_nullable_to_non_nullable
|
||||||
as bool,lastTyped: freezed == lastTyped ? _self.lastTyped : lastTyped // ignore: cast_nullable_to_non_nullable
|
as bool,status: freezed == status ? _self.status : status // ignore: cast_nullable_to_non_nullable
|
||||||
|
as SnAccountStatus?,lastTyped: freezed == lastTyped ? _self.lastTyped : lastTyped // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime?,
|
as DateTime?,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@@ -1130,6 +1131,18 @@ $SnAccountCopyWith<$Res> get account {
|
|||||||
return $SnAccountCopyWith<$Res>(_self.account, (value) {
|
return $SnAccountCopyWith<$Res>(_self.account, (value) {
|
||||||
return _then(_self.copyWith(account: value));
|
return _then(_self.copyWith(account: value));
|
||||||
});
|
});
|
||||||
|
}/// Create a copy of SnChatMember
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$SnAccountStatusCopyWith<$Res>? get status {
|
||||||
|
if (_self.status == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $SnAccountStatusCopyWith<$Res>(_self.status!, (value) {
|
||||||
|
return _then(_self.copyWith(status: value));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1209,10 +1222,10 @@ return $default(_that);case _:
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, String id, String chatRoomId, SnChatRoom? chatRoom, String accountId, SnAccount account, String? nick, int role, int notify, DateTime? joinedAt, DateTime? breakUntil, DateTime? timeoutUntil, bool isBot, DateTime? lastTyped)? $default,{required TResult orElse(),}) {final _that = this;
|
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, String id, String chatRoomId, SnChatRoom? chatRoom, String accountId, SnAccount account, String? nick, int role, int notify, DateTime? joinedAt, DateTime? breakUntil, DateTime? timeoutUntil, bool isBot, SnAccountStatus? status, DateTime? lastTyped)? $default,{required TResult orElse(),}) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _SnChatMember() when $default != null:
|
case _SnChatMember() when $default != null:
|
||||||
return $default(_that.createdAt,_that.updatedAt,_that.deletedAt,_that.id,_that.chatRoomId,_that.chatRoom,_that.accountId,_that.account,_that.nick,_that.role,_that.notify,_that.joinedAt,_that.breakUntil,_that.timeoutUntil,_that.isBot,_that.lastTyped);case _:
|
return $default(_that.createdAt,_that.updatedAt,_that.deletedAt,_that.id,_that.chatRoomId,_that.chatRoom,_that.accountId,_that.account,_that.nick,_that.role,_that.notify,_that.joinedAt,_that.breakUntil,_that.timeoutUntil,_that.isBot,_that.status,_that.lastTyped);case _:
|
||||||
return orElse();
|
return orElse();
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1230,10 +1243,10 @@ return $default(_that.createdAt,_that.updatedAt,_that.deletedAt,_that.id,_that.c
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, String id, String chatRoomId, SnChatRoom? chatRoom, String accountId, SnAccount account, String? nick, int role, int notify, DateTime? joinedAt, DateTime? breakUntil, DateTime? timeoutUntil, bool isBot, DateTime? lastTyped) $default,) {final _that = this;
|
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, String id, String chatRoomId, SnChatRoom? chatRoom, String accountId, SnAccount account, String? nick, int role, int notify, DateTime? joinedAt, DateTime? breakUntil, DateTime? timeoutUntil, bool isBot, SnAccountStatus? status, DateTime? lastTyped) $default,) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _SnChatMember():
|
case _SnChatMember():
|
||||||
return $default(_that.createdAt,_that.updatedAt,_that.deletedAt,_that.id,_that.chatRoomId,_that.chatRoom,_that.accountId,_that.account,_that.nick,_that.role,_that.notify,_that.joinedAt,_that.breakUntil,_that.timeoutUntil,_that.isBot,_that.lastTyped);}
|
return $default(_that.createdAt,_that.updatedAt,_that.deletedAt,_that.id,_that.chatRoomId,_that.chatRoom,_that.accountId,_that.account,_that.nick,_that.role,_that.notify,_that.joinedAt,_that.breakUntil,_that.timeoutUntil,_that.isBot,_that.status,_that.lastTyped);}
|
||||||
}
|
}
|
||||||
/// A variant of `when` that fallback to returning `null`
|
/// A variant of `when` that fallback to returning `null`
|
||||||
///
|
///
|
||||||
@@ -1247,10 +1260,10 @@ return $default(_that.createdAt,_that.updatedAt,_that.deletedAt,_that.id,_that.c
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, String id, String chatRoomId, SnChatRoom? chatRoom, String accountId, SnAccount account, String? nick, int role, int notify, DateTime? joinedAt, DateTime? breakUntil, DateTime? timeoutUntil, bool isBot, DateTime? lastTyped)? $default,) {final _that = this;
|
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, String id, String chatRoomId, SnChatRoom? chatRoom, String accountId, SnAccount account, String? nick, int role, int notify, DateTime? joinedAt, DateTime? breakUntil, DateTime? timeoutUntil, bool isBot, SnAccountStatus? status, DateTime? lastTyped)? $default,) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _SnChatMember() when $default != null:
|
case _SnChatMember() when $default != null:
|
||||||
return $default(_that.createdAt,_that.updatedAt,_that.deletedAt,_that.id,_that.chatRoomId,_that.chatRoom,_that.accountId,_that.account,_that.nick,_that.role,_that.notify,_that.joinedAt,_that.breakUntil,_that.timeoutUntil,_that.isBot,_that.lastTyped);case _:
|
return $default(_that.createdAt,_that.updatedAt,_that.deletedAt,_that.id,_that.chatRoomId,_that.chatRoom,_that.accountId,_that.account,_that.nick,_that.role,_that.notify,_that.joinedAt,_that.breakUntil,_that.timeoutUntil,_that.isBot,_that.status,_that.lastTyped);case _:
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1262,7 +1275,7 @@ return $default(_that.createdAt,_that.updatedAt,_that.deletedAt,_that.id,_that.c
|
|||||||
@JsonSerializable()
|
@JsonSerializable()
|
||||||
|
|
||||||
class _SnChatMember implements SnChatMember {
|
class _SnChatMember implements SnChatMember {
|
||||||
const _SnChatMember({required this.createdAt, required this.updatedAt, required this.deletedAt, required this.id, required this.chatRoomId, required this.chatRoom, required this.accountId, required this.account, required this.nick, required this.role, required this.notify, required this.joinedAt, required this.breakUntil, required this.timeoutUntil, required this.isBot, this.lastTyped});
|
const _SnChatMember({required this.createdAt, required this.updatedAt, required this.deletedAt, required this.id, required this.chatRoomId, required this.chatRoom, required this.accountId, required this.account, required this.nick, required this.role, required this.notify, required this.joinedAt, required this.breakUntil, required this.timeoutUntil, required this.isBot, required this.status, this.lastTyped});
|
||||||
factory _SnChatMember.fromJson(Map<String, dynamic> json) => _$SnChatMemberFromJson(json);
|
factory _SnChatMember.fromJson(Map<String, dynamic> json) => _$SnChatMemberFromJson(json);
|
||||||
|
|
||||||
@override final DateTime createdAt;
|
@override final DateTime createdAt;
|
||||||
@@ -1280,6 +1293,7 @@ class _SnChatMember implements SnChatMember {
|
|||||||
@override final DateTime? breakUntil;
|
@override final DateTime? breakUntil;
|
||||||
@override final DateTime? timeoutUntil;
|
@override final DateTime? timeoutUntil;
|
||||||
@override final bool isBot;
|
@override final bool isBot;
|
||||||
|
@override final SnAccountStatus? status;
|
||||||
// Frontend data
|
// Frontend data
|
||||||
@override final DateTime? lastTyped;
|
@override final DateTime? lastTyped;
|
||||||
|
|
||||||
@@ -1296,16 +1310,16 @@ Map<String, dynamic> toJson() {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnChatMember&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)&&(identical(other.id, id) || other.id == id)&&(identical(other.chatRoomId, chatRoomId) || other.chatRoomId == chatRoomId)&&(identical(other.chatRoom, chatRoom) || other.chatRoom == chatRoom)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.account, account) || other.account == account)&&(identical(other.nick, nick) || other.nick == nick)&&(identical(other.role, role) || other.role == role)&&(identical(other.notify, notify) || other.notify == notify)&&(identical(other.joinedAt, joinedAt) || other.joinedAt == joinedAt)&&(identical(other.breakUntil, breakUntil) || other.breakUntil == breakUntil)&&(identical(other.timeoutUntil, timeoutUntil) || other.timeoutUntil == timeoutUntil)&&(identical(other.isBot, isBot) || other.isBot == isBot)&&(identical(other.lastTyped, lastTyped) || other.lastTyped == lastTyped));
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnChatMember&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)&&(identical(other.id, id) || other.id == id)&&(identical(other.chatRoomId, chatRoomId) || other.chatRoomId == chatRoomId)&&(identical(other.chatRoom, chatRoom) || other.chatRoom == chatRoom)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.account, account) || other.account == account)&&(identical(other.nick, nick) || other.nick == nick)&&(identical(other.role, role) || other.role == role)&&(identical(other.notify, notify) || other.notify == notify)&&(identical(other.joinedAt, joinedAt) || other.joinedAt == joinedAt)&&(identical(other.breakUntil, breakUntil) || other.breakUntil == breakUntil)&&(identical(other.timeoutUntil, timeoutUntil) || other.timeoutUntil == timeoutUntil)&&(identical(other.isBot, isBot) || other.isBot == isBot)&&(identical(other.status, status) || other.status == status)&&(identical(other.lastTyped, lastTyped) || other.lastTyped == lastTyped));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType,createdAt,updatedAt,deletedAt,id,chatRoomId,chatRoom,accountId,account,nick,role,notify,joinedAt,breakUntil,timeoutUntil,isBot,lastTyped);
|
int get hashCode => Object.hash(runtimeType,createdAt,updatedAt,deletedAt,id,chatRoomId,chatRoom,accountId,account,nick,role,notify,joinedAt,breakUntil,timeoutUntil,isBot,status,lastTyped);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'SnChatMember(createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, id: $id, chatRoomId: $chatRoomId, chatRoom: $chatRoom, accountId: $accountId, account: $account, nick: $nick, role: $role, notify: $notify, joinedAt: $joinedAt, breakUntil: $breakUntil, timeoutUntil: $timeoutUntil, isBot: $isBot, lastTyped: $lastTyped)';
|
return 'SnChatMember(createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, id: $id, chatRoomId: $chatRoomId, chatRoom: $chatRoom, accountId: $accountId, account: $account, nick: $nick, role: $role, notify: $notify, joinedAt: $joinedAt, breakUntil: $breakUntil, timeoutUntil: $timeoutUntil, isBot: $isBot, status: $status, lastTyped: $lastTyped)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1316,11 +1330,11 @@ abstract mixin class _$SnChatMemberCopyWith<$Res> implements $SnChatMemberCopyWi
|
|||||||
factory _$SnChatMemberCopyWith(_SnChatMember value, $Res Function(_SnChatMember) _then) = __$SnChatMemberCopyWithImpl;
|
factory _$SnChatMemberCopyWith(_SnChatMember value, $Res Function(_SnChatMember) _then) = __$SnChatMemberCopyWithImpl;
|
||||||
@override @useResult
|
@override @useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, String id, String chatRoomId, SnChatRoom? chatRoom, String accountId, SnAccount account, String? nick, int role, int notify, DateTime? joinedAt, DateTime? breakUntil, DateTime? timeoutUntil, bool isBot, DateTime? lastTyped
|
DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, String id, String chatRoomId, SnChatRoom? chatRoom, String accountId, SnAccount account, String? nick, int role, int notify, DateTime? joinedAt, DateTime? breakUntil, DateTime? timeoutUntil, bool isBot, SnAccountStatus? status, DateTime? lastTyped
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@override $SnChatRoomCopyWith<$Res>? get chatRoom;@override $SnAccountCopyWith<$Res> get account;
|
@override $SnChatRoomCopyWith<$Res>? get chatRoom;@override $SnAccountCopyWith<$Res> get account;@override $SnAccountStatusCopyWith<$Res>? get status;
|
||||||
|
|
||||||
}
|
}
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
@@ -1333,7 +1347,7 @@ class __$SnChatMemberCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of SnChatMember
|
/// Create a copy of SnChatMember
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@override @pragma('vm:prefer-inline') $Res call({Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,Object? id = null,Object? chatRoomId = null,Object? chatRoom = freezed,Object? accountId = null,Object? account = null,Object? nick = freezed,Object? role = null,Object? notify = null,Object? joinedAt = freezed,Object? breakUntil = freezed,Object? timeoutUntil = freezed,Object? isBot = null,Object? lastTyped = freezed,}) {
|
@override @pragma('vm:prefer-inline') $Res call({Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,Object? id = null,Object? chatRoomId = null,Object? chatRoom = freezed,Object? accountId = null,Object? account = null,Object? nick = freezed,Object? role = null,Object? notify = null,Object? joinedAt = freezed,Object? breakUntil = freezed,Object? timeoutUntil = freezed,Object? isBot = null,Object? status = freezed,Object? lastTyped = freezed,}) {
|
||||||
return _then(_SnChatMember(
|
return _then(_SnChatMember(
|
||||||
createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
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,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
|
||||||
@@ -1350,7 +1364,8 @@ as int,joinedAt: freezed == joinedAt ? _self.joinedAt : joinedAt // ignore: cast
|
|||||||
as DateTime?,breakUntil: freezed == breakUntil ? _self.breakUntil : breakUntil // ignore: cast_nullable_to_non_nullable
|
as DateTime?,breakUntil: freezed == breakUntil ? _self.breakUntil : breakUntil // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime?,timeoutUntil: freezed == timeoutUntil ? _self.timeoutUntil : timeoutUntil // ignore: cast_nullable_to_non_nullable
|
as DateTime?,timeoutUntil: freezed == timeoutUntil ? _self.timeoutUntil : timeoutUntil // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime?,isBot: null == isBot ? _self.isBot : isBot // ignore: cast_nullable_to_non_nullable
|
as DateTime?,isBot: null == isBot ? _self.isBot : isBot // ignore: cast_nullable_to_non_nullable
|
||||||
as bool,lastTyped: freezed == lastTyped ? _self.lastTyped : lastTyped // ignore: cast_nullable_to_non_nullable
|
as bool,status: freezed == status ? _self.status : status // ignore: cast_nullable_to_non_nullable
|
||||||
|
as SnAccountStatus?,lastTyped: freezed == lastTyped ? _self.lastTyped : lastTyped // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime?,
|
as DateTime?,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@@ -1376,6 +1391,18 @@ $SnAccountCopyWith<$Res> get account {
|
|||||||
return $SnAccountCopyWith<$Res>(_self.account, (value) {
|
return $SnAccountCopyWith<$Res>(_self.account, (value) {
|
||||||
return _then(_self.copyWith(account: value));
|
return _then(_self.copyWith(account: value));
|
||||||
});
|
});
|
||||||
|
}/// Create a copy of SnChatMember
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$SnAccountStatusCopyWith<$Res>? get status {
|
||||||
|
if (_self.status == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $SnAccountStatusCopyWith<$Res>(_self.status!, (value) {
|
||||||
|
return _then(_self.copyWith(status: value));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -177,6 +177,12 @@ _SnChatMember _$SnChatMemberFromJson(Map<String, dynamic> json) =>
|
|||||||
? null
|
? null
|
||||||
: DateTime.parse(json['timeout_until'] as String),
|
: DateTime.parse(json['timeout_until'] as String),
|
||||||
isBot: json['is_bot'] as bool,
|
isBot: json['is_bot'] as bool,
|
||||||
|
status:
|
||||||
|
json['status'] == null
|
||||||
|
? null
|
||||||
|
: SnAccountStatus.fromJson(
|
||||||
|
json['status'] as Map<String, dynamic>,
|
||||||
|
),
|
||||||
lastTyped:
|
lastTyped:
|
||||||
json['last_typed'] == null
|
json['last_typed'] == null
|
||||||
? null
|
? null
|
||||||
@@ -200,6 +206,7 @@ Map<String, dynamic> _$SnChatMemberToJson(_SnChatMember instance) =>
|
|||||||
'break_until': instance.breakUntil?.toIso8601String(),
|
'break_until': instance.breakUntil?.toIso8601String(),
|
||||||
'timeout_until': instance.timeoutUntil?.toIso8601String(),
|
'timeout_until': instance.timeoutUntil?.toIso8601String(),
|
||||||
'is_bot': instance.isBot,
|
'is_bot': instance.isBot,
|
||||||
|
'status': instance.status?.toJson(),
|
||||||
'last_typed': instance.lastTyped?.toIso8601String(),
|
'last_typed': instance.lastTyped?.toIso8601String(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -11,8 +11,8 @@ sealed class SnScrappedLink with _$SnScrappedLink {
|
|||||||
required String title,
|
required String title,
|
||||||
required String? description,
|
required String? description,
|
||||||
required String? imageUrl,
|
required String? imageUrl,
|
||||||
required String faviconUrl,
|
required String? faviconUrl,
|
||||||
required String siteName,
|
required String? siteName,
|
||||||
required String? contentType,
|
required String? contentType,
|
||||||
required String? author,
|
required String? author,
|
||||||
required DateTime? publishedDate,
|
required DateTime? publishedDate,
|
||||||
|
@@ -15,7 +15,7 @@ T _$identity<T>(T value) => value;
|
|||||||
/// @nodoc
|
/// @nodoc
|
||||||
mixin _$SnScrappedLink {
|
mixin _$SnScrappedLink {
|
||||||
|
|
||||||
String get type; String get url; String get title; String? get description; String? get imageUrl; String get faviconUrl; String get siteName; String? get contentType; String? get author; DateTime? get publishedDate;
|
String get type; String get url; String get title; String? get description; String? get imageUrl; String? get faviconUrl; String? get siteName; String? get contentType; String? get author; DateTime? get publishedDate;
|
||||||
/// Create a copy of SnScrappedLink
|
/// Create a copy of SnScrappedLink
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@@ -48,7 +48,7 @@ abstract mixin class $SnScrappedLinkCopyWith<$Res> {
|
|||||||
factory $SnScrappedLinkCopyWith(SnScrappedLink value, $Res Function(SnScrappedLink) _then) = _$SnScrappedLinkCopyWithImpl;
|
factory $SnScrappedLinkCopyWith(SnScrappedLink value, $Res Function(SnScrappedLink) _then) = _$SnScrappedLinkCopyWithImpl;
|
||||||
@useResult
|
@useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
String type, String url, String title, String? description, String? imageUrl, String faviconUrl, String siteName, String? contentType, String? author, DateTime? publishedDate
|
String type, String url, String title, String? description, String? imageUrl, String? faviconUrl, String? siteName, String? contentType, String? author, DateTime? publishedDate
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -65,16 +65,16 @@ class _$SnScrappedLinkCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of SnScrappedLink
|
/// Create a copy of SnScrappedLink
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@pragma('vm:prefer-inline') @override $Res call({Object? type = null,Object? url = null,Object? title = null,Object? description = freezed,Object? imageUrl = freezed,Object? faviconUrl = null,Object? siteName = null,Object? contentType = freezed,Object? author = freezed,Object? publishedDate = freezed,}) {
|
@pragma('vm:prefer-inline') @override $Res call({Object? type = null,Object? url = null,Object? title = null,Object? description = freezed,Object? imageUrl = freezed,Object? faviconUrl = freezed,Object? siteName = freezed,Object? contentType = freezed,Object? author = freezed,Object? publishedDate = freezed,}) {
|
||||||
return _then(_self.copyWith(
|
return _then(_self.copyWith(
|
||||||
type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable
|
type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable
|
||||||
as String,url: null == url ? _self.url : url // ignore: cast_nullable_to_non_nullable
|
as String,url: null == url ? _self.url : url // ignore: cast_nullable_to_non_nullable
|
||||||
as String,title: null == title ? _self.title : title // ignore: cast_nullable_to_non_nullable
|
as String,title: null == title ? _self.title : title // ignore: cast_nullable_to_non_nullable
|
||||||
as String,description: freezed == description ? _self.description : description // ignore: cast_nullable_to_non_nullable
|
as String,description: freezed == description ? _self.description : description // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,imageUrl: freezed == imageUrl ? _self.imageUrl : imageUrl // ignore: cast_nullable_to_non_nullable
|
as String?,imageUrl: freezed == imageUrl ? _self.imageUrl : imageUrl // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,faviconUrl: null == faviconUrl ? _self.faviconUrl : faviconUrl // ignore: cast_nullable_to_non_nullable
|
as String?,faviconUrl: freezed == faviconUrl ? _self.faviconUrl : faviconUrl // ignore: cast_nullable_to_non_nullable
|
||||||
as String,siteName: null == siteName ? _self.siteName : siteName // ignore: cast_nullable_to_non_nullable
|
as String?,siteName: freezed == siteName ? _self.siteName : siteName // ignore: cast_nullable_to_non_nullable
|
||||||
as String,contentType: freezed == contentType ? _self.contentType : contentType // ignore: cast_nullable_to_non_nullable
|
as String?,contentType: freezed == contentType ? _self.contentType : contentType // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,author: freezed == author ? _self.author : author // ignore: cast_nullable_to_non_nullable
|
as String?,author: freezed == author ? _self.author : author // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,publishedDate: freezed == publishedDate ? _self.publishedDate : publishedDate // ignore: cast_nullable_to_non_nullable
|
as String?,publishedDate: freezed == publishedDate ? _self.publishedDate : publishedDate // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime?,
|
as DateTime?,
|
||||||
@@ -159,7 +159,7 @@ return $default(_that);case _:
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String type, String url, String title, String? description, String? imageUrl, String faviconUrl, String siteName, String? contentType, String? author, DateTime? publishedDate)? $default,{required TResult orElse(),}) {final _that = this;
|
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String type, String url, String title, String? description, String? imageUrl, String? faviconUrl, String? siteName, String? contentType, String? author, DateTime? publishedDate)? $default,{required TResult orElse(),}) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _SnScrappedLink() when $default != null:
|
case _SnScrappedLink() when $default != null:
|
||||||
return $default(_that.type,_that.url,_that.title,_that.description,_that.imageUrl,_that.faviconUrl,_that.siteName,_that.contentType,_that.author,_that.publishedDate);case _:
|
return $default(_that.type,_that.url,_that.title,_that.description,_that.imageUrl,_that.faviconUrl,_that.siteName,_that.contentType,_that.author,_that.publishedDate);case _:
|
||||||
@@ -180,7 +180,7 @@ return $default(_that.type,_that.url,_that.title,_that.description,_that.imageUr
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String type, String url, String title, String? description, String? imageUrl, String faviconUrl, String siteName, String? contentType, String? author, DateTime? publishedDate) $default,) {final _that = this;
|
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String type, String url, String title, String? description, String? imageUrl, String? faviconUrl, String? siteName, String? contentType, String? author, DateTime? publishedDate) $default,) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _SnScrappedLink():
|
case _SnScrappedLink():
|
||||||
return $default(_that.type,_that.url,_that.title,_that.description,_that.imageUrl,_that.faviconUrl,_that.siteName,_that.contentType,_that.author,_that.publishedDate);}
|
return $default(_that.type,_that.url,_that.title,_that.description,_that.imageUrl,_that.faviconUrl,_that.siteName,_that.contentType,_that.author,_that.publishedDate);}
|
||||||
@@ -197,7 +197,7 @@ return $default(_that.type,_that.url,_that.title,_that.description,_that.imageUr
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String type, String url, String title, String? description, String? imageUrl, String faviconUrl, String siteName, String? contentType, String? author, DateTime? publishedDate)? $default,) {final _that = this;
|
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String type, String url, String title, String? description, String? imageUrl, String? faviconUrl, String? siteName, String? contentType, String? author, DateTime? publishedDate)? $default,) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _SnScrappedLink() when $default != null:
|
case _SnScrappedLink() when $default != null:
|
||||||
return $default(_that.type,_that.url,_that.title,_that.description,_that.imageUrl,_that.faviconUrl,_that.siteName,_that.contentType,_that.author,_that.publishedDate);case _:
|
return $default(_that.type,_that.url,_that.title,_that.description,_that.imageUrl,_that.faviconUrl,_that.siteName,_that.contentType,_that.author,_that.publishedDate);case _:
|
||||||
@@ -220,8 +220,8 @@ class _SnScrappedLink implements SnScrappedLink {
|
|||||||
@override final String title;
|
@override final String title;
|
||||||
@override final String? description;
|
@override final String? description;
|
||||||
@override final String? imageUrl;
|
@override final String? imageUrl;
|
||||||
@override final String faviconUrl;
|
@override final String? faviconUrl;
|
||||||
@override final String siteName;
|
@override final String? siteName;
|
||||||
@override final String? contentType;
|
@override final String? contentType;
|
||||||
@override final String? author;
|
@override final String? author;
|
||||||
@override final DateTime? publishedDate;
|
@override final DateTime? publishedDate;
|
||||||
@@ -259,7 +259,7 @@ abstract mixin class _$SnScrappedLinkCopyWith<$Res> implements $SnScrappedLinkCo
|
|||||||
factory _$SnScrappedLinkCopyWith(_SnScrappedLink value, $Res Function(_SnScrappedLink) _then) = __$SnScrappedLinkCopyWithImpl;
|
factory _$SnScrappedLinkCopyWith(_SnScrappedLink value, $Res Function(_SnScrappedLink) _then) = __$SnScrappedLinkCopyWithImpl;
|
||||||
@override @useResult
|
@override @useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
String type, String url, String title, String? description, String? imageUrl, String faviconUrl, String siteName, String? contentType, String? author, DateTime? publishedDate
|
String type, String url, String title, String? description, String? imageUrl, String? faviconUrl, String? siteName, String? contentType, String? author, DateTime? publishedDate
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -276,16 +276,16 @@ class __$SnScrappedLinkCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of SnScrappedLink
|
/// Create a copy of SnScrappedLink
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@override @pragma('vm:prefer-inline') $Res call({Object? type = null,Object? url = null,Object? title = null,Object? description = freezed,Object? imageUrl = freezed,Object? faviconUrl = null,Object? siteName = null,Object? contentType = freezed,Object? author = freezed,Object? publishedDate = freezed,}) {
|
@override @pragma('vm:prefer-inline') $Res call({Object? type = null,Object? url = null,Object? title = null,Object? description = freezed,Object? imageUrl = freezed,Object? faviconUrl = freezed,Object? siteName = freezed,Object? contentType = freezed,Object? author = freezed,Object? publishedDate = freezed,}) {
|
||||||
return _then(_SnScrappedLink(
|
return _then(_SnScrappedLink(
|
||||||
type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable
|
type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable
|
||||||
as String,url: null == url ? _self.url : url // ignore: cast_nullable_to_non_nullable
|
as String,url: null == url ? _self.url : url // ignore: cast_nullable_to_non_nullable
|
||||||
as String,title: null == title ? _self.title : title // ignore: cast_nullable_to_non_nullable
|
as String,title: null == title ? _self.title : title // ignore: cast_nullable_to_non_nullable
|
||||||
as String,description: freezed == description ? _self.description : description // ignore: cast_nullable_to_non_nullable
|
as String,description: freezed == description ? _self.description : description // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,imageUrl: freezed == imageUrl ? _self.imageUrl : imageUrl // ignore: cast_nullable_to_non_nullable
|
as String?,imageUrl: freezed == imageUrl ? _self.imageUrl : imageUrl // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,faviconUrl: null == faviconUrl ? _self.faviconUrl : faviconUrl // ignore: cast_nullable_to_non_nullable
|
as String?,faviconUrl: freezed == faviconUrl ? _self.faviconUrl : faviconUrl // ignore: cast_nullable_to_non_nullable
|
||||||
as String,siteName: null == siteName ? _self.siteName : siteName // ignore: cast_nullable_to_non_nullable
|
as String?,siteName: freezed == siteName ? _self.siteName : siteName // ignore: cast_nullable_to_non_nullable
|
||||||
as String,contentType: freezed == contentType ? _self.contentType : contentType // ignore: cast_nullable_to_non_nullable
|
as String?,contentType: freezed == contentType ? _self.contentType : contentType // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,author: freezed == author ? _self.author : author // ignore: cast_nullable_to_non_nullable
|
as String?,author: freezed == author ? _self.author : author // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,publishedDate: freezed == publishedDate ? _self.publishedDate : publishedDate // ignore: cast_nullable_to_non_nullable
|
as String?,publishedDate: freezed == publishedDate ? _self.publishedDate : publishedDate // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime?,
|
as DateTime?,
|
||||||
|
@@ -13,8 +13,8 @@ _SnScrappedLink _$SnScrappedLinkFromJson(Map<String, dynamic> json) =>
|
|||||||
title: json['title'] as String,
|
title: json['title'] as String,
|
||||||
description: json['description'] as String?,
|
description: json['description'] as String?,
|
||||||
imageUrl: json['image_url'] as String?,
|
imageUrl: json['image_url'] as String?,
|
||||||
faviconUrl: json['favicon_url'] as String,
|
faviconUrl: json['favicon_url'] as String?,
|
||||||
siteName: json['site_name'] as String,
|
siteName: json['site_name'] as String?,
|
||||||
contentType: json['content_type'] as String?,
|
contentType: json['content_type'] as String?,
|
||||||
author: json['author'] as String?,
|
author: json['author'] as String?,
|
||||||
publishedDate:
|
publishedDate:
|
||||||
|
@@ -3,6 +3,7 @@ import 'package:island/models/file.dart';
|
|||||||
import 'package:island/models/post_category.dart';
|
import 'package:island/models/post_category.dart';
|
||||||
import 'package:island/models/post_tag.dart';
|
import 'package:island/models/post_tag.dart';
|
||||||
import 'package:island/models/publisher.dart';
|
import 'package:island/models/publisher.dart';
|
||||||
|
import 'package:island/models/realm.dart';
|
||||||
|
|
||||||
part 'post.freezed.dart';
|
part 'post.freezed.dart';
|
||||||
part 'post.g.dart';
|
part 'post.g.dart';
|
||||||
@@ -18,6 +19,7 @@ sealed class SnPost with _$SnPost {
|
|||||||
@Default(null) DateTime? publishedAt,
|
@Default(null) DateTime? publishedAt,
|
||||||
@Default(0) int visibility,
|
@Default(0) int visibility,
|
||||||
String? content,
|
String? content,
|
||||||
|
String? slug,
|
||||||
@Default(0) int type,
|
@Default(0) int type,
|
||||||
Map<String, dynamic>? meta,
|
Map<String, dynamic>? meta,
|
||||||
@Default(0) int viewsUnique,
|
@Default(0) int viewsUnique,
|
||||||
@@ -31,6 +33,8 @@ sealed class SnPost with _$SnPost {
|
|||||||
SnPost? repliedPost,
|
SnPost? repliedPost,
|
||||||
String? forwardedPostId,
|
String? forwardedPostId,
|
||||||
SnPost? forwardedPost,
|
SnPost? forwardedPost,
|
||||||
|
String? realmId,
|
||||||
|
SnRealm? realm,
|
||||||
@Default([]) List<SnCloudFile> attachments,
|
@Default([]) List<SnCloudFile> attachments,
|
||||||
required SnPublisher publisher,
|
required SnPublisher publisher,
|
||||||
@Default({}) Map<String, int> reactionsCount,
|
@Default({}) Map<String, int> reactionsCount,
|
||||||
|
@@ -15,7 +15,7 @@ T _$identity<T>(T value) => value;
|
|||||||
/// @nodoc
|
/// @nodoc
|
||||||
mixin _$SnPost {
|
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; int get type; Map<String, dynamic>? get meta; int get viewsUnique; int get viewsTotal; int get upvotes; int get downvotes; int get repliesCount; String? get threadedPostId; SnPost? get threadedPost; String? get repliedPostId; SnPost? get repliedPost; String? get forwardedPostId; SnPost? get forwardedPost; 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; int get viewsUnique; int get viewsTotal; int get upvotes; int get downvotes; int get repliesCount; 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
|
/// Create a copy of SnPost
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@@ -28,16 +28,16 @@ $SnPostCopyWith<SnPost> get copyWith => _$SnPostCopyWithImpl<SnPost>(this as SnP
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
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.type, type) || other.type == type)&&const DeepCollectionEquality().equals(other.meta, meta)&&(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.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)&&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.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.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)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hashAll([runtimeType,id,title,description,language,editedAt,publishedAt,visibility,content,type,const DeepCollectionEquality().hash(meta),viewsUnique,viewsTotal,upvotes,downvotes,repliesCount,threadedPostId,threadedPost,repliedPostId,repliedPost,forwardedPostId,forwardedPost,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),viewsUnique,viewsTotal,upvotes,downvotes,repliesCount,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
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'SnPost(id: $id, title: $title, description: $description, language: $language, editedAt: $editedAt, publishedAt: $publishedAt, visibility: $visibility, content: $content, type: $type, meta: $meta, viewsUnique: $viewsUnique, viewsTotal: $viewsTotal, upvotes: $upvotes, downvotes: $downvotes, repliesCount: $repliesCount, threadedPostId: $threadedPostId, threadedPost: $threadedPost, repliedPostId: $repliedPostId, repliedPost: $repliedPost, forwardedPostId: $forwardedPostId, forwardedPost: $forwardedPost, 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, viewsUnique: $viewsUnique, viewsTotal: $viewsTotal, upvotes: $upvotes, downvotes: $downvotes, repliesCount: $repliesCount, 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,11 +48,11 @@ abstract mixin class $SnPostCopyWith<$Res> {
|
|||||||
factory $SnPostCopyWith(SnPost value, $Res Function(SnPost) _then) = _$SnPostCopyWithImpl;
|
factory $SnPostCopyWith(SnPost value, $Res Function(SnPost) _then) = _$SnPostCopyWithImpl;
|
||||||
@useResult
|
@useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
String id, String? title, String? description, String? language, DateTime? editedAt, DateTime? publishedAt, int visibility, String? content, int type, Map<String, dynamic>? meta, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, String? threadedPostId, SnPost? threadedPost, String? repliedPostId, SnPost? repliedPost, String? forwardedPostId, SnPost? forwardedPost, 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, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, 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
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
$SnPostCopyWith<$Res>? get threadedPost;$SnPostCopyWith<$Res>? get repliedPost;$SnPostCopyWith<$Res>? get forwardedPost;$SnPublisherCopyWith<$Res> get publisher;
|
$SnPostCopyWith<$Res>? get threadedPost;$SnPostCopyWith<$Res>? get repliedPost;$SnPostCopyWith<$Res>? get forwardedPost;$SnRealmCopyWith<$Res>? get realm;$SnPublisherCopyWith<$Res> get publisher;
|
||||||
|
|
||||||
}
|
}
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
@@ -65,7 +65,7 @@ class _$SnPostCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of SnPost
|
/// Create a copy of SnPost
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// 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? type = null,Object? meta = freezed,Object? viewsUnique = null,Object? viewsTotal = null,Object? upvotes = null,Object? downvotes = null,Object? repliesCount = null,Object? threadedPostId = freezed,Object? threadedPost = freezed,Object? repliedPostId = freezed,Object? repliedPost = freezed,Object? forwardedPostId = freezed,Object? forwardedPost = 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? viewsUnique = null,Object? viewsTotal = null,Object? upvotes = null,Object? downvotes = null,Object? repliesCount = null,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(
|
return _then(_self.copyWith(
|
||||||
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
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
|
as String,title: freezed == title ? _self.title : title // ignore: cast_nullable_to_non_nullable
|
||||||
@@ -75,6 +75,7 @@ as String?,editedAt: freezed == editedAt ? _self.editedAt : editedAt // ignore:
|
|||||||
as DateTime?,publishedAt: freezed == publishedAt ? _self.publishedAt : publishedAt // ignore: cast_nullable_to_non_nullable
|
as DateTime?,publishedAt: freezed == publishedAt ? _self.publishedAt : publishedAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime?,visibility: null == visibility ? _self.visibility : visibility // ignore: cast_nullable_to_non_nullable
|
as DateTime?,visibility: null == visibility ? _self.visibility : visibility // ignore: cast_nullable_to_non_nullable
|
||||||
as int,content: freezed == content ? _self.content : content // ignore: cast_nullable_to_non_nullable
|
as int,content: freezed == content ? _self.content : content // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,slug: freezed == slug ? _self.slug : slug // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable
|
as String?,type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable
|
||||||
as int,meta: freezed == meta ? _self.meta : meta // ignore: cast_nullable_to_non_nullable
|
as int,meta: freezed == meta ? _self.meta : meta // ignore: cast_nullable_to_non_nullable
|
||||||
as Map<String, dynamic>?,viewsUnique: null == viewsUnique ? _self.viewsUnique : viewsUnique // ignore: cast_nullable_to_non_nullable
|
as Map<String, dynamic>?,viewsUnique: null == viewsUnique ? _self.viewsUnique : viewsUnique // ignore: cast_nullable_to_non_nullable
|
||||||
@@ -88,7 +89,9 @@ as SnPost?,repliedPostId: freezed == repliedPostId ? _self.repliedPostId : repli
|
|||||||
as String?,repliedPost: freezed == repliedPost ? _self.repliedPost : repliedPost // ignore: cast_nullable_to_non_nullable
|
as String?,repliedPost: freezed == repliedPost ? _self.repliedPost : repliedPost // ignore: cast_nullable_to_non_nullable
|
||||||
as SnPost?,forwardedPostId: freezed == forwardedPostId ? _self.forwardedPostId : forwardedPostId // ignore: cast_nullable_to_non_nullable
|
as SnPost?,forwardedPostId: freezed == forwardedPostId ? _self.forwardedPostId : forwardedPostId // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,forwardedPost: freezed == forwardedPost ? _self.forwardedPost : forwardedPost // ignore: cast_nullable_to_non_nullable
|
as String?,forwardedPost: freezed == forwardedPost ? _self.forwardedPost : forwardedPost // ignore: cast_nullable_to_non_nullable
|
||||||
as SnPost?,attachments: null == attachments ? _self.attachments : attachments // ignore: cast_nullable_to_non_nullable
|
as SnPost?,realmId: freezed == realmId ? _self.realmId : realmId // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,realm: freezed == realm ? _self.realm : realm // ignore: cast_nullable_to_non_nullable
|
||||||
|
as SnRealm?,attachments: null == attachments ? _self.attachments : attachments // ignore: cast_nullable_to_non_nullable
|
||||||
as List<SnCloudFile>,publisher: null == publisher ? _self.publisher : publisher // ignore: cast_nullable_to_non_nullable
|
as List<SnCloudFile>,publisher: null == publisher ? _self.publisher : publisher // ignore: cast_nullable_to_non_nullable
|
||||||
as SnPublisher,reactionsCount: null == reactionsCount ? _self.reactionsCount : reactionsCount // ignore: cast_nullable_to_non_nullable
|
as SnPublisher,reactionsCount: null == reactionsCount ? _self.reactionsCount : reactionsCount // ignore: cast_nullable_to_non_nullable
|
||||||
as Map<String, int>,reactionsMade: null == reactionsMade ? _self.reactionsMade : reactionsMade // ignore: cast_nullable_to_non_nullable
|
as Map<String, int>,reactionsMade: null == reactionsMade ? _self.reactionsMade : reactionsMade // ignore: cast_nullable_to_non_nullable
|
||||||
@@ -143,6 +146,18 @@ $SnPostCopyWith<$Res>? get forwardedPost {
|
|||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@override
|
@override
|
||||||
@pragma('vm:prefer-inline')
|
@pragma('vm:prefer-inline')
|
||||||
|
$SnRealmCopyWith<$Res>? get realm {
|
||||||
|
if (_self.realm == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $SnRealmCopyWith<$Res>(_self.realm!, (value) {
|
||||||
|
return _then(_self.copyWith(realm: value));
|
||||||
|
});
|
||||||
|
}/// Create a copy of SnPost
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
$SnPublisherCopyWith<$Res> get publisher {
|
$SnPublisherCopyWith<$Res> get publisher {
|
||||||
|
|
||||||
return $SnPublisherCopyWith<$Res>(_self.publisher, (value) {
|
return $SnPublisherCopyWith<$Res>(_self.publisher, (value) {
|
||||||
@@ -227,10 +242,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, int type, Map<String, dynamic>? meta, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, String? threadedPostId, SnPost? threadedPost, String? repliedPostId, SnPost? repliedPost, String? forwardedPostId, SnPost? forwardedPost, 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, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, 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) {
|
switch (_that) {
|
||||||
case _SnPost() when $default != null:
|
case _SnPost() when $default != null:
|
||||||
return $default(_that.id,_that.title,_that.description,_that.language,_that.editedAt,_that.publishedAt,_that.visibility,_that.content,_that.type,_that.meta,_that.viewsUnique,_that.viewsTotal,_that.upvotes,_that.downvotes,_that.repliesCount,_that.threadedPostId,_that.threadedPost,_that.repliedPostId,_that.repliedPost,_that.forwardedPostId,_that.forwardedPost,_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.viewsUnique,_that.viewsTotal,_that.upvotes,_that.downvotes,_that.repliesCount,_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();
|
return orElse();
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -248,10 +263,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, int type, Map<String, dynamic>? meta, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, String? threadedPostId, SnPost? threadedPost, String? repliedPostId, SnPost? repliedPost, String? forwardedPostId, SnPost? forwardedPost, 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, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, 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) {
|
switch (_that) {
|
||||||
case _SnPost():
|
case _SnPost():
|
||||||
return $default(_that.id,_that.title,_that.description,_that.language,_that.editedAt,_that.publishedAt,_that.visibility,_that.content,_that.type,_that.meta,_that.viewsUnique,_that.viewsTotal,_that.upvotes,_that.downvotes,_that.repliesCount,_that.threadedPostId,_that.threadedPost,_that.repliedPostId,_that.repliedPost,_that.forwardedPostId,_that.forwardedPost,_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.viewsUnique,_that.viewsTotal,_that.upvotes,_that.downvotes,_that.repliesCount,_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`
|
/// A variant of `when` that fallback to returning `null`
|
||||||
///
|
///
|
||||||
@@ -265,10 +280,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, int type, Map<String, dynamic>? meta, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, String? threadedPostId, SnPost? threadedPost, String? repliedPostId, SnPost? repliedPost, String? forwardedPostId, SnPost? forwardedPost, 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, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, 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) {
|
switch (_that) {
|
||||||
case _SnPost() when $default != null:
|
case _SnPost() when $default != null:
|
||||||
return $default(_that.id,_that.title,_that.description,_that.language,_that.editedAt,_that.publishedAt,_that.visibility,_that.content,_that.type,_that.meta,_that.viewsUnique,_that.viewsTotal,_that.upvotes,_that.downvotes,_that.repliesCount,_that.threadedPostId,_that.threadedPost,_that.repliedPostId,_that.repliedPost,_that.forwardedPostId,_that.forwardedPost,_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.viewsUnique,_that.viewsTotal,_that.upvotes,_that.downvotes,_that.repliesCount,_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;
|
return null;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -280,7 +295,7 @@ return $default(_that.id,_that.title,_that.description,_that.language,_that.edit
|
|||||||
@JsonSerializable()
|
@JsonSerializable()
|
||||||
|
|
||||||
class _SnPost implements SnPost {
|
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.type = 0, final Map<String, dynamic>? meta, this.viewsUnique = 0, this.viewsTotal = 0, this.upvotes = 0, this.downvotes = 0, this.repliesCount = 0, this.threadedPostId, this.threadedPost, this.repliedPostId, this.repliedPost, this.forwardedPostId, this.forwardedPost, 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.viewsUnique = 0, this.viewsTotal = 0, this.upvotes = 0, this.downvotes = 0, this.repliesCount = 0, 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);
|
factory _SnPost.fromJson(Map<String, dynamic> json) => _$SnPostFromJson(json);
|
||||||
|
|
||||||
@override final String id;
|
@override final String id;
|
||||||
@@ -291,6 +306,7 @@ class _SnPost implements SnPost {
|
|||||||
@override@JsonKey() final DateTime? publishedAt;
|
@override@JsonKey() final DateTime? publishedAt;
|
||||||
@override@JsonKey() final int visibility;
|
@override@JsonKey() final int visibility;
|
||||||
@override final String? content;
|
@override final String? content;
|
||||||
|
@override final String? slug;
|
||||||
@override@JsonKey() final int type;
|
@override@JsonKey() final int type;
|
||||||
final Map<String, dynamic>? _meta;
|
final Map<String, dynamic>? _meta;
|
||||||
@override Map<String, dynamic>? get meta {
|
@override Map<String, dynamic>? get meta {
|
||||||
@@ -312,6 +328,8 @@ class _SnPost implements SnPost {
|
|||||||
@override final SnPost? repliedPost;
|
@override final SnPost? repliedPost;
|
||||||
@override final String? forwardedPostId;
|
@override final String? forwardedPostId;
|
||||||
@override final SnPost? forwardedPost;
|
@override final SnPost? forwardedPost;
|
||||||
|
@override final String? realmId;
|
||||||
|
@override final SnRealm? realm;
|
||||||
final List<SnCloudFile> _attachments;
|
final List<SnCloudFile> _attachments;
|
||||||
@override@JsonKey() List<SnCloudFile> get attachments {
|
@override@JsonKey() List<SnCloudFile> get attachments {
|
||||||
if (_attachments is EqualUnmodifiableListView) return _attachments;
|
if (_attachments is EqualUnmodifiableListView) return _attachments;
|
||||||
@@ -380,16 +398,16 @@ Map<String, dynamic> toJson() {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
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.type, type) || other.type == type)&&const DeepCollectionEquality().equals(other._meta, _meta)&&(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.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)&&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.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.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)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hashAll([runtimeType,id,title,description,language,editedAt,publishedAt,visibility,content,type,const DeepCollectionEquality().hash(_meta),viewsUnique,viewsTotal,upvotes,downvotes,repliesCount,threadedPostId,threadedPost,repliedPostId,repliedPost,forwardedPostId,forwardedPost,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),viewsUnique,viewsTotal,upvotes,downvotes,repliesCount,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
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'SnPost(id: $id, title: $title, description: $description, language: $language, editedAt: $editedAt, publishedAt: $publishedAt, visibility: $visibility, content: $content, type: $type, meta: $meta, viewsUnique: $viewsUnique, viewsTotal: $viewsTotal, upvotes: $upvotes, downvotes: $downvotes, repliesCount: $repliesCount, threadedPostId: $threadedPostId, threadedPost: $threadedPost, repliedPostId: $repliedPostId, repliedPost: $repliedPost, forwardedPostId: $forwardedPostId, forwardedPost: $forwardedPost, 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, viewsUnique: $viewsUnique, viewsTotal: $viewsTotal, upvotes: $upvotes, downvotes: $downvotes, repliesCount: $repliesCount, 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)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -400,11 +418,11 @@ abstract mixin class _$SnPostCopyWith<$Res> implements $SnPostCopyWith<$Res> {
|
|||||||
factory _$SnPostCopyWith(_SnPost value, $Res Function(_SnPost) _then) = __$SnPostCopyWithImpl;
|
factory _$SnPostCopyWith(_SnPost value, $Res Function(_SnPost) _then) = __$SnPostCopyWithImpl;
|
||||||
@override @useResult
|
@override @useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
String id, String? title, String? description, String? language, DateTime? editedAt, DateTime? publishedAt, int visibility, String? content, int type, Map<String, dynamic>? meta, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, String? threadedPostId, SnPost? threadedPost, String? repliedPostId, SnPost? repliedPost, String? forwardedPostId, SnPost? forwardedPost, 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, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, 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
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@override $SnPostCopyWith<$Res>? get threadedPost;@override $SnPostCopyWith<$Res>? get repliedPost;@override $SnPostCopyWith<$Res>? get forwardedPost;@override $SnPublisherCopyWith<$Res> get publisher;
|
@override $SnPostCopyWith<$Res>? get threadedPost;@override $SnPostCopyWith<$Res>? get repliedPost;@override $SnPostCopyWith<$Res>? get forwardedPost;@override $SnRealmCopyWith<$Res>? get realm;@override $SnPublisherCopyWith<$Res> get publisher;
|
||||||
|
|
||||||
}
|
}
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
@@ -417,7 +435,7 @@ class __$SnPostCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of SnPost
|
/// Create a copy of SnPost
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// 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? type = null,Object? meta = freezed,Object? viewsUnique = null,Object? viewsTotal = null,Object? upvotes = null,Object? downvotes = null,Object? repliesCount = null,Object? threadedPostId = freezed,Object? threadedPost = freezed,Object? repliedPostId = freezed,Object? repliedPost = freezed,Object? forwardedPostId = freezed,Object? forwardedPost = 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? viewsUnique = null,Object? viewsTotal = null,Object? upvotes = null,Object? downvotes = null,Object? repliesCount = null,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(
|
return _then(_SnPost(
|
||||||
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
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
|
as String,title: freezed == title ? _self.title : title // ignore: cast_nullable_to_non_nullable
|
||||||
@@ -427,6 +445,7 @@ as String?,editedAt: freezed == editedAt ? _self.editedAt : editedAt // ignore:
|
|||||||
as DateTime?,publishedAt: freezed == publishedAt ? _self.publishedAt : publishedAt // ignore: cast_nullable_to_non_nullable
|
as DateTime?,publishedAt: freezed == publishedAt ? _self.publishedAt : publishedAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime?,visibility: null == visibility ? _self.visibility : visibility // ignore: cast_nullable_to_non_nullable
|
as DateTime?,visibility: null == visibility ? _self.visibility : visibility // ignore: cast_nullable_to_non_nullable
|
||||||
as int,content: freezed == content ? _self.content : content // ignore: cast_nullable_to_non_nullable
|
as int,content: freezed == content ? _self.content : content // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,slug: freezed == slug ? _self.slug : slug // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable
|
as String?,type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable
|
||||||
as int,meta: freezed == meta ? _self._meta : meta // ignore: cast_nullable_to_non_nullable
|
as int,meta: freezed == meta ? _self._meta : meta // ignore: cast_nullable_to_non_nullable
|
||||||
as Map<String, dynamic>?,viewsUnique: null == viewsUnique ? _self.viewsUnique : viewsUnique // ignore: cast_nullable_to_non_nullable
|
as Map<String, dynamic>?,viewsUnique: null == viewsUnique ? _self.viewsUnique : viewsUnique // ignore: cast_nullable_to_non_nullable
|
||||||
@@ -440,7 +459,9 @@ as SnPost?,repliedPostId: freezed == repliedPostId ? _self.repliedPostId : repli
|
|||||||
as String?,repliedPost: freezed == repliedPost ? _self.repliedPost : repliedPost // ignore: cast_nullable_to_non_nullable
|
as String?,repliedPost: freezed == repliedPost ? _self.repliedPost : repliedPost // ignore: cast_nullable_to_non_nullable
|
||||||
as SnPost?,forwardedPostId: freezed == forwardedPostId ? _self.forwardedPostId : forwardedPostId // ignore: cast_nullable_to_non_nullable
|
as SnPost?,forwardedPostId: freezed == forwardedPostId ? _self.forwardedPostId : forwardedPostId // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,forwardedPost: freezed == forwardedPost ? _self.forwardedPost : forwardedPost // ignore: cast_nullable_to_non_nullable
|
as String?,forwardedPost: freezed == forwardedPost ? _self.forwardedPost : forwardedPost // ignore: cast_nullable_to_non_nullable
|
||||||
as SnPost?,attachments: null == attachments ? _self._attachments : attachments // ignore: cast_nullable_to_non_nullable
|
as SnPost?,realmId: freezed == realmId ? _self.realmId : realmId // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,realm: freezed == realm ? _self.realm : realm // ignore: cast_nullable_to_non_nullable
|
||||||
|
as SnRealm?,attachments: null == attachments ? _self._attachments : attachments // ignore: cast_nullable_to_non_nullable
|
||||||
as List<SnCloudFile>,publisher: null == publisher ? _self.publisher : publisher // ignore: cast_nullable_to_non_nullable
|
as List<SnCloudFile>,publisher: null == publisher ? _self.publisher : publisher // ignore: cast_nullable_to_non_nullable
|
||||||
as SnPublisher,reactionsCount: null == reactionsCount ? _self._reactionsCount : reactionsCount // ignore: cast_nullable_to_non_nullable
|
as SnPublisher,reactionsCount: null == reactionsCount ? _self._reactionsCount : reactionsCount // ignore: cast_nullable_to_non_nullable
|
||||||
as Map<String, int>,reactionsMade: null == reactionsMade ? _self._reactionsMade : reactionsMade // ignore: cast_nullable_to_non_nullable
|
as Map<String, int>,reactionsMade: null == reactionsMade ? _self._reactionsMade : reactionsMade // ignore: cast_nullable_to_non_nullable
|
||||||
@@ -496,6 +517,18 @@ $SnPostCopyWith<$Res>? get forwardedPost {
|
|||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@override
|
@override
|
||||||
@pragma('vm:prefer-inline')
|
@pragma('vm:prefer-inline')
|
||||||
|
$SnRealmCopyWith<$Res>? get realm {
|
||||||
|
if (_self.realm == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $SnRealmCopyWith<$Res>(_self.realm!, (value) {
|
||||||
|
return _then(_self.copyWith(realm: value));
|
||||||
|
});
|
||||||
|
}/// Create a copy of SnPost
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
$SnPublisherCopyWith<$Res> get publisher {
|
$SnPublisherCopyWith<$Res> get publisher {
|
||||||
|
|
||||||
return $SnPublisherCopyWith<$Res>(_self.publisher, (value) {
|
return $SnPublisherCopyWith<$Res>(_self.publisher, (value) {
|
||||||
|
@@ -21,6 +21,7 @@ _SnPost _$SnPostFromJson(Map<String, dynamic> json) => _SnPost(
|
|||||||
: DateTime.parse(json['published_at'] as String),
|
: DateTime.parse(json['published_at'] as String),
|
||||||
visibility: (json['visibility'] as num?)?.toInt() ?? 0,
|
visibility: (json['visibility'] as num?)?.toInt() ?? 0,
|
||||||
content: json['content'] as String?,
|
content: json['content'] as String?,
|
||||||
|
slug: json['slug'] as String?,
|
||||||
type: (json['type'] as num?)?.toInt() ?? 0,
|
type: (json['type'] as num?)?.toInt() ?? 0,
|
||||||
meta: json['meta'] as Map<String, dynamic>?,
|
meta: json['meta'] as Map<String, dynamic>?,
|
||||||
viewsUnique: (json['views_unique'] as num?)?.toInt() ?? 0,
|
viewsUnique: (json['views_unique'] as num?)?.toInt() ?? 0,
|
||||||
@@ -43,6 +44,11 @@ _SnPost _$SnPostFromJson(Map<String, dynamic> json) => _SnPost(
|
|||||||
json['forwarded_post'] == null
|
json['forwarded_post'] == null
|
||||||
? null
|
? null
|
||||||
: SnPost.fromJson(json['forwarded_post'] as Map<String, dynamic>),
|
: SnPost.fromJson(json['forwarded_post'] as Map<String, dynamic>),
|
||||||
|
realmId: json['realm_id'] as String?,
|
||||||
|
realm:
|
||||||
|
json['realm'] == null
|
||||||
|
? null
|
||||||
|
: SnRealm.fromJson(json['realm'] as Map<String, dynamic>),
|
||||||
attachments:
|
attachments:
|
||||||
(json['attachments'] as List<dynamic>?)
|
(json['attachments'] as List<dynamic>?)
|
||||||
?.map((e) => SnCloudFile.fromJson(e as Map<String, dynamic>))
|
?.map((e) => SnCloudFile.fromJson(e as Map<String, dynamic>))
|
||||||
@@ -95,6 +101,7 @@ Map<String, dynamic> _$SnPostToJson(_SnPost instance) => <String, dynamic>{
|
|||||||
'published_at': instance.publishedAt?.toIso8601String(),
|
'published_at': instance.publishedAt?.toIso8601String(),
|
||||||
'visibility': instance.visibility,
|
'visibility': instance.visibility,
|
||||||
'content': instance.content,
|
'content': instance.content,
|
||||||
|
'slug': instance.slug,
|
||||||
'type': instance.type,
|
'type': instance.type,
|
||||||
'meta': instance.meta,
|
'meta': instance.meta,
|
||||||
'views_unique': instance.viewsUnique,
|
'views_unique': instance.viewsUnique,
|
||||||
@@ -108,6 +115,8 @@ Map<String, dynamic> _$SnPostToJson(_SnPost instance) => <String, dynamic>{
|
|||||||
'replied_post': instance.repliedPost?.toJson(),
|
'replied_post': instance.repliedPost?.toJson(),
|
||||||
'forwarded_post_id': instance.forwardedPostId,
|
'forwarded_post_id': instance.forwardedPostId,
|
||||||
'forwarded_post': instance.forwardedPost?.toJson(),
|
'forwarded_post': instance.forwardedPost?.toJson(),
|
||||||
|
'realm_id': instance.realmId,
|
||||||
|
'realm': instance.realm?.toJson(),
|
||||||
'attachments': instance.attachments.map((e) => e.toJson()).toList(),
|
'attachments': instance.attachments.map((e) => e.toJson()).toList(),
|
||||||
'publisher': instance.publisher.toJson(),
|
'publisher': instance.publisher.toJson(),
|
||||||
'reactions_count': instance.reactionsCount,
|
'reactions_count': instance.reactionsCount,
|
||||||
|
@@ -15,6 +15,7 @@ sealed class SnPostCategory with _$SnPostCategory {
|
|||||||
required String slug,
|
required String slug,
|
||||||
String? name,
|
String? name,
|
||||||
@Default([]) List<SnPost> posts,
|
@Default([]) List<SnPost> posts,
|
||||||
|
@Default(0) int usage,
|
||||||
}) = _SnPostCategory;
|
}) = _SnPostCategory;
|
||||||
|
|
||||||
factory SnPostCategory.fromJson(Map<String, dynamic> json) =>
|
factory SnPostCategory.fromJson(Map<String, dynamic> json) =>
|
||||||
|
@@ -15,7 +15,7 @@ T _$identity<T>(T value) => value;
|
|||||||
/// @nodoc
|
/// @nodoc
|
||||||
mixin _$SnPostCategory {
|
mixin _$SnPostCategory {
|
||||||
|
|
||||||
String get id; String get slug; String? get name; List<SnPost> get posts;
|
String get id; String get slug; String? get name; List<SnPost> get posts; int get usage;
|
||||||
/// Create a copy of SnPostCategory
|
/// Create a copy of SnPostCategory
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@@ -28,16 +28,16 @@ $SnPostCategoryCopyWith<SnPostCategory> get copyWith => _$SnPostCategoryCopyWith
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnPostCategory&&(identical(other.id, id) || other.id == id)&&(identical(other.slug, slug) || other.slug == slug)&&(identical(other.name, name) || other.name == name)&&const DeepCollectionEquality().equals(other.posts, posts));
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnPostCategory&&(identical(other.id, id) || other.id == id)&&(identical(other.slug, slug) || other.slug == slug)&&(identical(other.name, name) || other.name == name)&&const DeepCollectionEquality().equals(other.posts, posts)&&(identical(other.usage, usage) || other.usage == usage));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType,id,slug,name,const DeepCollectionEquality().hash(posts));
|
int get hashCode => Object.hash(runtimeType,id,slug,name,const DeepCollectionEquality().hash(posts),usage);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'SnPostCategory(id: $id, slug: $slug, name: $name, posts: $posts)';
|
return 'SnPostCategory(id: $id, slug: $slug, name: $name, posts: $posts, usage: $usage)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -48,7 +48,7 @@ abstract mixin class $SnPostCategoryCopyWith<$Res> {
|
|||||||
factory $SnPostCategoryCopyWith(SnPostCategory value, $Res Function(SnPostCategory) _then) = _$SnPostCategoryCopyWithImpl;
|
factory $SnPostCategoryCopyWith(SnPostCategory value, $Res Function(SnPostCategory) _then) = _$SnPostCategoryCopyWithImpl;
|
||||||
@useResult
|
@useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
String id, String slug, String? name, List<SnPost> posts
|
String id, String slug, String? name, List<SnPost> posts, int usage
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -65,13 +65,14 @@ class _$SnPostCategoryCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of SnPostCategory
|
/// Create a copy of SnPostCategory
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? slug = null,Object? name = freezed,Object? posts = null,}) {
|
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? slug = null,Object? name = freezed,Object? posts = null,Object? usage = null,}) {
|
||||||
return _then(_self.copyWith(
|
return _then(_self.copyWith(
|
||||||
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||||
as String,slug: null == slug ? _self.slug : slug // ignore: cast_nullable_to_non_nullable
|
as String,slug: null == slug ? _self.slug : slug // ignore: cast_nullable_to_non_nullable
|
||||||
as String,name: freezed == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
|
as String,name: freezed == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,posts: null == posts ? _self.posts : posts // ignore: cast_nullable_to_non_nullable
|
as String?,posts: null == posts ? _self.posts : posts // ignore: cast_nullable_to_non_nullable
|
||||||
as List<SnPost>,
|
as List<SnPost>,usage: null == usage ? _self.usage : usage // ignore: cast_nullable_to_non_nullable
|
||||||
|
as int,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,10 +154,10 @@ return $default(_that);case _:
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String id, String slug, String? name, List<SnPost> posts)? $default,{required TResult orElse(),}) {final _that = this;
|
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String id, String slug, String? name, List<SnPost> posts, int usage)? $default,{required TResult orElse(),}) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _SnPostCategory() when $default != null:
|
case _SnPostCategory() when $default != null:
|
||||||
return $default(_that.id,_that.slug,_that.name,_that.posts);case _:
|
return $default(_that.id,_that.slug,_that.name,_that.posts,_that.usage);case _:
|
||||||
return orElse();
|
return orElse();
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -174,10 +175,10 @@ return $default(_that.id,_that.slug,_that.name,_that.posts);case _:
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String id, String slug, String? name, List<SnPost> posts) $default,) {final _that = this;
|
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String id, String slug, String? name, List<SnPost> posts, int usage) $default,) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _SnPostCategory():
|
case _SnPostCategory():
|
||||||
return $default(_that.id,_that.slug,_that.name,_that.posts);}
|
return $default(_that.id,_that.slug,_that.name,_that.posts,_that.usage);}
|
||||||
}
|
}
|
||||||
/// A variant of `when` that fallback to returning `null`
|
/// A variant of `when` that fallback to returning `null`
|
||||||
///
|
///
|
||||||
@@ -191,10 +192,10 @@ return $default(_that.id,_that.slug,_that.name,_that.posts);}
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String id, String slug, String? name, List<SnPost> posts)? $default,) {final _that = this;
|
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String id, String slug, String? name, List<SnPost> posts, int usage)? $default,) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _SnPostCategory() when $default != null:
|
case _SnPostCategory() when $default != null:
|
||||||
return $default(_that.id,_that.slug,_that.name,_that.posts);case _:
|
return $default(_that.id,_that.slug,_that.name,_that.posts,_that.usage);case _:
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -206,7 +207,7 @@ return $default(_that.id,_that.slug,_that.name,_that.posts);case _:
|
|||||||
@JsonSerializable()
|
@JsonSerializable()
|
||||||
|
|
||||||
class _SnPostCategory extends SnPostCategory {
|
class _SnPostCategory extends SnPostCategory {
|
||||||
const _SnPostCategory({required this.id, required this.slug, this.name, final List<SnPost> posts = const []}): _posts = posts,super._();
|
const _SnPostCategory({required this.id, required this.slug, this.name, final List<SnPost> posts = const [], this.usage = 0}): _posts = posts,super._();
|
||||||
factory _SnPostCategory.fromJson(Map<String, dynamic> json) => _$SnPostCategoryFromJson(json);
|
factory _SnPostCategory.fromJson(Map<String, dynamic> json) => _$SnPostCategoryFromJson(json);
|
||||||
|
|
||||||
@override final String id;
|
@override final String id;
|
||||||
@@ -219,6 +220,7 @@ class _SnPostCategory extends SnPostCategory {
|
|||||||
return EqualUnmodifiableListView(_posts);
|
return EqualUnmodifiableListView(_posts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override@JsonKey() final int usage;
|
||||||
|
|
||||||
/// Create a copy of SnPostCategory
|
/// Create a copy of SnPostCategory
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@@ -233,16 +235,16 @@ Map<String, dynamic> toJson() {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnPostCategory&&(identical(other.id, id) || other.id == id)&&(identical(other.slug, slug) || other.slug == slug)&&(identical(other.name, name) || other.name == name)&&const DeepCollectionEquality().equals(other._posts, _posts));
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnPostCategory&&(identical(other.id, id) || other.id == id)&&(identical(other.slug, slug) || other.slug == slug)&&(identical(other.name, name) || other.name == name)&&const DeepCollectionEquality().equals(other._posts, _posts)&&(identical(other.usage, usage) || other.usage == usage));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType,id,slug,name,const DeepCollectionEquality().hash(_posts));
|
int get hashCode => Object.hash(runtimeType,id,slug,name,const DeepCollectionEquality().hash(_posts),usage);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'SnPostCategory(id: $id, slug: $slug, name: $name, posts: $posts)';
|
return 'SnPostCategory(id: $id, slug: $slug, name: $name, posts: $posts, usage: $usage)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -253,7 +255,7 @@ abstract mixin class _$SnPostCategoryCopyWith<$Res> implements $SnPostCategoryCo
|
|||||||
factory _$SnPostCategoryCopyWith(_SnPostCategory value, $Res Function(_SnPostCategory) _then) = __$SnPostCategoryCopyWithImpl;
|
factory _$SnPostCategoryCopyWith(_SnPostCategory value, $Res Function(_SnPostCategory) _then) = __$SnPostCategoryCopyWithImpl;
|
||||||
@override @useResult
|
@override @useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
String id, String slug, String? name, List<SnPost> posts
|
String id, String slug, String? name, List<SnPost> posts, int usage
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -270,13 +272,14 @@ class __$SnPostCategoryCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of SnPostCategory
|
/// Create a copy of SnPostCategory
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? slug = null,Object? name = freezed,Object? posts = null,}) {
|
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? slug = null,Object? name = freezed,Object? posts = null,Object? usage = null,}) {
|
||||||
return _then(_SnPostCategory(
|
return _then(_SnPostCategory(
|
||||||
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||||
as String,slug: null == slug ? _self.slug : slug // ignore: cast_nullable_to_non_nullable
|
as String,slug: null == slug ? _self.slug : slug // ignore: cast_nullable_to_non_nullable
|
||||||
as String,name: freezed == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
|
as String,name: freezed == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,posts: null == posts ? _self._posts : posts // ignore: cast_nullable_to_non_nullable
|
as String?,posts: null == posts ? _self._posts : posts // ignore: cast_nullable_to_non_nullable
|
||||||
as List<SnPost>,
|
as List<SnPost>,usage: null == usage ? _self.usage : usage // ignore: cast_nullable_to_non_nullable
|
||||||
|
as int,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -16,6 +16,7 @@ _SnPostCategory _$SnPostCategoryFromJson(Map<String, dynamic> json) =>
|
|||||||
?.map((e) => SnPost.fromJson(e as Map<String, dynamic>))
|
?.map((e) => SnPost.fromJson(e as Map<String, dynamic>))
|
||||||
.toList() ??
|
.toList() ??
|
||||||
const [],
|
const [],
|
||||||
|
usage: (json['usage'] as num?)?.toInt() ?? 0,
|
||||||
);
|
);
|
||||||
|
|
||||||
Map<String, dynamic> _$SnPostCategoryToJson(_SnPostCategory instance) =>
|
Map<String, dynamic> _$SnPostCategoryToJson(_SnPostCategory instance) =>
|
||||||
@@ -24,4 +25,5 @@ Map<String, dynamic> _$SnPostCategoryToJson(_SnPostCategory instance) =>
|
|||||||
'slug': instance.slug,
|
'slug': instance.slug,
|
||||||
'name': instance.name,
|
'name': instance.name,
|
||||||
'posts': instance.posts.map((e) => e.toJson()).toList(),
|
'posts': instance.posts.map((e) => e.toJson()).toList(),
|
||||||
|
'usage': instance.usage,
|
||||||
};
|
};
|
||||||
|
@@ -11,6 +11,7 @@ sealed class SnPostTag with _$SnPostTag {
|
|||||||
required String slug,
|
required String slug,
|
||||||
String? name,
|
String? name,
|
||||||
@Default([]) List<SnPost> posts,
|
@Default([]) List<SnPost> posts,
|
||||||
|
@Default(0) int usage,
|
||||||
}) = _SnPostTag;
|
}) = _SnPostTag;
|
||||||
|
|
||||||
factory SnPostTag.fromJson(Map<String, dynamic> json) =>
|
factory SnPostTag.fromJson(Map<String, dynamic> json) =>
|
||||||
|
@@ -15,7 +15,7 @@ T _$identity<T>(T value) => value;
|
|||||||
/// @nodoc
|
/// @nodoc
|
||||||
mixin _$SnPostTag {
|
mixin _$SnPostTag {
|
||||||
|
|
||||||
String get id; String get slug; String? get name; List<SnPost> get posts;
|
String get id; String get slug; String? get name; List<SnPost> get posts; int get usage;
|
||||||
/// Create a copy of SnPostTag
|
/// Create a copy of SnPostTag
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@@ -28,16 +28,16 @@ $SnPostTagCopyWith<SnPostTag> get copyWith => _$SnPostTagCopyWithImpl<SnPostTag>
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnPostTag&&(identical(other.id, id) || other.id == id)&&(identical(other.slug, slug) || other.slug == slug)&&(identical(other.name, name) || other.name == name)&&const DeepCollectionEquality().equals(other.posts, posts));
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnPostTag&&(identical(other.id, id) || other.id == id)&&(identical(other.slug, slug) || other.slug == slug)&&(identical(other.name, name) || other.name == name)&&const DeepCollectionEquality().equals(other.posts, posts)&&(identical(other.usage, usage) || other.usage == usage));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType,id,slug,name,const DeepCollectionEquality().hash(posts));
|
int get hashCode => Object.hash(runtimeType,id,slug,name,const DeepCollectionEquality().hash(posts),usage);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'SnPostTag(id: $id, slug: $slug, name: $name, posts: $posts)';
|
return 'SnPostTag(id: $id, slug: $slug, name: $name, posts: $posts, usage: $usage)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -48,7 +48,7 @@ abstract mixin class $SnPostTagCopyWith<$Res> {
|
|||||||
factory $SnPostTagCopyWith(SnPostTag value, $Res Function(SnPostTag) _then) = _$SnPostTagCopyWithImpl;
|
factory $SnPostTagCopyWith(SnPostTag value, $Res Function(SnPostTag) _then) = _$SnPostTagCopyWithImpl;
|
||||||
@useResult
|
@useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
String id, String slug, String? name, List<SnPost> posts
|
String id, String slug, String? name, List<SnPost> posts, int usage
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -65,13 +65,14 @@ class _$SnPostTagCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of SnPostTag
|
/// Create a copy of SnPostTag
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? slug = null,Object? name = freezed,Object? posts = null,}) {
|
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? slug = null,Object? name = freezed,Object? posts = null,Object? usage = null,}) {
|
||||||
return _then(_self.copyWith(
|
return _then(_self.copyWith(
|
||||||
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||||
as String,slug: null == slug ? _self.slug : slug // ignore: cast_nullable_to_non_nullable
|
as String,slug: null == slug ? _self.slug : slug // ignore: cast_nullable_to_non_nullable
|
||||||
as String,name: freezed == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
|
as String,name: freezed == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,posts: null == posts ? _self.posts : posts // ignore: cast_nullable_to_non_nullable
|
as String?,posts: null == posts ? _self.posts : posts // ignore: cast_nullable_to_non_nullable
|
||||||
as List<SnPost>,
|
as List<SnPost>,usage: null == usage ? _self.usage : usage // ignore: cast_nullable_to_non_nullable
|
||||||
|
as int,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,10 +154,10 @@ return $default(_that);case _:
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String id, String slug, String? name, List<SnPost> posts)? $default,{required TResult orElse(),}) {final _that = this;
|
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String id, String slug, String? name, List<SnPost> posts, int usage)? $default,{required TResult orElse(),}) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _SnPostTag() when $default != null:
|
case _SnPostTag() when $default != null:
|
||||||
return $default(_that.id,_that.slug,_that.name,_that.posts);case _:
|
return $default(_that.id,_that.slug,_that.name,_that.posts,_that.usage);case _:
|
||||||
return orElse();
|
return orElse();
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -174,10 +175,10 @@ return $default(_that.id,_that.slug,_that.name,_that.posts);case _:
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String id, String slug, String? name, List<SnPost> posts) $default,) {final _that = this;
|
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String id, String slug, String? name, List<SnPost> posts, int usage) $default,) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _SnPostTag():
|
case _SnPostTag():
|
||||||
return $default(_that.id,_that.slug,_that.name,_that.posts);}
|
return $default(_that.id,_that.slug,_that.name,_that.posts,_that.usage);}
|
||||||
}
|
}
|
||||||
/// A variant of `when` that fallback to returning `null`
|
/// A variant of `when` that fallback to returning `null`
|
||||||
///
|
///
|
||||||
@@ -191,10 +192,10 @@ return $default(_that.id,_that.slug,_that.name,_that.posts);}
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String id, String slug, String? name, List<SnPost> posts)? $default,) {final _that = this;
|
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String id, String slug, String? name, List<SnPost> posts, int usage)? $default,) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _SnPostTag() when $default != null:
|
case _SnPostTag() when $default != null:
|
||||||
return $default(_that.id,_that.slug,_that.name,_that.posts);case _:
|
return $default(_that.id,_that.slug,_that.name,_that.posts,_that.usage);case _:
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -206,7 +207,7 @@ return $default(_that.id,_that.slug,_that.name,_that.posts);case _:
|
|||||||
@JsonSerializable()
|
@JsonSerializable()
|
||||||
|
|
||||||
class _SnPostTag implements SnPostTag {
|
class _SnPostTag implements SnPostTag {
|
||||||
const _SnPostTag({required this.id, required this.slug, this.name, final List<SnPost> posts = const []}): _posts = posts;
|
const _SnPostTag({required this.id, required this.slug, this.name, final List<SnPost> posts = const [], this.usage = 0}): _posts = posts;
|
||||||
factory _SnPostTag.fromJson(Map<String, dynamic> json) => _$SnPostTagFromJson(json);
|
factory _SnPostTag.fromJson(Map<String, dynamic> json) => _$SnPostTagFromJson(json);
|
||||||
|
|
||||||
@override final String id;
|
@override final String id;
|
||||||
@@ -219,6 +220,7 @@ class _SnPostTag implements SnPostTag {
|
|||||||
return EqualUnmodifiableListView(_posts);
|
return EqualUnmodifiableListView(_posts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override@JsonKey() final int usage;
|
||||||
|
|
||||||
/// Create a copy of SnPostTag
|
/// Create a copy of SnPostTag
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@@ -233,16 +235,16 @@ Map<String, dynamic> toJson() {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnPostTag&&(identical(other.id, id) || other.id == id)&&(identical(other.slug, slug) || other.slug == slug)&&(identical(other.name, name) || other.name == name)&&const DeepCollectionEquality().equals(other._posts, _posts));
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnPostTag&&(identical(other.id, id) || other.id == id)&&(identical(other.slug, slug) || other.slug == slug)&&(identical(other.name, name) || other.name == name)&&const DeepCollectionEquality().equals(other._posts, _posts)&&(identical(other.usage, usage) || other.usage == usage));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType,id,slug,name,const DeepCollectionEquality().hash(_posts));
|
int get hashCode => Object.hash(runtimeType,id,slug,name,const DeepCollectionEquality().hash(_posts),usage);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'SnPostTag(id: $id, slug: $slug, name: $name, posts: $posts)';
|
return 'SnPostTag(id: $id, slug: $slug, name: $name, posts: $posts, usage: $usage)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -253,7 +255,7 @@ abstract mixin class _$SnPostTagCopyWith<$Res> implements $SnPostTagCopyWith<$Re
|
|||||||
factory _$SnPostTagCopyWith(_SnPostTag value, $Res Function(_SnPostTag) _then) = __$SnPostTagCopyWithImpl;
|
factory _$SnPostTagCopyWith(_SnPostTag value, $Res Function(_SnPostTag) _then) = __$SnPostTagCopyWithImpl;
|
||||||
@override @useResult
|
@override @useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
String id, String slug, String? name, List<SnPost> posts
|
String id, String slug, String? name, List<SnPost> posts, int usage
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -270,13 +272,14 @@ class __$SnPostTagCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of SnPostTag
|
/// Create a copy of SnPostTag
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? slug = null,Object? name = freezed,Object? posts = null,}) {
|
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? slug = null,Object? name = freezed,Object? posts = null,Object? usage = null,}) {
|
||||||
return _then(_SnPostTag(
|
return _then(_SnPostTag(
|
||||||
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||||
as String,slug: null == slug ? _self.slug : slug // ignore: cast_nullable_to_non_nullable
|
as String,slug: null == slug ? _self.slug : slug // ignore: cast_nullable_to_non_nullable
|
||||||
as String,name: freezed == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
|
as String,name: freezed == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,posts: null == posts ? _self._posts : posts // ignore: cast_nullable_to_non_nullable
|
as String?,posts: null == posts ? _self._posts : posts // ignore: cast_nullable_to_non_nullable
|
||||||
as List<SnPost>,
|
as List<SnPost>,usage: null == usage ? _self.usage : usage // ignore: cast_nullable_to_non_nullable
|
||||||
|
as int,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -15,6 +15,7 @@ _SnPostTag _$SnPostTagFromJson(Map<String, dynamic> json) => _SnPostTag(
|
|||||||
?.map((e) => SnPost.fromJson(e as Map<String, dynamic>))
|
?.map((e) => SnPost.fromJson(e as Map<String, dynamic>))
|
||||||
.toList() ??
|
.toList() ??
|
||||||
const [],
|
const [],
|
||||||
|
usage: (json['usage'] as num?)?.toInt() ?? 0,
|
||||||
);
|
);
|
||||||
|
|
||||||
Map<String, dynamic> _$SnPostTagToJson(_SnPostTag instance) =>
|
Map<String, dynamic> _$SnPostTagToJson(_SnPostTag instance) =>
|
||||||
@@ -23,4 +24,5 @@ Map<String, dynamic> _$SnPostTagToJson(_SnPostTag instance) =>
|
|||||||
'slug': instance.slug,
|
'slug': instance.slug,
|
||||||
'name': instance.name,
|
'name': instance.name,
|
||||||
'posts': instance.posts.map((e) => e.toJson()).toList(),
|
'posts': instance.posts.map((e) => e.toJson()).toList(),
|
||||||
|
'usage': instance.usage,
|
||||||
};
|
};
|
||||||
|
@@ -40,6 +40,7 @@ sealed class SnRealmMember with _$SnRealmMember {
|
|||||||
required DateTime createdAt,
|
required DateTime createdAt,
|
||||||
required DateTime updatedAt,
|
required DateTime updatedAt,
|
||||||
required DateTime? deletedAt,
|
required DateTime? deletedAt,
|
||||||
|
required SnAccountStatus? status,
|
||||||
}) = _SnRealmMember;
|
}) = _SnRealmMember;
|
||||||
|
|
||||||
factory SnRealmMember.fromJson(Map<String, dynamic> json) =>
|
factory SnRealmMember.fromJson(Map<String, dynamic> json) =>
|
||||||
|
@@ -359,7 +359,7 @@ $SnCloudFileCopyWith<$Res>? get background {
|
|||||||
/// @nodoc
|
/// @nodoc
|
||||||
mixin _$SnRealmMember {
|
mixin _$SnRealmMember {
|
||||||
|
|
||||||
String get realmId; SnRealm? get realm; String get accountId; SnAccount? get account; int get role; DateTime? get joinedAt; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt;
|
String get realmId; SnRealm? get realm; String get accountId; SnAccount? get account; int get role; DateTime? get joinedAt; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt; SnAccountStatus? get status;
|
||||||
/// Create a copy of SnRealmMember
|
/// Create a copy of SnRealmMember
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@@ -372,16 +372,16 @@ $SnRealmMemberCopyWith<SnRealmMember> get copyWith => _$SnRealmMemberCopyWithImp
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnRealmMember&&(identical(other.realmId, realmId) || other.realmId == realmId)&&(identical(other.realm, realm) || other.realm == realm)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.account, account) || other.account == account)&&(identical(other.role, role) || other.role == role)&&(identical(other.joinedAt, joinedAt) || other.joinedAt == joinedAt)&&(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 SnRealmMember&&(identical(other.realmId, realmId) || other.realmId == realmId)&&(identical(other.realm, realm) || other.realm == realm)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.account, account) || other.account == account)&&(identical(other.role, role) || other.role == role)&&(identical(other.joinedAt, joinedAt) || other.joinedAt == joinedAt)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)&&(identical(other.status, status) || other.status == status));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType,realmId,realm,accountId,account,role,joinedAt,createdAt,updatedAt,deletedAt);
|
int get hashCode => Object.hash(runtimeType,realmId,realm,accountId,account,role,joinedAt,createdAt,updatedAt,deletedAt,status);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'SnRealmMember(realmId: $realmId, realm: $realm, accountId: $accountId, account: $account, role: $role, joinedAt: $joinedAt, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
return 'SnRealmMember(realmId: $realmId, realm: $realm, accountId: $accountId, account: $account, role: $role, joinedAt: $joinedAt, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, status: $status)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -392,11 +392,11 @@ abstract mixin class $SnRealmMemberCopyWith<$Res> {
|
|||||||
factory $SnRealmMemberCopyWith(SnRealmMember value, $Res Function(SnRealmMember) _then) = _$SnRealmMemberCopyWithImpl;
|
factory $SnRealmMemberCopyWith(SnRealmMember value, $Res Function(SnRealmMember) _then) = _$SnRealmMemberCopyWithImpl;
|
||||||
@useResult
|
@useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
String realmId, SnRealm? realm, String accountId, SnAccount? account, int role, DateTime? joinedAt, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
String realmId, SnRealm? realm, String accountId, SnAccount? account, int role, DateTime? joinedAt, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, SnAccountStatus? status
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
$SnRealmCopyWith<$Res>? get realm;$SnAccountCopyWith<$Res>? get account;
|
$SnRealmCopyWith<$Res>? get realm;$SnAccountCopyWith<$Res>? get account;$SnAccountStatusCopyWith<$Res>? get status;
|
||||||
|
|
||||||
}
|
}
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
@@ -409,7 +409,7 @@ class _$SnRealmMemberCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of SnRealmMember
|
/// Create a copy of SnRealmMember
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@pragma('vm:prefer-inline') @override $Res call({Object? realmId = null,Object? realm = freezed,Object? accountId = null,Object? account = freezed,Object? role = null,Object? joinedAt = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
@pragma('vm:prefer-inline') @override $Res call({Object? realmId = null,Object? realm = freezed,Object? accountId = null,Object? account = freezed,Object? role = null,Object? joinedAt = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,Object? status = freezed,}) {
|
||||||
return _then(_self.copyWith(
|
return _then(_self.copyWith(
|
||||||
realmId: null == realmId ? _self.realmId : realmId // ignore: cast_nullable_to_non_nullable
|
realmId: null == realmId ? _self.realmId : realmId // ignore: cast_nullable_to_non_nullable
|
||||||
as String,realm: freezed == realm ? _self.realm : realm // ignore: cast_nullable_to_non_nullable
|
as String,realm: freezed == realm ? _self.realm : realm // ignore: cast_nullable_to_non_nullable
|
||||||
@@ -420,7 +420,8 @@ as int,joinedAt: freezed == joinedAt ? _self.joinedAt : joinedAt // ignore: cast
|
|||||||
as DateTime?,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
as DateTime?,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,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,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime?,
|
as DateTime?,status: freezed == status ? _self.status : status // ignore: cast_nullable_to_non_nullable
|
||||||
|
as SnAccountStatus?,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
/// Create a copy of SnRealmMember
|
/// Create a copy of SnRealmMember
|
||||||
@@ -447,6 +448,18 @@ $SnAccountCopyWith<$Res>? get account {
|
|||||||
return $SnAccountCopyWith<$Res>(_self.account!, (value) {
|
return $SnAccountCopyWith<$Res>(_self.account!, (value) {
|
||||||
return _then(_self.copyWith(account: value));
|
return _then(_self.copyWith(account: value));
|
||||||
});
|
});
|
||||||
|
}/// Create a copy of SnRealmMember
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$SnAccountStatusCopyWith<$Res>? get status {
|
||||||
|
if (_self.status == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $SnAccountStatusCopyWith<$Res>(_self.status!, (value) {
|
||||||
|
return _then(_self.copyWith(status: value));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -526,10 +539,10 @@ return $default(_that);case _:
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String realmId, SnRealm? realm, String accountId, SnAccount? account, int role, DateTime? joinedAt, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,{required TResult orElse(),}) {final _that = this;
|
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String realmId, SnRealm? realm, String accountId, SnAccount? account, int role, DateTime? joinedAt, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, SnAccountStatus? status)? $default,{required TResult orElse(),}) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _SnRealmMember() when $default != null:
|
case _SnRealmMember() when $default != null:
|
||||||
return $default(_that.realmId,_that.realm,_that.accountId,_that.account,_that.role,_that.joinedAt,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
|
return $default(_that.realmId,_that.realm,_that.accountId,_that.account,_that.role,_that.joinedAt,_that.createdAt,_that.updatedAt,_that.deletedAt,_that.status);case _:
|
||||||
return orElse();
|
return orElse();
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -547,10 +560,10 @@ return $default(_that.realmId,_that.realm,_that.accountId,_that.account,_that.ro
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String realmId, SnRealm? realm, String accountId, SnAccount? account, int role, DateTime? joinedAt, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt) $default,) {final _that = this;
|
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String realmId, SnRealm? realm, String accountId, SnAccount? account, int role, DateTime? joinedAt, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, SnAccountStatus? status) $default,) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _SnRealmMember():
|
case _SnRealmMember():
|
||||||
return $default(_that.realmId,_that.realm,_that.accountId,_that.account,_that.role,_that.joinedAt,_that.createdAt,_that.updatedAt,_that.deletedAt);}
|
return $default(_that.realmId,_that.realm,_that.accountId,_that.account,_that.role,_that.joinedAt,_that.createdAt,_that.updatedAt,_that.deletedAt,_that.status);}
|
||||||
}
|
}
|
||||||
/// A variant of `when` that fallback to returning `null`
|
/// A variant of `when` that fallback to returning `null`
|
||||||
///
|
///
|
||||||
@@ -564,10 +577,10 @@ return $default(_that.realmId,_that.realm,_that.accountId,_that.account,_that.ro
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String realmId, SnRealm? realm, String accountId, SnAccount? account, int role, DateTime? joinedAt, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,) {final _that = this;
|
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String realmId, SnRealm? realm, String accountId, SnAccount? account, int role, DateTime? joinedAt, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, SnAccountStatus? status)? $default,) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _SnRealmMember() when $default != null:
|
case _SnRealmMember() when $default != null:
|
||||||
return $default(_that.realmId,_that.realm,_that.accountId,_that.account,_that.role,_that.joinedAt,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
|
return $default(_that.realmId,_that.realm,_that.accountId,_that.account,_that.role,_that.joinedAt,_that.createdAt,_that.updatedAt,_that.deletedAt,_that.status);case _:
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -579,7 +592,7 @@ return $default(_that.realmId,_that.realm,_that.accountId,_that.account,_that.ro
|
|||||||
@JsonSerializable()
|
@JsonSerializable()
|
||||||
|
|
||||||
class _SnRealmMember implements SnRealmMember {
|
class _SnRealmMember implements SnRealmMember {
|
||||||
const _SnRealmMember({required this.realmId, required this.realm, required this.accountId, required this.account, required this.role, required this.joinedAt, required this.createdAt, required this.updatedAt, required this.deletedAt});
|
const _SnRealmMember({required this.realmId, required this.realm, required this.accountId, required this.account, required this.role, required this.joinedAt, required this.createdAt, required this.updatedAt, required this.deletedAt, required this.status});
|
||||||
factory _SnRealmMember.fromJson(Map<String, dynamic> json) => _$SnRealmMemberFromJson(json);
|
factory _SnRealmMember.fromJson(Map<String, dynamic> json) => _$SnRealmMemberFromJson(json);
|
||||||
|
|
||||||
@override final String realmId;
|
@override final String realmId;
|
||||||
@@ -591,6 +604,7 @@ class _SnRealmMember implements SnRealmMember {
|
|||||||
@override final DateTime createdAt;
|
@override final DateTime createdAt;
|
||||||
@override final DateTime updatedAt;
|
@override final DateTime updatedAt;
|
||||||
@override final DateTime? deletedAt;
|
@override final DateTime? deletedAt;
|
||||||
|
@override final SnAccountStatus? status;
|
||||||
|
|
||||||
/// Create a copy of SnRealmMember
|
/// Create a copy of SnRealmMember
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@@ -605,16 +619,16 @@ Map<String, dynamic> toJson() {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnRealmMember&&(identical(other.realmId, realmId) || other.realmId == realmId)&&(identical(other.realm, realm) || other.realm == realm)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.account, account) || other.account == account)&&(identical(other.role, role) || other.role == role)&&(identical(other.joinedAt, joinedAt) || other.joinedAt == joinedAt)&&(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 _SnRealmMember&&(identical(other.realmId, realmId) || other.realmId == realmId)&&(identical(other.realm, realm) || other.realm == realm)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.account, account) || other.account == account)&&(identical(other.role, role) || other.role == role)&&(identical(other.joinedAt, joinedAt) || other.joinedAt == joinedAt)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)&&(identical(other.status, status) || other.status == status));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType,realmId,realm,accountId,account,role,joinedAt,createdAt,updatedAt,deletedAt);
|
int get hashCode => Object.hash(runtimeType,realmId,realm,accountId,account,role,joinedAt,createdAt,updatedAt,deletedAt,status);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'SnRealmMember(realmId: $realmId, realm: $realm, accountId: $accountId, account: $account, role: $role, joinedAt: $joinedAt, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
return 'SnRealmMember(realmId: $realmId, realm: $realm, accountId: $accountId, account: $account, role: $role, joinedAt: $joinedAt, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, status: $status)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -625,11 +639,11 @@ abstract mixin class _$SnRealmMemberCopyWith<$Res> implements $SnRealmMemberCopy
|
|||||||
factory _$SnRealmMemberCopyWith(_SnRealmMember value, $Res Function(_SnRealmMember) _then) = __$SnRealmMemberCopyWithImpl;
|
factory _$SnRealmMemberCopyWith(_SnRealmMember value, $Res Function(_SnRealmMember) _then) = __$SnRealmMemberCopyWithImpl;
|
||||||
@override @useResult
|
@override @useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
String realmId, SnRealm? realm, String accountId, SnAccount? account, int role, DateTime? joinedAt, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
String realmId, SnRealm? realm, String accountId, SnAccount? account, int role, DateTime? joinedAt, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, SnAccountStatus? status
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@override $SnRealmCopyWith<$Res>? get realm;@override $SnAccountCopyWith<$Res>? get account;
|
@override $SnRealmCopyWith<$Res>? get realm;@override $SnAccountCopyWith<$Res>? get account;@override $SnAccountStatusCopyWith<$Res>? get status;
|
||||||
|
|
||||||
}
|
}
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
@@ -642,7 +656,7 @@ class __$SnRealmMemberCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of SnRealmMember
|
/// Create a copy of SnRealmMember
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@override @pragma('vm:prefer-inline') $Res call({Object? realmId = null,Object? realm = freezed,Object? accountId = null,Object? account = freezed,Object? role = null,Object? joinedAt = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
@override @pragma('vm:prefer-inline') $Res call({Object? realmId = null,Object? realm = freezed,Object? accountId = null,Object? account = freezed,Object? role = null,Object? joinedAt = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,Object? status = freezed,}) {
|
||||||
return _then(_SnRealmMember(
|
return _then(_SnRealmMember(
|
||||||
realmId: null == realmId ? _self.realmId : realmId // ignore: cast_nullable_to_non_nullable
|
realmId: null == realmId ? _self.realmId : realmId // ignore: cast_nullable_to_non_nullable
|
||||||
as String,realm: freezed == realm ? _self.realm : realm // ignore: cast_nullable_to_non_nullable
|
as String,realm: freezed == realm ? _self.realm : realm // ignore: cast_nullable_to_non_nullable
|
||||||
@@ -653,7 +667,8 @@ as int,joinedAt: freezed == joinedAt ? _self.joinedAt : joinedAt // ignore: cast
|
|||||||
as DateTime?,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
as DateTime?,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,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,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime?,
|
as DateTime?,status: freezed == status ? _self.status : status // ignore: cast_nullable_to_non_nullable
|
||||||
|
as SnAccountStatus?,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -681,6 +696,18 @@ $SnAccountCopyWith<$Res>? get account {
|
|||||||
return $SnAccountCopyWith<$Res>(_self.account!, (value) {
|
return $SnAccountCopyWith<$Res>(_self.account!, (value) {
|
||||||
return _then(_self.copyWith(account: value));
|
return _then(_self.copyWith(account: value));
|
||||||
});
|
});
|
||||||
|
}/// Create a copy of SnRealmMember
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$SnAccountStatusCopyWith<$Res>? get status {
|
||||||
|
if (_self.status == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $SnAccountStatusCopyWith<$Res>(_self.status!, (value) {
|
||||||
|
return _then(_self.copyWith(status: value));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -75,6 +75,12 @@ _SnRealmMember _$SnRealmMemberFromJson(Map<String, dynamic> json) =>
|
|||||||
json['deleted_at'] == null
|
json['deleted_at'] == null
|
||||||
? null
|
? null
|
||||||
: DateTime.parse(json['deleted_at'] as String),
|
: DateTime.parse(json['deleted_at'] as String),
|
||||||
|
status:
|
||||||
|
json['status'] == null
|
||||||
|
? null
|
||||||
|
: SnAccountStatus.fromJson(
|
||||||
|
json['status'] as Map<String, dynamic>,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
Map<String, dynamic> _$SnRealmMemberToJson(_SnRealmMember instance) =>
|
Map<String, dynamic> _$SnRealmMemberToJson(_SnRealmMember instance) =>
|
||||||
@@ -88,4 +94,5 @@ Map<String, dynamic> _$SnRealmMemberToJson(_SnRealmMember instance) =>
|
|||||||
'created_at': instance.createdAt.toIso8601String(),
|
'created_at': instance.createdAt.toIso8601String(),
|
||||||
'updated_at': instance.updatedAt.toIso8601String(),
|
'updated_at': instance.updatedAt.toIso8601String(),
|
||||||
'deleted_at': instance.deletedAt?.toIso8601String(),
|
'deleted_at': instance.deletedAt?.toIso8601String(),
|
||||||
|
'status': instance.status?.toJson(),
|
||||||
};
|
};
|
||||||
|
@@ -23,6 +23,8 @@ const kAppSoundEffects = 'app_sound_effects';
|
|||||||
const kAppAprilFoolFeatures = 'app_april_fool_features';
|
const kAppAprilFoolFeatures = 'app_april_fool_features';
|
||||||
const kAppWindowSize = 'app_window_size';
|
const kAppWindowSize = 'app_window_size';
|
||||||
const kAppEnterToSend = 'app_enter_to_send';
|
const kAppEnterToSend = 'app_enter_to_send';
|
||||||
|
const kFeaturedPostsCollapsedId =
|
||||||
|
'featured_posts_collapsed_id'; // Key for storing the ID of the collapsed featured post
|
||||||
|
|
||||||
const Map<String, FilterQuality> kImageQualityLevel = {
|
const Map<String, FilterQuality> kImageQualityLevel = {
|
||||||
'settingsImageQualityLowest': FilterQuality.none,
|
'settingsImageQualityLowest': FilterQuality.none,
|
||||||
|
@@ -1,6 +1,11 @@
|
|||||||
|
import 'dart:convert';
|
||||||
import 'dart:developer';
|
import 'dart:developer';
|
||||||
|
|
||||||
|
import 'package:dio/dio.dart';
|
||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:firebase_analytics/firebase_analytics.dart';
|
import 'package:firebase_analytics/firebase_analytics.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:flutter_platform_alert/flutter_platform_alert.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:island/models/account.dart';
|
import 'package:island/models/account.dart';
|
||||||
@@ -13,6 +18,11 @@ class UserInfoNotifier extends StateNotifier<AsyncValue<SnAccount?>> {
|
|||||||
UserInfoNotifier(this._ref) : super(const AsyncValue.data(null));
|
UserInfoNotifier(this._ref) : super(const AsyncValue.data(null));
|
||||||
|
|
||||||
Future<void> fetchUser() async {
|
Future<void> fetchUser() async {
|
||||||
|
final token = _ref.watch(tokenProvider);
|
||||||
|
if (token == null) {
|
||||||
|
log('[UserInfo] No token found, not going to fetch...');
|
||||||
|
return;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
final client = _ref.read(apiClientProvider);
|
final client = _ref.read(apiClientProvider);
|
||||||
final response = await client.get('/id/accounts/me');
|
final response = await client.get('/id/accounts/me');
|
||||||
@@ -20,6 +30,44 @@ class UserInfoNotifier extends StateNotifier<AsyncValue<SnAccount?>> {
|
|||||||
state = AsyncValue.data(user);
|
state = AsyncValue.data(user);
|
||||||
FirebaseAnalytics.instance.setUserId(id: user.id);
|
FirebaseAnalytics.instance.setUserId(id: user.id);
|
||||||
} catch (error, stackTrace) {
|
} catch (error, stackTrace) {
|
||||||
|
if (!kIsWeb) {
|
||||||
|
if (error is DioException) {
|
||||||
|
FlutterPlatformAlert.showCustomAlert(
|
||||||
|
windowTitle: 'failedToLoadUserInfo'.tr(),
|
||||||
|
text: [
|
||||||
|
(error.response?.statusCode == 401
|
||||||
|
? 'failedToLoadUserInfoUnauthorized'
|
||||||
|
: 'failedToLoadUserInfoNetwork')
|
||||||
|
.tr()
|
||||||
|
.trim(),
|
||||||
|
'${error.response!.statusCode}\n${error.response?.headers}',
|
||||||
|
jsonEncode(error.response?.data),
|
||||||
|
].join('\n\n'),
|
||||||
|
iconStyle: IconStyle.error,
|
||||||
|
neutralButtonTitle: 'retry'.tr(),
|
||||||
|
negativeButtonTitle: 'okay'.tr(),
|
||||||
|
).then((value) {
|
||||||
|
if (value == CustomButton.neutralButton) {
|
||||||
|
fetchUser();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
FlutterPlatformAlert.showCustomAlert(
|
||||||
|
windowTitle: 'failedToLoadUserInfo'.tr(),
|
||||||
|
text:
|
||||||
|
[
|
||||||
|
'failedToLoadUserInfoNetwork'.tr(),
|
||||||
|
error.toString(),
|
||||||
|
].join('\n\n').trim(),
|
||||||
|
iconStyle: IconStyle.error,
|
||||||
|
neutralButtonTitle: 'retry'.tr(),
|
||||||
|
negativeButtonTitle: 'okay'.tr(),
|
||||||
|
).then((value) {
|
||||||
|
if (value == CustomButton.neutralButton) {
|
||||||
|
fetchUser();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
log(
|
log(
|
||||||
"[UserInfo] Failed to fetch user info...",
|
"[UserInfo] Failed to fetch user info...",
|
||||||
name: 'UserInfoNotifier',
|
name: 'UserInfoNotifier',
|
||||||
|
@@ -1,6 +1,8 @@
|
|||||||
|
import 'dart:io' show Platform;
|
||||||
|
import 'package:animations/animations.dart';
|
||||||
import 'package:firebase_analytics/firebase_analytics.dart';
|
import 'package:firebase_analytics/firebase_analytics.dart';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/foundation.dart' show kIsWeb;
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:island/screens/about.dart';
|
import 'package:island/screens/about.dart';
|
||||||
@@ -9,6 +11,7 @@ import 'package:island/screens/developers/edit_app.dart';
|
|||||||
import 'package:island/screens/developers/new_app.dart';
|
import 'package:island/screens/developers/new_app.dart';
|
||||||
import 'package:island/screens/developers/hub.dart';
|
import 'package:island/screens/developers/hub.dart';
|
||||||
import 'package:island/screens/discovery/articles.dart';
|
import 'package:island/screens/discovery/articles.dart';
|
||||||
|
import 'package:island/screens/posts/post_categories_list.dart';
|
||||||
import 'package:island/screens/posts/post_category_detail.dart';
|
import 'package:island/screens/posts/post_category_detail.dart';
|
||||||
import 'package:island/screens/posts/post_search.dart';
|
import 'package:island/screens/posts/post_search.dart';
|
||||||
import 'package:island/widgets/app_wrapper.dart';
|
import 'package:island/widgets/app_wrapper.dart';
|
||||||
@@ -20,9 +23,9 @@ import 'package:island/screens/notification.dart';
|
|||||||
import 'package:island/screens/wallet.dart';
|
import 'package:island/screens/wallet.dart';
|
||||||
import 'package:island/screens/account/relationship.dart';
|
import 'package:island/screens/account/relationship.dart';
|
||||||
import 'package:island/screens/account/profile.dart';
|
import 'package:island/screens/account/profile.dart';
|
||||||
import 'package:island/screens/account/me/update.dart';
|
import 'package:island/screens/account/me/profile_update.dart';
|
||||||
import 'package:island/screens/account/leveling.dart';
|
import 'package:island/screens/account/leveling.dart';
|
||||||
import 'package:island/screens/account/me/settings.dart';
|
import 'package:island/screens/account/me/account_settings.dart';
|
||||||
import 'package:island/screens/chat/chat.dart';
|
import 'package:island/screens/chat/chat.dart';
|
||||||
import 'package:island/screens/chat/room.dart';
|
import 'package:island/screens/chat/room.dart';
|
||||||
import 'package:island/screens/chat/room_detail.dart';
|
import 'package:island/screens/chat/room_detail.dart';
|
||||||
@@ -50,19 +53,42 @@ import 'package:island/screens/account/event_calendar.dart';
|
|||||||
import 'package:island/screens/discovery/realms.dart';
|
import 'package:island/screens/discovery/realms.dart';
|
||||||
import 'package:island/screens/reports/report_detail.dart';
|
import 'package:island/screens/reports/report_detail.dart';
|
||||||
import 'package:island/screens/reports/report_list.dart';
|
import 'package:island/screens/reports/report_list.dart';
|
||||||
|
import 'package:island/widgets/post/post_shuffle.dart';
|
||||||
|
|
||||||
// Shell route keys for nested navigation
|
// Shell route keys for nested navigation
|
||||||
final rootNavigatorKey = GlobalKey<NavigatorState>();
|
final rootNavigatorKey = GlobalKey<NavigatorState>();
|
||||||
final _shellNavigatorKey = GlobalKey<NavigatorState>();
|
final _shellNavigatorKey = GlobalKey<NavigatorState>();
|
||||||
final _tabsShellKey = GlobalKey<NavigatorState>();
|
final _tabsShellKey = GlobalKey<NavigatorState>();
|
||||||
|
|
||||||
|
Widget _tabPagesTransitionBuilder(
|
||||||
|
BuildContext context,
|
||||||
|
Animation<double> animation,
|
||||||
|
Animation<double> secondaryAnimation,
|
||||||
|
Widget child,
|
||||||
|
) {
|
||||||
|
return FadeThroughTransition(
|
||||||
|
animation: animation,
|
||||||
|
secondaryAnimation: secondaryAnimation,
|
||||||
|
fillColor: Theme.of(context).colorScheme.surface,
|
||||||
|
child: child,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool get _supportsAnalytics =>
|
||||||
|
kIsWeb ||
|
||||||
|
Platform.isAndroid ||
|
||||||
|
Platform.isIOS ||
|
||||||
|
Platform.isMacOS ||
|
||||||
|
Platform.isWindows;
|
||||||
|
|
||||||
// Provider for the router
|
// Provider for the router
|
||||||
final routerProvider = Provider<GoRouter>((ref) {
|
final routerProvider = Provider<GoRouter>((ref) {
|
||||||
return GoRouter(
|
return GoRouter(
|
||||||
navigatorKey: rootNavigatorKey,
|
navigatorKey: rootNavigatorKey,
|
||||||
initialLocation: '/',
|
initialLocation: '/',
|
||||||
observers: [
|
observers: [
|
||||||
FirebaseAnalyticsObserver(analytics: FirebaseAnalytics.instance),
|
if (_supportsAnalytics)
|
||||||
|
FirebaseAnalyticsObserver(analytics: FirebaseAnalytics.instance),
|
||||||
],
|
],
|
||||||
routes: [
|
routes: [
|
||||||
ShellRoute(
|
ShellRoute(
|
||||||
@@ -339,7 +365,12 @@ final routerProvider = Provider<GoRouter>((ref) {
|
|||||||
GoRoute(
|
GoRoute(
|
||||||
name: 'explore',
|
name: 'explore',
|
||||||
path: '/',
|
path: '/',
|
||||||
builder: (context, state) => const ExploreScreen(),
|
pageBuilder:
|
||||||
|
(context, state) => CustomTransitionPage(
|
||||||
|
key: const ValueKey('explore'),
|
||||||
|
child: const ExploreScreen(),
|
||||||
|
transitionsBuilder: _tabPagesTransitionBuilder,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
GoRoute(
|
GoRoute(
|
||||||
name: 'postSearch',
|
name: 'postSearch',
|
||||||
@@ -347,12 +378,14 @@ final routerProvider = Provider<GoRouter>((ref) {
|
|||||||
builder: (context, state) => const PostSearchScreen(),
|
builder: (context, state) => const PostSearchScreen(),
|
||||||
),
|
),
|
||||||
GoRoute(
|
GoRoute(
|
||||||
name: 'postDetail',
|
name: 'postShuffle',
|
||||||
path: '/posts/:id',
|
path: '/posts/shuffle',
|
||||||
builder: (context, state) {
|
builder: (context, state) => const PostShuffleScreen(),
|
||||||
final id = state.pathParameters['id']!;
|
),
|
||||||
return PostDetailScreen(id: id);
|
GoRoute(
|
||||||
},
|
name: 'postCategories',
|
||||||
|
path: '/posts/categories',
|
||||||
|
builder: (context, state) => const PostCategoriesListScreen(),
|
||||||
),
|
),
|
||||||
GoRoute(
|
GoRoute(
|
||||||
name: 'postCategoryDetail',
|
name: 'postCategoryDetail',
|
||||||
@@ -362,6 +395,11 @@ final routerProvider = Provider<GoRouter>((ref) {
|
|||||||
return PostCategoryDetailScreen(slug: slug, isCategory: true);
|
return PostCategoryDetailScreen(slug: slug, isCategory: true);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
GoRoute(
|
||||||
|
name: 'postTags',
|
||||||
|
path: '/posts/tags',
|
||||||
|
builder: (context, state) => const PostTagsListScreen(),
|
||||||
|
),
|
||||||
GoRoute(
|
GoRoute(
|
||||||
name: 'postTagDetail',
|
name: 'postTagDetail',
|
||||||
path: '/posts/tags/:slug',
|
path: '/posts/tags/:slug',
|
||||||
@@ -373,6 +411,14 @@ final routerProvider = Provider<GoRouter>((ref) {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
GoRoute(
|
||||||
|
name: 'postDetail',
|
||||||
|
path: '/posts/:id',
|
||||||
|
builder: (context, state) {
|
||||||
|
final id = state.pathParameters['id']!;
|
||||||
|
return PostDetailScreen(id: id);
|
||||||
|
},
|
||||||
|
),
|
||||||
GoRoute(
|
GoRoute(
|
||||||
name: 'publisherProfile',
|
name: 'publisherProfile',
|
||||||
path: '/publishers/:name',
|
path: '/publishers/:name',
|
||||||
@@ -389,8 +435,12 @@ final routerProvider = Provider<GoRouter>((ref) {
|
|||||||
|
|
||||||
// Chat tab
|
// Chat tab
|
||||||
ShellRoute(
|
ShellRoute(
|
||||||
builder:
|
pageBuilder:
|
||||||
(context, state, child) => ChatShellScreen(child: child),
|
(context, state, child) => CustomTransitionPage(
|
||||||
|
key: const ValueKey('chat'),
|
||||||
|
child: ChatShellScreen(child: child),
|
||||||
|
transitionsBuilder: _tabPagesTransitionBuilder,
|
||||||
|
),
|
||||||
routes: [
|
routes: [
|
||||||
GoRoute(
|
GoRoute(
|
||||||
name: 'chatList',
|
name: 'chatList',
|
||||||
@@ -433,7 +483,12 @@ final routerProvider = Provider<GoRouter>((ref) {
|
|||||||
GoRoute(
|
GoRoute(
|
||||||
name: 'realmList',
|
name: 'realmList',
|
||||||
path: '/realms',
|
path: '/realms',
|
||||||
builder: (context, state) => const RealmListScreen(),
|
pageBuilder:
|
||||||
|
(context, state) => CustomTransitionPage(
|
||||||
|
key: const ValueKey('realms'),
|
||||||
|
child: const RealmListScreen(),
|
||||||
|
transitionsBuilder: _tabPagesTransitionBuilder,
|
||||||
|
),
|
||||||
routes: [
|
routes: [
|
||||||
GoRoute(
|
GoRoute(
|
||||||
name: 'realmNew',
|
name: 'realmNew',
|
||||||
@@ -461,8 +516,12 @@ final routerProvider = Provider<GoRouter>((ref) {
|
|||||||
|
|
||||||
// Account tab
|
// Account tab
|
||||||
ShellRoute(
|
ShellRoute(
|
||||||
builder:
|
pageBuilder:
|
||||||
(context, state, child) => AccountShellScreen(child: child),
|
(context, state, child) => CustomTransitionPage(
|
||||||
|
key: const ValueKey('account'),
|
||||||
|
child: AccountShellScreen(child: child),
|
||||||
|
transitionsBuilder: _tabPagesTransitionBuilder,
|
||||||
|
),
|
||||||
routes: [
|
routes: [
|
||||||
GoRoute(
|
GoRoute(
|
||||||
name: 'account',
|
name: 'account',
|
||||||
|
@@ -178,7 +178,8 @@ class _AboutScreenState extends ConsumerState<AboutScreen> {
|
|||||||
context,
|
context,
|
||||||
icon: Symbols.label,
|
icon: Symbols.label,
|
||||||
label: 'aboutDeviceName'.tr(),
|
label: 'aboutDeviceName'.tr(),
|
||||||
value: _deviceInfo?.data['name'],
|
value:
|
||||||
|
_deviceInfo?.data['name'] ?? 'unknown'.tr(),
|
||||||
),
|
),
|
||||||
_buildInfoItem(
|
_buildInfoItem(
|
||||||
context,
|
context,
|
||||||
|
@@ -6,6 +6,7 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:gap/gap.dart';
|
import 'package:gap/gap.dart';
|
||||||
import 'package:google_fonts/google_fonts.dart';
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:island/models/account.dart';
|
||||||
import 'package:island/models/wallet.dart';
|
import 'package:island/models/wallet.dart';
|
||||||
import 'package:island/pods/network.dart';
|
import 'package:island/pods/network.dart';
|
||||||
import 'package:island/pods/userinfo.dart';
|
import 'package:island/pods/userinfo.dart';
|
||||||
@@ -19,6 +20,7 @@ import 'package:island/widgets/payment/payment_overlay.dart';
|
|||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:material_symbols_icons/symbols.dart';
|
import 'package:material_symbols_icons/symbols.dart';
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
|
import 'package:riverpod_paging_utils/riverpod_paging_utils.dart';
|
||||||
import 'package:styled_widget/styled_widget.dart';
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
|
|
||||||
part 'leveling.g.dart';
|
part 'leveling.g.dart';
|
||||||
@@ -35,13 +37,49 @@ Future<SnWalletSubscription?> accountStellarSubscription(Ref ref) async {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@riverpod
|
||||||
|
class LevelingHistoryNotifier extends _$LevelingHistoryNotifier
|
||||||
|
with CursorPagingNotifierMixin<SnExperienceRecord> {
|
||||||
|
static const int _pageSize = 20;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<CursorPagingData<SnExperienceRecord>> build() => fetch(cursor: null);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<CursorPagingData<SnExperienceRecord>> 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(
|
||||||
|
'/id/accounts/me/leveling',
|
||||||
|
queryParameters: queryParams,
|
||||||
|
);
|
||||||
|
final total = int.parse(response.headers.value('X-Total') ?? '0');
|
||||||
|
final List<dynamic> data = response.data;
|
||||||
|
final records =
|
||||||
|
data.map((json) => SnExperienceRecord.fromJson(json)).toList();
|
||||||
|
|
||||||
|
final hasMore = offset + records.length < total;
|
||||||
|
final nextCursor = hasMore ? (offset + records.length).toString() : null;
|
||||||
|
|
||||||
|
return CursorPagingData(
|
||||||
|
items: records,
|
||||||
|
hasMore: hasMore,
|
||||||
|
nextCursor: nextCursor,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class LevelingScreen extends HookConsumerWidget {
|
class LevelingScreen extends HookConsumerWidget {
|
||||||
const LevelingScreen({super.key});
|
const LevelingScreen({super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final user = ref.watch(userInfoProvider);
|
final user = ref.watch(userInfoProvider);
|
||||||
final stellarSubscription = ref.watch(accountStellarSubscriptionProvider);
|
|
||||||
|
|
||||||
if (user.value == null) {
|
if (user.value == null) {
|
||||||
return AppScaffold(
|
return AppScaffold(
|
||||||
@@ -50,47 +88,150 @@ class LevelingScreen extends HookConsumerWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
final currentLevel = user.value!.profile.level;
|
return DefaultTabController(
|
||||||
final currentExp = user.value!.profile.experience;
|
length: 2,
|
||||||
final progress = user.value!.profile.levelingProgress;
|
child: AppScaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: Text('levelingProgress'.tr()),
|
||||||
|
bottom: TabBar(
|
||||||
|
tabs: [
|
||||||
|
Tab(text: 'leveling'.tr()),
|
||||||
|
Tab(text: 'stellarProgram'.tr()),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
body: TabBarView(
|
||||||
|
children: [
|
||||||
|
_buildLevelingTab(context, ref, user.value!),
|
||||||
|
_buildStellarProgramTab(context, ref),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return AppScaffold(
|
Widget _buildLevelingTab(
|
||||||
appBar: AppBar(title: Text('levelingProgress'.tr())),
|
BuildContext context,
|
||||||
body: SingleChildScrollView(
|
WidgetRef ref,
|
||||||
padding: getTabbedPadding(context, horizontal: 20, vertical: 20),
|
SnAccount user,
|
||||||
child: Center(
|
) {
|
||||||
child: ConstrainedBox(
|
final currentLevel = user.profile.level;
|
||||||
constraints: const BoxConstraints(maxWidth: 480),
|
final currentExp = user.profile.experience;
|
||||||
child: Column(
|
final progress = user.profile.levelingProgress;
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
|
||||||
children: [
|
|
||||||
// Current Progress Card
|
|
||||||
LevelingProgressCard(
|
|
||||||
level: currentLevel,
|
|
||||||
experience: currentExp,
|
|
||||||
progress: progress,
|
|
||||||
),
|
|
||||||
const Gap(24),
|
|
||||||
|
|
||||||
// Level Stairs Graph
|
return Center(
|
||||||
Text(
|
child: Container(
|
||||||
'levelProgress'.tr(),
|
padding: const EdgeInsets.symmetric(horizontal: 20),
|
||||||
style: Theme.of(context).textTheme.headlineSmall?.copyWith(
|
constraints: const BoxConstraints(maxWidth: 480),
|
||||||
fontWeight: FontWeight.bold,
|
child: CustomScrollView(
|
||||||
),
|
slivers: [
|
||||||
),
|
const SliverGap(20),
|
||||||
const Gap(16),
|
|
||||||
|
|
||||||
// Stairs visualization with fixed height and horizontal scroll
|
// Current Progress Card
|
||||||
_buildLevelStairs(context, currentLevel),
|
SliverToBoxAdapter(
|
||||||
|
child: LevelingProgressCard(
|
||||||
const Gap(24),
|
level: currentLevel,
|
||||||
|
experience: currentExp,
|
||||||
// Membership section
|
progress: progress,
|
||||||
_buildMembershipSection(context, ref, stellarSubscription),
|
),
|
||||||
const Gap(16),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
|
const SliverGap(24),
|
||||||
|
|
||||||
|
// Level Stairs Graph
|
||||||
|
SliverToBoxAdapter(
|
||||||
|
child: Text(
|
||||||
|
'levelProgress'.tr(),
|
||||||
|
style: Theme.of(context).textTheme.headlineSmall?.copyWith(
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SliverGap(16),
|
||||||
|
|
||||||
|
// Stairs visualization with fixed height and horizontal scroll
|
||||||
|
SliverToBoxAdapter(child: _buildLevelStairs(context, currentLevel)),
|
||||||
|
const SliverGap(24),
|
||||||
|
|
||||||
|
// Leveling History
|
||||||
|
SliverToBoxAdapter(
|
||||||
|
child: Text(
|
||||||
|
'levelingHistory'.tr(),
|
||||||
|
style: Theme.of(context).textTheme.headlineSmall?.copyWith(
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SliverGap(8),
|
||||||
|
PagingHelperSliverView(
|
||||||
|
provider: levelingHistoryNotifierProvider,
|
||||||
|
futureRefreshable: levelingHistoryNotifierProvider.future,
|
||||||
|
notifierRefreshable: levelingHistoryNotifierProvider.notifier,
|
||||||
|
contentBuilder:
|
||||||
|
(data, widgetCount, endItemView) => SliverList.builder(
|
||||||
|
itemCount: widgetCount,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
if (index == widgetCount - 1) {
|
||||||
|
return endItemView;
|
||||||
|
}
|
||||||
|
final record = data.items[index];
|
||||||
|
return ListTile(
|
||||||
|
title: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: [
|
||||||
|
Text(record.reason),
|
||||||
|
Row(
|
||||||
|
spacing: 4,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
record.createdAt.formatRelative(context),
|
||||||
|
).fontSize(13),
|
||||||
|
Text('·').fontSize(13).bold(),
|
||||||
|
Text(
|
||||||
|
record.createdAt.formatSystem(),
|
||||||
|
).fontSize(13),
|
||||||
|
],
|
||||||
|
).opacity(0.8),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
subtitle: Row(
|
||||||
|
spacing: 8,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
'${record.delta > 0 ? '+' : ''}${record.delta} EXP',
|
||||||
|
),
|
||||||
|
if (record.bonusMultiplier != 1.0)
|
||||||
|
Text('x${record.bonusMultiplier}'),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
minTileHeight: 56,
|
||||||
|
contentPadding: EdgeInsets.symmetric(horizontal: 4),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
SliverGap(getTabbedPadding(context, vertical: 20).vertical),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildStellarProgramTab(BuildContext context, WidgetRef ref) {
|
||||||
|
final stellarSubscription = ref.watch(accountStellarSubscriptionProvider);
|
||||||
|
|
||||||
|
return SingleChildScrollView(
|
||||||
|
padding: getTabbedPadding(context, horizontal: 20, vertical: 20),
|
||||||
|
child: Center(
|
||||||
|
child: ConstrainedBox(
|
||||||
|
constraints: const BoxConstraints(maxWidth: 480),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: [
|
||||||
|
_buildMembershipSection(context, ref, stellarSubscription),
|
||||||
|
const Gap(16),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@@ -27,5 +27,26 @@ final accountStellarSubscriptionProvider =
|
|||||||
// ignore: unused_element
|
// ignore: unused_element
|
||||||
typedef AccountStellarSubscriptionRef =
|
typedef AccountStellarSubscriptionRef =
|
||||||
AutoDisposeFutureProviderRef<SnWalletSubscription?>;
|
AutoDisposeFutureProviderRef<SnWalletSubscription?>;
|
||||||
|
String _$levelingHistoryNotifierHash() =>
|
||||||
|
r'e795f9b7911c9e50f15c095ea237cb0e87bf1e89';
|
||||||
|
|
||||||
|
/// See also [LevelingHistoryNotifier].
|
||||||
|
@ProviderFor(LevelingHistoryNotifier)
|
||||||
|
final levelingHistoryNotifierProvider = AutoDisposeAsyncNotifierProvider<
|
||||||
|
LevelingHistoryNotifier,
|
||||||
|
CursorPagingData<SnExperienceRecord>
|
||||||
|
>.internal(
|
||||||
|
LevelingHistoryNotifier.new,
|
||||||
|
name: r'levelingHistoryNotifierProvider',
|
||||||
|
debugGetCreateSourceHash:
|
||||||
|
const bool.fromEnvironment('dart.vm.product')
|
||||||
|
? null
|
||||||
|
: _$levelingHistoryNotifierHash,
|
||||||
|
dependencies: null,
|
||||||
|
allTransitiveDependencies: null,
|
||||||
|
);
|
||||||
|
|
||||||
|
typedef _$LevelingHistoryNotifier =
|
||||||
|
AutoDisposeAsyncNotifier<CursorPagingData<SnExperienceRecord>>;
|
||||||
// ignore_for_file: type=lint
|
// 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
|
// 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
|
||||||
|
@@ -23,7 +23,7 @@ import 'package:material_symbols_icons/symbols.dart';
|
|||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
import 'package:styled_widget/styled_widget.dart';
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
|
|
||||||
part 'settings.g.dart';
|
part 'account_settings.g.dart';
|
||||||
|
|
||||||
@riverpod
|
@riverpod
|
||||||
Future<List<SnAuthFactor>> authFactors(Ref ref) async {
|
Future<List<SnAuthFactor>> authFactors(Ref ref) async {
|
@@ -1,6 +1,6 @@
|
|||||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
part of 'settings.dart';
|
part of 'account_settings.dart';
|
||||||
|
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
// RiverpodGenerator
|
// RiverpodGenerator
|
@@ -1,3 +1,4 @@
|
|||||||
|
import 'package:collection/collection.dart';
|
||||||
import 'package:croppy/croppy.dart' hide cropImage;
|
import 'package:croppy/croppy.dart' hide cropImage;
|
||||||
import 'package:dropdown_button2/dropdown_button2.dart';
|
import 'package:dropdown_button2/dropdown_button2.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
@@ -168,11 +169,18 @@ class UpdateProfileScreen extends HookConsumerWidget {
|
|||||||
'location': locationController.text,
|
'location': locationController.text,
|
||||||
'time_zone': timeZoneController.text,
|
'time_zone': timeZoneController.text,
|
||||||
'birthday': birthday.value?.toUtc().toIso8601String(),
|
'birthday': birthday.value?.toUtc().toIso8601String(),
|
||||||
'links': links.value,
|
'links':
|
||||||
|
links.value
|
||||||
|
.where((e) => e.name.isNotEmpty && e.url.isNotEmpty)
|
||||||
|
.toList(),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
final userNotifier = ref.read(userInfoProvider.notifier);
|
final userNotifier = ref.read(userInfoProvider.notifier);
|
||||||
userNotifier.fetchUser();
|
userNotifier.fetchUser();
|
||||||
|
links.value =
|
||||||
|
links.value
|
||||||
|
.where((e) => e.name.isNotEmpty && e.url.isNotEmpty)
|
||||||
|
.toList();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
showErrorAlert(err);
|
showErrorAlert(err);
|
||||||
} finally {
|
} finally {
|
||||||
@@ -568,6 +576,7 @@ class UpdateProfileScreen extends HookConsumerWidget {
|
|||||||
children: [
|
children: [
|
||||||
for (var i = 0; i < links.value.length; i++)
|
for (var i = 0; i < links.value.length; i++)
|
||||||
Row(
|
Row(
|
||||||
|
key: ValueKey(links.value[i].hashCode),
|
||||||
crossAxisAlignment: CrossAxisAlignment.end,
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
@@ -610,8 +619,10 @@ class UpdateProfileScreen extends HookConsumerWidget {
|
|||||||
IconButton(
|
IconButton(
|
||||||
icon: const Icon(Symbols.delete),
|
icon: const Icon(Symbols.delete),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
links.value = List.from(links.value)
|
links.value =
|
||||||
..removeAt(i);
|
links.value
|
||||||
|
.whereIndexed((idx, _) => idx != i)
|
||||||
|
.toList();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
@@ -6,7 +6,7 @@ import 'package:gap/gap.dart';
|
|||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:island/models/auth.dart';
|
import 'package:island/models/auth.dart';
|
||||||
import 'package:island/pods/network.dart';
|
import 'package:island/pods/network.dart';
|
||||||
import 'package:island/screens/account/me/settings.dart';
|
import 'package:island/screens/account/me/account_settings.dart';
|
||||||
import 'package:island/screens/auth/oidc.native.dart';
|
import 'package:island/screens/auth/oidc.native.dart';
|
||||||
import 'package:island/services/text.dart';
|
import 'package:island/services/text.dart';
|
||||||
import 'package:island/services/time.dart';
|
import 'package:island/services/time.dart';
|
||||||
|
@@ -6,7 +6,7 @@ import 'package:flutter_hooks/flutter_hooks.dart';
|
|||||||
import 'package:gap/gap.dart';
|
import 'package:gap/gap.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:island/pods/network.dart';
|
import 'package:island/pods/network.dart';
|
||||||
import 'package:island/screens/account/me/update.dart';
|
import 'package:island/screens/account/me/profile_update.dart';
|
||||||
import 'package:island/widgets/alert.dart';
|
import 'package:island/widgets/alert.dart';
|
||||||
import 'package:island/widgets/app_scaffold.dart';
|
import 'package:island/widgets/app_scaffold.dart';
|
||||||
import 'package:material_symbols_icons/symbols.dart';
|
import 'package:material_symbols_icons/symbols.dart';
|
||||||
|
@@ -23,7 +23,7 @@ import 'package:island/widgets/alert.dart';
|
|||||||
import 'package:island/widgets/app_scaffold.dart';
|
import 'package:island/widgets/app_scaffold.dart';
|
||||||
import 'package:island/widgets/content/cloud_files.dart';
|
import 'package:island/widgets/content/cloud_files.dart';
|
||||||
import 'package:island/widgets/content/sheet.dart';
|
import 'package:island/widgets/content/sheet.dart';
|
||||||
import 'package:island/widgets/realms/selection_dropdown.dart';
|
import 'package:island/widgets/realm/realm_selection_dropdown.dart';
|
||||||
import 'package:island/widgets/response.dart';
|
import 'package:island/widgets/response.dart';
|
||||||
import 'package:island/screens/tabs.dart';
|
import 'package:island/screens/tabs.dart';
|
||||||
import 'package:material_symbols_icons/symbols.dart';
|
import 'package:material_symbols_icons/symbols.dart';
|
||||||
@@ -80,10 +80,12 @@ class ChatRoomListTile extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
Row(
|
Row(
|
||||||
|
spacing: 4,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Badge(
|
||||||
'${data.lastMessage.sender.account.name}: ',
|
label: Text(data.lastMessage.sender.account.nick),
|
||||||
style: Theme.of(context).textTheme.bodySmall,
|
textColor: Theme.of(context).colorScheme.onPrimary,
|
||||||
|
backgroundColor: Theme.of(context).colorScheme.primary,
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Text(
|
child: Text(
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -6,7 +6,7 @@ part of 'room.dart';
|
|||||||
// RiverpodGenerator
|
// RiverpodGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
String _$messagesNotifierHash() => r'afc4d43f4948ec571118cef0321838a6cefc89c0';
|
String _$messagesNotifierHash() => r'32afe6ea24086d869cc47bd3389c8fd734409ca0';
|
||||||
|
|
||||||
/// Copied from Dart SDK
|
/// Copied from Dart SDK
|
||||||
class _SystemHash {
|
class _SystemHash {
|
||||||
|
@@ -10,6 +10,7 @@ import 'package:island/models/chat.dart';
|
|||||||
import 'package:island/pods/network.dart';
|
import 'package:island/pods/network.dart';
|
||||||
import 'package:island/screens/chat/chat.dart';
|
import 'package:island/screens/chat/chat.dart';
|
||||||
import 'package:island/widgets/account/account_picker.dart';
|
import 'package:island/widgets/account/account_picker.dart';
|
||||||
|
import 'package:island/widgets/account/status.dart';
|
||||||
import 'package:island/widgets/alert.dart';
|
import 'package:island/widgets/alert.dart';
|
||||||
import 'package:island/widgets/app_scaffold.dart';
|
import 'package:island/widgets/app_scaffold.dart';
|
||||||
import 'package:island/widgets/content/cloud_files.dart';
|
import 'package:island/widgets/content/cloud_files.dart';
|
||||||
@@ -544,7 +545,7 @@ class ChatMemberListNotifier extends _$ChatMemberListNotifier
|
|||||||
final apiClient = ref.watch(apiClientProvider);
|
final apiClient = ref.watch(apiClientProvider);
|
||||||
final response = await apiClient.get(
|
final response = await apiClient.get(
|
||||||
'/sphere/chat/$roomId/members',
|
'/sphere/chat/$roomId/members',
|
||||||
queryParameters: {'offset': offset, 'take': take},
|
queryParameters: {'offset': offset, 'take': take, 'withStatus': true},
|
||||||
);
|
);
|
||||||
|
|
||||||
final total = int.parse(response.headers.value('X-Total') ?? '0');
|
final total = int.parse(response.headers.value('X-Total') ?? '0');
|
||||||
@@ -672,6 +673,8 @@ class _ChatMemberListSheet extends HookConsumerWidget {
|
|||||||
spacing: 6,
|
spacing: 6,
|
||||||
children: [
|
children: [
|
||||||
Flexible(child: Text(member.account.nick)),
|
Flexible(child: Text(member.account.nick)),
|
||||||
|
if (member.status != null)
|
||||||
|
AccountStatusLabel(status: member.status!),
|
||||||
if (member.joinedAt == null)
|
if (member.joinedAt == null)
|
||||||
const Icon(Symbols.pending_actions, size: 20),
|
const Icon(Symbols.pending_actions, size: 20),
|
||||||
],
|
],
|
||||||
|
@@ -7,7 +7,7 @@ part of 'room_detail.dart';
|
|||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
String _$chatMemberListNotifierHash() =>
|
String _$chatMemberListNotifierHash() =>
|
||||||
r'c8fbf4b95df6dae24b1ba21063e9a43351832974';
|
r'3ea30150278523e9f6b23f9200ea9a9fbae9c973';
|
||||||
|
|
||||||
/// Copied from Dart SDK
|
/// Copied from Dart SDK
|
||||||
class _SystemHash {
|
class _SystemHash {
|
||||||
|
@@ -212,30 +212,6 @@ class CreatorHubScreen extends HookConsumerWidget {
|
|||||||
leading: !isWide ? const PageBackButton() : null,
|
leading: !isWide ? const PageBackButton() : null,
|
||||||
title: Text('creatorHub').tr(),
|
title: Text('creatorHub').tr(),
|
||||||
actions: [
|
actions: [
|
||||||
IconButton(
|
|
||||||
icon: Badge(
|
|
||||||
label: Text(
|
|
||||||
publisherInvites.when(
|
|
||||||
data: (invites) => invites.length.toString(),
|
|
||||||
error: (_, _) => '0',
|
|
||||||
loading: () => '0',
|
|
||||||
),
|
|
||||||
),
|
|
||||||
isLabelVisible: publisherInvites.when(
|
|
||||||
data: (invites) => invites.isNotEmpty,
|
|
||||||
error: (_, _) => false,
|
|
||||||
loading: () => false,
|
|
||||||
),
|
|
||||||
child: const Icon(Symbols.email),
|
|
||||||
),
|
|
||||||
onPressed: () {
|
|
||||||
showModalBottomSheet(
|
|
||||||
context: context,
|
|
||||||
isScrollControlled: true,
|
|
||||||
builder: (_) => const _PublisherInviteSheet(),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
DropdownButtonHideUnderline(
|
DropdownButtonHideUnderline(
|
||||||
child: DropdownButton2<SnPublisher>(
|
child: DropdownButton2<SnPublisher>(
|
||||||
alignment: Alignment.centerRight,
|
alignment: Alignment.centerRight,
|
||||||
@@ -323,6 +299,23 @@ class CreatorHubScreen extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
) ??
|
) ??
|
||||||
[]),
|
[]),
|
||||||
|
ListTile(
|
||||||
|
leading: const CircleAvatar(
|
||||||
|
child: Icon(Symbols.mail),
|
||||||
|
),
|
||||||
|
title: Text('publisherCollabInvitation').tr(),
|
||||||
|
subtitle: Text(
|
||||||
|
'publisherCollabInvitationCount',
|
||||||
|
).plural(publisherInvites.value?.length ?? 0),
|
||||||
|
trailing: const Icon(Symbols.chevron_right),
|
||||||
|
onTap: () {
|
||||||
|
showModalBottomSheet(
|
||||||
|
context: context,
|
||||||
|
isScrollControlled: true,
|
||||||
|
builder: (_) => const _PublisherInviteSheet(),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
leading: const CircleAvatar(
|
leading: const CircleAvatar(
|
||||||
child: Icon(Symbols.add),
|
child: Icon(Symbols.add),
|
||||||
|
@@ -19,7 +19,7 @@ import 'package:island/services/responsive.dart';
|
|||||||
import 'package:island/widgets/alert.dart';
|
import 'package:island/widgets/alert.dart';
|
||||||
import 'package:island/widgets/app_scaffold.dart';
|
import 'package:island/widgets/app_scaffold.dart';
|
||||||
import 'package:island/widgets/content/cloud_files.dart';
|
import 'package:island/widgets/content/cloud_files.dart';
|
||||||
import 'package:island/widgets/realms/selection_dropdown.dart';
|
import 'package:island/widgets/realm/realm_selection_dropdown.dart';
|
||||||
import 'package:material_symbols_icons/symbols.dart';
|
import 'package:material_symbols_icons/symbols.dart';
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
import 'package:styled_widget/styled_widget.dart';
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
|
@@ -106,11 +106,7 @@ class StickerPacksNotifier extends _$StickerPacksNotifier
|
|||||||
try {
|
try {
|
||||||
final response = await client.get(
|
final response = await client.get(
|
||||||
'/sphere/stickers',
|
'/sphere/stickers',
|
||||||
queryParameters: {
|
queryParameters: {'offset': offset, 'take': _pageSize, 'pub': pubName},
|
||||||
'offset': offset,
|
|
||||||
'take': _pageSize,
|
|
||||||
'pubName': pubName,
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
|
|
||||||
final total = int.parse(response.headers.value('X-Total') ?? '0');
|
final total = int.parse(response.headers.value('X-Total') ?? '0');
|
||||||
|
@@ -148,7 +148,7 @@ class _StickerPackProviderElement
|
|||||||
}
|
}
|
||||||
|
|
||||||
String _$stickerPacksNotifierHash() =>
|
String _$stickerPacksNotifierHash() =>
|
||||||
r'0a8edcf9c35396c411f1214f5e77b1e8fac6a3e6';
|
r'30024b35235f3085a5b1ec2204d0a974ee907e22';
|
||||||
|
|
||||||
abstract class _$StickerPacksNotifier
|
abstract class _$StickerPacksNotifier
|
||||||
extends BuildlessAutoDisposeAsyncNotifier<CursorPagingData<SnStickerPack>> {
|
extends BuildlessAutoDisposeAsyncNotifier<CursorPagingData<SnStickerPack>> {
|
||||||
|
@@ -11,6 +11,7 @@ import 'package:island/models/realm.dart';
|
|||||||
import 'package:island/models/webfeed.dart';
|
import 'package:island/models/webfeed.dart';
|
||||||
import 'package:island/pods/event_calendar.dart';
|
import 'package:island/pods/event_calendar.dart';
|
||||||
import 'package:island/pods/userinfo.dart';
|
import 'package:island/pods/userinfo.dart';
|
||||||
|
import 'package:island/screens/notification.dart';
|
||||||
import 'package:island/services/responsive.dart';
|
import 'package:island/services/responsive.dart';
|
||||||
import 'package:island/widgets/account/fortune_graph.dart';
|
import 'package:island/widgets/account/fortune_graph.dart';
|
||||||
import 'package:island/widgets/app_scaffold.dart';
|
import 'package:island/widgets/app_scaffold.dart';
|
||||||
@@ -30,6 +31,33 @@ import 'package:styled_widget/styled_widget.dart';
|
|||||||
|
|
||||||
part 'explore.g.dart';
|
part 'explore.g.dart';
|
||||||
|
|
||||||
|
Widget notificationIndicatorWidget(
|
||||||
|
BuildContext context, {
|
||||||
|
required int count,
|
||||||
|
EdgeInsets? margin,
|
||||||
|
}) => Card(
|
||||||
|
margin: margin,
|
||||||
|
child: ListTile(
|
||||||
|
shape: const RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(8)),
|
||||||
|
),
|
||||||
|
leading: const Icon(Symbols.notifications),
|
||||||
|
title: Row(
|
||||||
|
children: [
|
||||||
|
Text('notifications').tr().fontSize(14),
|
||||||
|
const Gap(8),
|
||||||
|
Badge(label: Text(count.toString())),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
trailing: const Icon(Symbols.chevron_right),
|
||||||
|
minTileHeight: 40,
|
||||||
|
contentPadding: EdgeInsets.only(left: 16, right: 15),
|
||||||
|
onTap: () {
|
||||||
|
GoRouter.of(context).pushNamed('notifications');
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
class ExploreScreen extends HookConsumerWidget {
|
class ExploreScreen extends HookConsumerWidget {
|
||||||
const ExploreScreen({super.key});
|
const ExploreScreen({super.key});
|
||||||
|
|
||||||
@@ -77,6 +105,10 @@ class ExploreScreen extends HookConsumerWidget {
|
|||||||
|
|
||||||
final user = ref.watch(userInfoProvider);
|
final user = ref.watch(userInfoProvider);
|
||||||
|
|
||||||
|
final notificationCount = ref.watch(
|
||||||
|
notificationUnreadCountNotifierProvider,
|
||||||
|
);
|
||||||
|
|
||||||
return AppScaffold(
|
return AppScaffold(
|
||||||
isNoBackground: false,
|
isNoBackground: false,
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
@@ -141,12 +173,60 @@ class ExploreScreen extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
tooltip: 'webArticlesStand'.tr(),
|
tooltip: 'webArticlesStand'.tr(),
|
||||||
),
|
),
|
||||||
IconButton(
|
PopupMenuButton(
|
||||||
onPressed: () {
|
itemBuilder:
|
||||||
context.pushNamed('postSearch');
|
(context) => [
|
||||||
},
|
PopupMenuItem(
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
const Icon(Symbols.category),
|
||||||
|
const Gap(12),
|
||||||
|
Text('categories').tr(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
onTap: () {
|
||||||
|
context.pushNamed('postCategories');
|
||||||
|
},
|
||||||
|
),
|
||||||
|
PopupMenuItem(
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
const Icon(Symbols.label),
|
||||||
|
const Gap(12),
|
||||||
|
Text('tags').tr(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
onTap: () {
|
||||||
|
context.pushNamed('postTags');
|
||||||
|
},
|
||||||
|
),
|
||||||
|
PopupMenuItem(
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
const Icon(Symbols.shuffle),
|
||||||
|
const Gap(12),
|
||||||
|
Text('postShuffle').tr(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
onTap: () {
|
||||||
|
context.pushNamed('postShuffle');
|
||||||
|
},
|
||||||
|
),
|
||||||
|
PopupMenuItem(
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
const Icon(Symbols.search),
|
||||||
|
const Gap(12),
|
||||||
|
Text('search').tr(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
onTap: () {
|
||||||
|
context.pushNamed('postSearch');
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
icon: Icon(
|
icon: Icon(
|
||||||
Symbols.search,
|
Symbols.action_key,
|
||||||
color: Theme.of(context).appBarTheme.foregroundColor!,
|
color: Theme.of(context).appBarTheme.foregroundColor!,
|
||||||
),
|
),
|
||||||
tooltip: 'search'.tr(),
|
tooltip: 'search'.tr(),
|
||||||
@@ -185,7 +265,7 @@ class ExploreScreen extends HookConsumerWidget {
|
|||||||
floatingActionButtonLocation: TabbedFabLocation(context),
|
floatingActionButtonLocation: TabbedFabLocation(context),
|
||||||
body: Builder(
|
body: Builder(
|
||||||
builder: (context) {
|
builder: (context) {
|
||||||
final isWider = isWiderScreen(context);
|
final isWide = isWideScreen(context);
|
||||||
|
|
||||||
final bodyView = _buildActivityList(
|
final bodyView = _buildActivityList(
|
||||||
context,
|
context,
|
||||||
@@ -193,40 +273,58 @@ class ExploreScreen extends HookConsumerWidget {
|
|||||||
currentFilter.value,
|
currentFilter.value,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (isWider) {
|
if (isWide) {
|
||||||
return Row(
|
return Row(
|
||||||
children: [
|
children: [
|
||||||
Flexible(flex: 3, child: bodyView.padding(left: 8)),
|
Flexible(flex: 3, child: bodyView.padding(left: 8)),
|
||||||
if (user.value != null)
|
if (user.value != null)
|
||||||
Flexible(
|
Flexible(
|
||||||
flex: 2,
|
flex: 2,
|
||||||
child: SingleChildScrollView(
|
child: Align(
|
||||||
child: Column(
|
alignment: Alignment.topCenter,
|
||||||
children: [
|
child: SingleChildScrollView(
|
||||||
CheckInWidget(
|
child: Column(
|
||||||
margin: EdgeInsets.only(
|
children: [
|
||||||
|
CheckInWidget(
|
||||||
|
margin: EdgeInsets.only(
|
||||||
|
left: 8,
|
||||||
|
right: 12,
|
||||||
|
top: 16,
|
||||||
|
),
|
||||||
|
onChecked: () {
|
||||||
|
ref.invalidate(
|
||||||
|
eventCalendarProvider(query.value),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
if (notificationCount.value != null &&
|
||||||
|
notificationCount.value! > 0)
|
||||||
|
notificationIndicatorWidget(
|
||||||
|
context,
|
||||||
|
count: notificationCount.value ?? 0,
|
||||||
|
margin: EdgeInsets.only(
|
||||||
|
left: 8,
|
||||||
|
right: 12,
|
||||||
|
top: 8,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
PostFeaturedList().padding(
|
||||||
left: 8,
|
left: 8,
|
||||||
right: 12,
|
right: 12,
|
||||||
top: 16,
|
top: 8,
|
||||||
),
|
),
|
||||||
onChecked: () {
|
FortuneGraphWidget(
|
||||||
ref.invalidate(
|
margin: EdgeInsets.only(
|
||||||
eventCalendarProvider(query.value),
|
left: 8,
|
||||||
);
|
right: 12,
|
||||||
},
|
top: 8,
|
||||||
),
|
),
|
||||||
PostFeaturedList().padding(
|
events: events,
|
||||||
left: 8,
|
constrainWidth: true,
|
||||||
right: 12,
|
onPointSelected: onDaySelected,
|
||||||
top: 8,
|
),
|
||||||
),
|
],
|
||||||
FortuneGraphWidget(
|
),
|
||||||
margin: EdgeInsets.only(left: 8, right: 12, top: 8),
|
|
||||||
events: events,
|
|
||||||
constrainWidth: true,
|
|
||||||
onPointSelected: onDaySelected,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
@@ -268,7 +366,7 @@ class ExploreScreen extends HookConsumerWidget {
|
|||||||
activityListNotifierProvider(filter).notifier,
|
activityListNotifierProvider(filter).notifier,
|
||||||
);
|
);
|
||||||
|
|
||||||
final isWider = isWiderScreen(context);
|
final isWide = isWideScreen(context);
|
||||||
|
|
||||||
return RefreshIndicator(
|
return RefreshIndicator(
|
||||||
onRefresh: () => Future.sync(activitiesNotifier.forceRefresh),
|
onRefresh: () => Future.sync(activitiesNotifier.forceRefresh),
|
||||||
@@ -283,7 +381,7 @@ class ExploreScreen extends HookConsumerWidget {
|
|||||||
widgetCount: widgetCount,
|
widgetCount: widgetCount,
|
||||||
endItemView: endItemView,
|
endItemView: endItemView,
|
||||||
activitiesNotifier: activitiesNotifier,
|
activitiesNotifier: activitiesNotifier,
|
||||||
contentOnly: isWider || filter != null,
|
contentOnly: isWide || filter != null,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -380,6 +478,10 @@ class _ActivityListView extends HookConsumerWidget {
|
|||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final user = ref.watch(userInfoProvider);
|
final user = ref.watch(userInfoProvider);
|
||||||
|
|
||||||
|
final notificationCount = ref.watch(
|
||||||
|
notificationUnreadCountNotifierProvider,
|
||||||
|
);
|
||||||
|
|
||||||
return CustomScrollView(
|
return CustomScrollView(
|
||||||
slivers: [
|
slivers: [
|
||||||
SliverGap(12),
|
SliverGap(12),
|
||||||
@@ -393,6 +495,14 @@ class _ActivityListView extends HookConsumerWidget {
|
|||||||
SliverToBoxAdapter(
|
SliverToBoxAdapter(
|
||||||
child: PostFeaturedList().padding(horizontal: 8, bottom: 4, top: 4),
|
child: PostFeaturedList().padding(horizontal: 8, bottom: 4, top: 4),
|
||||||
),
|
),
|
||||||
|
if (!contentOnly && (notificationCount.value ?? 0) > 0)
|
||||||
|
SliverToBoxAdapter(
|
||||||
|
child: notificationIndicatorWidget(
|
||||||
|
context,
|
||||||
|
count: notificationCount.value ?? 0,
|
||||||
|
margin: EdgeInsets.only(left: 8, right: 8, top: 4, bottom: 4),
|
||||||
|
),
|
||||||
|
),
|
||||||
SliverList.builder(
|
SliverList.builder(
|
||||||
itemCount: widgetCount,
|
itemCount: widgetCount,
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
|
@@ -3,14 +3,17 @@ import 'dart:math' as math;
|
|||||||
|
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:gap/gap.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:island/models/account.dart';
|
import 'package:island/models/account.dart';
|
||||||
import 'package:island/pods/network.dart';
|
import 'package:island/pods/network.dart';
|
||||||
import 'package:island/pods/websocket.dart';
|
import 'package:island/pods/websocket.dart';
|
||||||
import 'package:island/route.dart';
|
import 'package:island/route.dart';
|
||||||
|
import 'package:island/widgets/alert.dart';
|
||||||
import 'package:island/widgets/app_scaffold.dart';
|
import 'package:island/widgets/app_scaffold.dart';
|
||||||
import 'package:island/widgets/content/markdown.dart';
|
import 'package:island/widgets/content/markdown.dart';
|
||||||
|
import 'package:material_symbols_icons/material_symbols_icons.dart';
|
||||||
import 'package:relative_time/relative_time.dart';
|
import 'package:relative_time/relative_time.dart';
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
import 'package:riverpod_paging_utils/riverpod_paging_utils.dart';
|
import 'package:riverpod_paging_utils/riverpod_paging_utils.dart';
|
||||||
@@ -62,6 +65,10 @@ class NotificationUnreadCountNotifier
|
|||||||
final current = await future;
|
final current = await future;
|
||||||
state = AsyncData(math.max(current - count, 0));
|
state = AsyncData(math.max(current - count, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void clear() async {
|
||||||
|
state = AsyncData(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@riverpod
|
@riverpod
|
||||||
@@ -111,8 +118,28 @@ class NotificationScreen extends HookConsumerWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
Future<void> markAllRead() async {
|
||||||
|
showLoadingModal(context);
|
||||||
|
final apiClient = ref.watch(apiClientProvider);
|
||||||
|
await apiClient.post('/pusher/notifications/all/read');
|
||||||
|
if (!context.mounted) return;
|
||||||
|
hideLoadingModal(context);
|
||||||
|
ref.invalidate(notificationListNotifierProvider);
|
||||||
|
ref.watch(notificationUnreadCountNotifierProvider.notifier).clear();
|
||||||
|
}
|
||||||
|
|
||||||
return AppScaffold(
|
return AppScaffold(
|
||||||
appBar: AppBar(title: const Text('notifications').tr()),
|
appBar: AppBar(
|
||||||
|
leading: const PageBackButton(),
|
||||||
|
title: const Text('notifications').tr(),
|
||||||
|
actions: [
|
||||||
|
IconButton(
|
||||||
|
onPressed: markAllRead,
|
||||||
|
icon: const Icon(Symbols.mark_as_unread),
|
||||||
|
),
|
||||||
|
const Gap(8),
|
||||||
|
],
|
||||||
|
),
|
||||||
body: PagingHelperView(
|
body: PagingHelperView(
|
||||||
provider: notificationListNotifierProvider,
|
provider: notificationListNotifierProvider,
|
||||||
futureRefreshable: notificationListNotifierProvider.future,
|
futureRefreshable: notificationListNotifierProvider.future,
|
||||||
|
@@ -7,7 +7,7 @@ part of 'notification.dart';
|
|||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
String _$notificationUnreadCountNotifierHash() =>
|
String _$notificationUnreadCountNotifierHash() =>
|
||||||
r'd199abf0d16944587e747798399a267a790341f3';
|
r'0763b66bd64e5a9b7c317887e109ab367515dfa4';
|
||||||
|
|
||||||
/// See also [NotificationUnreadCountNotifier].
|
/// See also [NotificationUnreadCountNotifier].
|
||||||
@ProviderFor(NotificationUnreadCountNotifier)
|
@ProviderFor(NotificationUnreadCountNotifier)
|
||||||
|
@@ -89,6 +89,9 @@ class ArticleComposeScreen extends HookConsumerWidget {
|
|||||||
}, [state]);
|
}, [state]);
|
||||||
|
|
||||||
final showPreview = useState(false);
|
final showPreview = useState(false);
|
||||||
|
final isAttachmentsExpanded = useState(
|
||||||
|
true,
|
||||||
|
); // New state for attachments section
|
||||||
|
|
||||||
// Initialize publisher once when data is available
|
// Initialize publisher once when data is available
|
||||||
useEffect(() {
|
useEffect(() {
|
||||||
@@ -297,71 +300,88 @@ class ArticleComposeScreen extends HookConsumerWidget {
|
|||||||
valueListenable: state.attachments,
|
valueListenable: state.attachments,
|
||||||
builder: (context, attachments, _) {
|
builder: (context, attachments, _) {
|
||||||
if (attachments.isEmpty) return const SizedBox.shrink();
|
if (attachments.isEmpty) return const SizedBox.shrink();
|
||||||
return Column(
|
return Theme(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
data: Theme.of(
|
||||||
children: [
|
context,
|
||||||
const Gap(16),
|
).copyWith(dividerColor: Colors.transparent),
|
||||||
Text(
|
child: ExpansionTile(
|
||||||
'articleAttachmentHint'.tr(),
|
initiallyExpanded: isAttachmentsExpanded.value,
|
||||||
style: Theme.of(context).textTheme.bodySmall?.copyWith(
|
onExpansionChanged: (expanded) {
|
||||||
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
isAttachmentsExpanded.value = expanded;
|
||||||
),
|
},
|
||||||
).padding(bottom: 8),
|
collapsedBackgroundColor:
|
||||||
ValueListenableBuilder<Map<int, double>>(
|
Theme.of(context).colorScheme.surfaceContainer,
|
||||||
valueListenable: state.attachmentProgress,
|
title: Column(
|
||||||
builder: (context, progressMap, _) {
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
return Wrap(
|
children: [
|
||||||
spacing: 8,
|
Text('attachments').tr(),
|
||||||
runSpacing: 8,
|
Text(
|
||||||
children: [
|
'articleAttachmentHint'.tr(),
|
||||||
for (var idx = 0; idx < attachments.length; idx++)
|
style: Theme.of(
|
||||||
SizedBox(
|
context,
|
||||||
width: 280,
|
).textTheme.bodySmall?.copyWith(
|
||||||
height: 280,
|
color:
|
||||||
child: AttachmentPreview(
|
Theme.of(
|
||||||
item: attachments[idx],
|
context,
|
||||||
progress: progressMap[idx],
|
).colorScheme.onSurfaceVariant,
|
||||||
onRequestUpload:
|
),
|
||||||
() => ComposeLogic.uploadAttachment(
|
),
|
||||||
ref,
|
],
|
||||||
state,
|
|
||||||
idx,
|
|
||||||
),
|
|
||||||
onUpdate:
|
|
||||||
(value) =>
|
|
||||||
ComposeLogic.updateAttachment(
|
|
||||||
state,
|
|
||||||
value,
|
|
||||||
idx,
|
|
||||||
),
|
|
||||||
onDelete:
|
|
||||||
() => ComposeLogic.deleteAttachment(
|
|
||||||
ref,
|
|
||||||
state,
|
|
||||||
idx,
|
|
||||||
),
|
|
||||||
onMove: (delta) {
|
|
||||||
state
|
|
||||||
.attachments
|
|
||||||
.value = ComposeLogic.moveAttachment(
|
|
||||||
state.attachments.value,
|
|
||||||
idx,
|
|
||||||
delta,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
onInsert:
|
|
||||||
() => ComposeLogic.insertAttachment(
|
|
||||||
ref,
|
|
||||||
state,
|
|
||||||
idx,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
],
|
children: [
|
||||||
|
ValueListenableBuilder<Map<int, double>>(
|
||||||
|
valueListenable: state.attachmentProgress,
|
||||||
|
builder: (context, progressMap, _) {
|
||||||
|
return Wrap(
|
||||||
|
runSpacing: 8,
|
||||||
|
spacing: 8,
|
||||||
|
children: [
|
||||||
|
for (
|
||||||
|
var idx = 0;
|
||||||
|
idx < attachments.length;
|
||||||
|
idx++
|
||||||
|
)
|
||||||
|
SizedBox(
|
||||||
|
width: 180,
|
||||||
|
height: 180,
|
||||||
|
child: AttachmentPreview(
|
||||||
|
isCompact: true,
|
||||||
|
item: attachments[idx],
|
||||||
|
progress: progressMap[idx],
|
||||||
|
onRequestUpload:
|
||||||
|
() => ComposeLogic.uploadAttachment(
|
||||||
|
ref,
|
||||||
|
state,
|
||||||
|
idx,
|
||||||
|
),
|
||||||
|
onUpdate:
|
||||||
|
(value) =>
|
||||||
|
ComposeLogic.updateAttachment(
|
||||||
|
state,
|
||||||
|
value,
|
||||||
|
idx,
|
||||||
|
),
|
||||||
|
onDelete:
|
||||||
|
() => ComposeLogic.deleteAttachment(
|
||||||
|
ref,
|
||||||
|
state,
|
||||||
|
idx,
|
||||||
|
),
|
||||||
|
onInsert:
|
||||||
|
() => ComposeLogic.insertAttachment(
|
||||||
|
ref,
|
||||||
|
state,
|
||||||
|
idx,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
Gap(16),
|
||||||
|
],
|
||||||
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
242
lib/screens/posts/post_categories_list.dart
Normal file
242
lib/screens/posts/post_categories_list.dart
Normal file
@@ -0,0 +1,242 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:go_router/go_router.dart';
|
||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:island/models/post_category.dart';
|
||||||
|
import 'package:island/models/post_tag.dart';
|
||||||
|
import 'package:island/pods/network.dart';
|
||||||
|
import 'package:island/widgets/app_scaffold.dart';
|
||||||
|
import 'package:island/widgets/response.dart';
|
||||||
|
import 'package:material_symbols_icons/symbols.dart';
|
||||||
|
import 'package:riverpod_paging_utils/riverpod_paging_utils.dart';
|
||||||
|
|
||||||
|
// Post Categories Notifier
|
||||||
|
final postCategoriesNotifierProvider = StateNotifierProvider.autoDispose<
|
||||||
|
PostCategoriesNotifier,
|
||||||
|
AsyncValue<CursorPagingData<SnPostCategory>>
|
||||||
|
>((ref) {
|
||||||
|
return PostCategoriesNotifier(ref);
|
||||||
|
});
|
||||||
|
|
||||||
|
class PostCategoriesNotifier
|
||||||
|
extends StateNotifier<AsyncValue<CursorPagingData<SnPostCategory>>> {
|
||||||
|
final AutoDisposeRef ref;
|
||||||
|
static const int _pageSize = 20;
|
||||||
|
bool _isLoading = false;
|
||||||
|
|
||||||
|
PostCategoriesNotifier(this.ref) : super(const AsyncValue.loading()) {
|
||||||
|
state = const AsyncValue.data(
|
||||||
|
CursorPagingData(items: [], hasMore: false, nextCursor: null),
|
||||||
|
);
|
||||||
|
fetch(cursor: null);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> fetch({String? cursor}) async {
|
||||||
|
if (_isLoading) return;
|
||||||
|
|
||||||
|
_isLoading = true;
|
||||||
|
if (cursor == null) {
|
||||||
|
state = const AsyncValue.loading();
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
final client = ref.read(apiClientProvider);
|
||||||
|
final offset = cursor == null ? 0 : int.parse(cursor);
|
||||||
|
|
||||||
|
final response = await client.get(
|
||||||
|
'/sphere/posts/categories',
|
||||||
|
queryParameters: {
|
||||||
|
'offset': offset,
|
||||||
|
'take': _pageSize,
|
||||||
|
'order': 'usage',
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
final data = response.data as List;
|
||||||
|
final categories =
|
||||||
|
data.map((json) => SnPostCategory.fromJson(json)).toList();
|
||||||
|
final hasMore = categories.length == _pageSize;
|
||||||
|
final nextCursor =
|
||||||
|
hasMore ? (offset + categories.length).toString() : null;
|
||||||
|
|
||||||
|
state = AsyncValue.data(
|
||||||
|
CursorPagingData(
|
||||||
|
items: [...(state.value?.items ?? []), ...categories],
|
||||||
|
hasMore: hasMore,
|
||||||
|
nextCursor: nextCursor,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} catch (e, stack) {
|
||||||
|
state = AsyncValue.error(e, stack);
|
||||||
|
} finally {
|
||||||
|
_isLoading = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Post Tags Notifier
|
||||||
|
final postTagsNotifierProvider = StateNotifierProvider.autoDispose<
|
||||||
|
PostTagsNotifier,
|
||||||
|
AsyncValue<CursorPagingData<SnPostTag>>
|
||||||
|
>((ref) {
|
||||||
|
return PostTagsNotifier(ref);
|
||||||
|
});
|
||||||
|
|
||||||
|
class PostTagsNotifier
|
||||||
|
extends StateNotifier<AsyncValue<CursorPagingData<SnPostTag>>> {
|
||||||
|
final AutoDisposeRef ref;
|
||||||
|
static const int _pageSize = 20;
|
||||||
|
bool _isLoading = false;
|
||||||
|
|
||||||
|
PostTagsNotifier(this.ref) : super(const AsyncValue.loading()) {
|
||||||
|
state = const AsyncValue.data(
|
||||||
|
CursorPagingData(items: [], hasMore: false, nextCursor: null),
|
||||||
|
);
|
||||||
|
fetch(cursor: null);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> fetch({String? cursor}) async {
|
||||||
|
if (_isLoading) return;
|
||||||
|
|
||||||
|
_isLoading = true;
|
||||||
|
if (cursor == null) {
|
||||||
|
state = const AsyncValue.loading();
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
final client = ref.read(apiClientProvider);
|
||||||
|
final offset = cursor == null ? 0 : int.parse(cursor);
|
||||||
|
|
||||||
|
final response = await client.get(
|
||||||
|
'/sphere/posts/tags',
|
||||||
|
queryParameters: {
|
||||||
|
'offset': offset,
|
||||||
|
'take': _pageSize,
|
||||||
|
'order': 'usage',
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
final data = response.data as List;
|
||||||
|
final tags = data.map((json) => SnPostTag.fromJson(json)).toList();
|
||||||
|
final hasMore = tags.length == _pageSize;
|
||||||
|
final nextCursor = hasMore ? (offset + tags.length).toString() : null;
|
||||||
|
|
||||||
|
state = AsyncValue.data(
|
||||||
|
CursorPagingData(
|
||||||
|
items: [...(state.value?.items ?? []), ...tags],
|
||||||
|
hasMore: hasMore,
|
||||||
|
nextCursor: nextCursor,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} catch (e, stack) {
|
||||||
|
state = AsyncValue.error(e, stack);
|
||||||
|
} finally {
|
||||||
|
_isLoading = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class PostCategoriesListScreen extends ConsumerWidget {
|
||||||
|
const PostCategoriesListScreen({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final categoriesState = ref.watch(postCategoriesNotifierProvider);
|
||||||
|
|
||||||
|
return AppScaffold(
|
||||||
|
appBar: AppBar(title: const Text('categories').tr()),
|
||||||
|
body: categoriesState.when(
|
||||||
|
data: (data) {
|
||||||
|
if (data.items.isEmpty) {
|
||||||
|
return const Center(child: Text('No categories found'));
|
||||||
|
}
|
||||||
|
return ListView.builder(
|
||||||
|
padding: EdgeInsets.zero,
|
||||||
|
itemCount: data.items.length + (data.hasMore ? 1 : 0),
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
if (index >= data.items.length) {
|
||||||
|
ref
|
||||||
|
.read(postCategoriesNotifierProvider.notifier)
|
||||||
|
.fetch(cursor: data.nextCursor);
|
||||||
|
return const Center(child: CircularProgressIndicator());
|
||||||
|
}
|
||||||
|
final category = data.items[index];
|
||||||
|
return ListTile(
|
||||||
|
leading: const Icon(Symbols.category),
|
||||||
|
contentPadding: EdgeInsets.symmetric(horizontal: 24),
|
||||||
|
trailing: const Icon(Symbols.chevron_right),
|
||||||
|
title: Text(category.categoryDisplayTitle),
|
||||||
|
subtitle: Text('postCount'.plural(category.usage)),
|
||||||
|
onTap: () {
|
||||||
|
context.pushNamed(
|
||||||
|
'postCategoryDetail',
|
||||||
|
pathParameters: {'slug': category.slug},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
loading: () => const Center(child: CircularProgressIndicator()),
|
||||||
|
error:
|
||||||
|
(error, stack) => ResponseErrorWidget(
|
||||||
|
error: error,
|
||||||
|
onRetry: () => ref.invalidate(postCategoriesNotifierProvider),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class PostTagsListScreen extends ConsumerWidget {
|
||||||
|
const PostTagsListScreen({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final tagsState = ref.watch(postTagsNotifierProvider);
|
||||||
|
|
||||||
|
return AppScaffold(
|
||||||
|
appBar: AppBar(title: const Text('tags').tr()),
|
||||||
|
body: tagsState.when(
|
||||||
|
data: (data) {
|
||||||
|
if (data.items.isEmpty) {
|
||||||
|
return const Center(child: Text('No tags found'));
|
||||||
|
}
|
||||||
|
return ListView.builder(
|
||||||
|
padding: EdgeInsets.zero,
|
||||||
|
itemCount: data.items.length + (data.hasMore ? 1 : 0),
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
if (index >= data.items.length) {
|
||||||
|
ref
|
||||||
|
.read(postTagsNotifierProvider.notifier)
|
||||||
|
.fetch(cursor: data.nextCursor);
|
||||||
|
return const Center(child: CircularProgressIndicator());
|
||||||
|
}
|
||||||
|
final tag = data.items[index];
|
||||||
|
return ListTile(
|
||||||
|
title: Text(tag.name ?? '#${tag.slug}'),
|
||||||
|
contentPadding: EdgeInsets.symmetric(horizontal: 24),
|
||||||
|
leading: const Icon(Symbols.label),
|
||||||
|
trailing: const Icon(Symbols.chevron_right),
|
||||||
|
subtitle: Text('postCount'.plural(tag.usage)),
|
||||||
|
onTap: () {
|
||||||
|
context.pushNamed(
|
||||||
|
'postTagDetail',
|
||||||
|
pathParameters: {'slug': tag.slug},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
loading: () => const Center(child: CircularProgressIndicator()),
|
||||||
|
error:
|
||||||
|
(error, stack) => ResponseErrorWidget(
|
||||||
|
error: error,
|
||||||
|
onRetry: () => ref.invalidate(postTagsNotifierProvider),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@@ -1,3 +1,4 @@
|
|||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:gap/gap.dart';
|
import 'package:gap/gap.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
@@ -8,6 +9,7 @@ import 'package:island/widgets/app_scaffold.dart';
|
|||||||
import 'package:island/widgets/post/post_item.dart';
|
import 'package:island/widgets/post/post_item.dart';
|
||||||
import 'package:island/widgets/post/post_quick_reply.dart';
|
import 'package:island/widgets/post/post_quick_reply.dart';
|
||||||
import 'package:island/widgets/post/post_replies.dart';
|
import 'package:island/widgets/post/post_replies.dart';
|
||||||
|
import 'package:island/widgets/response.dart';
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
import 'package:styled_widget/styled_widget.dart';
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
|
|
||||||
@@ -55,7 +57,10 @@ class PostDetailScreen extends HookConsumerWidget {
|
|||||||
|
|
||||||
return AppScaffold(
|
return AppScaffold(
|
||||||
isNoBackground: false,
|
isNoBackground: false,
|
||||||
appBar: AppBar(title: const Text('Post')),
|
appBar: AppBar(
|
||||||
|
leading: const PageBackButton(),
|
||||||
|
title: Text('postDetail').tr(),
|
||||||
|
),
|
||||||
body: postState.when(
|
body: postState.when(
|
||||||
data: (post) {
|
data: (post) {
|
||||||
return Stack(
|
return Stack(
|
||||||
@@ -117,8 +122,12 @@ class PostDetailScreen extends HookConsumerWidget {
|
|||||||
],
|
],
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
loading: () => const Center(child: CircularProgressIndicator()),
|
loading: () => ResponseLoadingWidget(),
|
||||||
error: (e, _) => Text('Error: $e'),
|
error:
|
||||||
|
(e, _) => ResponseErrorWidget(
|
||||||
|
error: e,
|
||||||
|
onRetry: () => ref.invalidate(postStateProvider(id)),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@@ -51,12 +51,12 @@ class PostSearchNotifier
|
|||||||
final offset = cursor == null ? 0 : int.parse(cursor);
|
final offset = cursor == null ? 0 : int.parse(cursor);
|
||||||
|
|
||||||
final response = await client.get(
|
final response = await client.get(
|
||||||
'/sphere/posts/search',
|
'/sphere/posts',
|
||||||
queryParameters: {
|
queryParameters: {
|
||||||
'query': _currentQuery,
|
'query': _currentQuery,
|
||||||
'offset': offset,
|
'offset': offset,
|
||||||
'take': _pageSize,
|
'take': _pageSize,
|
||||||
'useVector': false,
|
'vector': false,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@@ -147,7 +147,11 @@ class PublisherProfileScreen extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
backgroundColor: Theme.of(context).colorScheme.primary,
|
backgroundColor: Theme.of(context).colorScheme.primary,
|
||||||
offset: Offset(0, 48),
|
offset: Offset(0, 48),
|
||||||
child: ProfilePictureWidget(file: data.picture, radius: 32),
|
child: ProfilePictureWidget(
|
||||||
|
file: data.picture,
|
||||||
|
radius: 32,
|
||||||
|
borderRadius: data.type == 0 ? null : 12,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Navigator.pop(context, true);
|
Navigator.pop(context, true);
|
||||||
|
@@ -4,6 +4,9 @@ import 'package:island/screens/chat/chat.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:island/models/chat.dart';
|
import 'package:island/models/chat.dart';
|
||||||
import 'package:island/services/color.dart';
|
import 'package:island/services/color.dart';
|
||||||
|
import 'package:island/services/responsive.dart';
|
||||||
|
import 'package:island/widgets/account/status.dart';
|
||||||
|
import 'package:island/widgets/post/post_list.dart';
|
||||||
import 'package:palette_generator/palette_generator.dart';
|
import 'package:palette_generator/palette_generator.dart';
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
import 'package:gap/gap.dart';
|
import 'package:gap/gap.dart';
|
||||||
@@ -78,155 +81,287 @@ class RealmDetailScreen extends HookConsumerWidget {
|
|||||||
offset: Offset(1.0, 1.0),
|
offset: Offset(1.0, 1.0),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
final realmIdentity = ref.watch(realmIdentityProvider(slug));
|
||||||
|
final realmChatRooms = ref.watch(realmChatRoomsProvider(slug));
|
||||||
|
|
||||||
|
Widget realmDescriptionWidget(SnRealm realm) => Card(
|
||||||
|
margin: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||||||
|
child: Theme(
|
||||||
|
data: Theme.of(context).copyWith(dividerColor: Colors.transparent),
|
||||||
|
child: ExpansionTile(
|
||||||
|
shape: const RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(8)),
|
||||||
|
),
|
||||||
|
collapsedShape: const RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(8)),
|
||||||
|
),
|
||||||
|
title: const Text('description').tr(),
|
||||||
|
initiallyExpanded:
|
||||||
|
realmIdentity.hasValue && realmIdentity.value == null,
|
||||||
|
tilePadding: EdgeInsets.only(left: 24, right: 20),
|
||||||
|
expandedCrossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
realm.description,
|
||||||
|
style: const TextStyle(fontSize: 16),
|
||||||
|
).padding(horizontal: 20, bottom: 16, top: 8),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
Widget realmActionWidget(SnRealm realm) => Card(
|
||||||
|
margin: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||||||
|
child: FilledButton.tonalIcon(
|
||||||
|
onPressed: () async {
|
||||||
|
try {
|
||||||
|
final apiClient = ref.read(apiClientProvider);
|
||||||
|
await apiClient.post('/sphere/realms/$slug/members/me');
|
||||||
|
ref.invalidate(realmIdentityProvider(slug));
|
||||||
|
ref.invalidate(realmsJoinedProvider);
|
||||||
|
showSnackBar('realmJoinSuccess'.tr());
|
||||||
|
} catch (err) {
|
||||||
|
showErrorAlert(err);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
icon: const Icon(Symbols.add),
|
||||||
|
label: const Text('realmJoin').tr(),
|
||||||
|
).padding(all: 16),
|
||||||
|
);
|
||||||
|
|
||||||
|
Widget realmChatRoomListWidget(SnRealm realm) => Card(
|
||||||
|
margin: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
'chatTabGroup',
|
||||||
|
).tr().bold().padding(horizontal: 24, top: 12, bottom: 4),
|
||||||
|
realmChatRooms.when(
|
||||||
|
loading: () => Center(child: CircularProgressIndicator()),
|
||||||
|
error: (error, _) => Center(child: Text('Error: $error')),
|
||||||
|
data: (rooms) {
|
||||||
|
if (rooms.isEmpty) {
|
||||||
|
return Text(
|
||||||
|
'dataEmpty',
|
||||||
|
).tr().padding(horizontal: 24, bottom: 12);
|
||||||
|
}
|
||||||
|
return Column(
|
||||||
|
children: [
|
||||||
|
for (final room in rooms)
|
||||||
|
ChatRoomListTile(
|
||||||
|
room: room,
|
||||||
|
onTap: () {
|
||||||
|
context.pushNamed(
|
||||||
|
'chatRoom',
|
||||||
|
pathParameters: {'id': room.id},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
return AppScaffold(
|
return AppScaffold(
|
||||||
isNoBackground: false,
|
isNoBackground: false,
|
||||||
|
appBar:
|
||||||
|
isWideScreen(context)
|
||||||
|
? realmState.when(
|
||||||
|
data:
|
||||||
|
(realm) => AppBar(
|
||||||
|
foregroundColor: appbarColor.value,
|
||||||
|
leading: PageBackButton(
|
||||||
|
color: appbarColor.value,
|
||||||
|
shadows: [iconShadow],
|
||||||
|
),
|
||||||
|
flexibleSpace: Stack(
|
||||||
|
children: [
|
||||||
|
Positioned.fill(
|
||||||
|
child:
|
||||||
|
realm!.background?.id != null
|
||||||
|
? CloudImageWidget(
|
||||||
|
fileId: realm.background!.id,
|
||||||
|
)
|
||||||
|
: Container(
|
||||||
|
color:
|
||||||
|
Theme.of(
|
||||||
|
context,
|
||||||
|
).appBarTheme.backgroundColor,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
FlexibleSpaceBar(
|
||||||
|
title: Text(
|
||||||
|
realm.name,
|
||||||
|
style: TextStyle(
|
||||||
|
color:
|
||||||
|
appbarColor.value ??
|
||||||
|
Theme.of(
|
||||||
|
context,
|
||||||
|
).appBarTheme.foregroundColor,
|
||||||
|
shadows: [iconShadow],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
background: Container(),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
IconButton(
|
||||||
|
icon: Icon(Icons.people, shadows: [iconShadow]),
|
||||||
|
onPressed: () {
|
||||||
|
showModalBottomSheet(
|
||||||
|
isScrollControlled: true,
|
||||||
|
context: context,
|
||||||
|
builder:
|
||||||
|
(context) =>
|
||||||
|
_RealmMemberListSheet(realmSlug: slug),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
_RealmActionMenu(
|
||||||
|
realmSlug: slug,
|
||||||
|
iconShadow: iconShadow,
|
||||||
|
),
|
||||||
|
const Gap(8),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
error: (_, _) => AppBar(leading: PageBackButton()),
|
||||||
|
loading: () => AppBar(leading: PageBackButton()),
|
||||||
|
)
|
||||||
|
: null,
|
||||||
body: realmState.when(
|
body: realmState.when(
|
||||||
loading: () => const Center(child: CircularProgressIndicator()),
|
loading: () => const Center(child: CircularProgressIndicator()),
|
||||||
error: (error, _) => Center(child: Text('Error: $error')),
|
error: (error, _) => Center(child: Text('Error: $error')),
|
||||||
data:
|
data:
|
||||||
(realm) => CustomScrollView(
|
(realm) =>
|
||||||
slivers: [
|
isWideScreen(context)
|
||||||
SliverAppBar(
|
? Row(
|
||||||
expandedHeight: 180,
|
children: [
|
||||||
pinned: true,
|
Flexible(
|
||||||
foregroundColor: appbarColor.value,
|
flex: 3,
|
||||||
leading: PageBackButton(
|
child: CustomScrollView(
|
||||||
color: appbarColor.value,
|
slivers: [SliverPostList(realm: slug)],
|
||||||
shadows: [iconShadow],
|
),
|
||||||
),
|
),
|
||||||
flexibleSpace: FlexibleSpaceBar(
|
Flexible(
|
||||||
background:
|
flex: 2,
|
||||||
realm!.background?.id != null
|
child: Column(
|
||||||
? CloudImageWidget(fileId: realm.background!.id)
|
children: [
|
||||||
: Container(
|
realmIdentity.when(
|
||||||
color:
|
loading: () => const SizedBox.shrink(),
|
||||||
Theme.of(context).appBarTheme.backgroundColor,
|
error: (_, _) => const SizedBox.shrink(),
|
||||||
),
|
data:
|
||||||
title: Text(
|
(identity) => Column(
|
||||||
realm.name,
|
crossAxisAlignment:
|
||||||
style: TextStyle(
|
CrossAxisAlignment.stretch,
|
||||||
color:
|
children: [
|
||||||
appbarColor.value ??
|
realmDescriptionWidget(realm!),
|
||||||
Theme.of(context).appBarTheme.foregroundColor,
|
if (identity == null &&
|
||||||
shadows: [iconShadow],
|
realm.isCommunity)
|
||||||
),
|
realmActionWidget(realm)
|
||||||
),
|
else
|
||||||
),
|
const SizedBox.shrink(),
|
||||||
actions: [
|
],
|
||||||
IconButton(
|
|
||||||
icon: Icon(Icons.people, shadows: [iconShadow]),
|
|
||||||
onPressed: () {
|
|
||||||
showModalBottomSheet(
|
|
||||||
isScrollControlled: true,
|
|
||||||
context: context,
|
|
||||||
builder:
|
|
||||||
(context) =>
|
|
||||||
_RealmMemberListSheet(realmSlug: slug),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
_RealmActionMenu(realmSlug: slug, iconShadow: iconShadow),
|
|
||||||
const Gap(8),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
SliverToBoxAdapter(
|
|
||||||
child: ref
|
|
||||||
.watch(realmIdentityProvider(slug))
|
|
||||||
.when(
|
|
||||||
loading: () => const SizedBox.shrink(),
|
|
||||||
error: (_, _) => const SizedBox.shrink(),
|
|
||||||
data:
|
|
||||||
(identity) => Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
|
||||||
children: [
|
|
||||||
ExpansionTile(
|
|
||||||
title: const Text('description').tr(),
|
|
||||||
initiallyExpanded: identity == null,
|
|
||||||
tilePadding: EdgeInsets.symmetric(
|
|
||||||
horizontal: 20,
|
|
||||||
),
|
|
||||||
expandedCrossAxisAlignment:
|
|
||||||
CrossAxisAlignment.stretch,
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
realm.description,
|
|
||||||
style: const TextStyle(fontSize: 16),
|
|
||||||
).padding(
|
|
||||||
horizontal: 20,
|
|
||||||
bottom: 16,
|
|
||||||
top: 8,
|
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
|
realmChatRoomListWidget(realm!),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
).padding(horizontal: 8, top: 8)
|
||||||
|
: CustomScrollView(
|
||||||
|
slivers: [
|
||||||
|
SliverAppBar(
|
||||||
|
expandedHeight: 180,
|
||||||
|
pinned: true,
|
||||||
|
foregroundColor: appbarColor.value,
|
||||||
|
leading: PageBackButton(
|
||||||
|
color: appbarColor.value,
|
||||||
|
shadows: [iconShadow],
|
||||||
|
),
|
||||||
|
flexibleSpace: Stack(
|
||||||
|
children: [
|
||||||
|
Positioned.fill(
|
||||||
|
child:
|
||||||
|
realm!.background?.id != null
|
||||||
|
? CloudImageWidget(
|
||||||
|
fileId: realm.background!.id,
|
||||||
|
)
|
||||||
|
: Container(
|
||||||
|
color:
|
||||||
|
Theme.of(
|
||||||
|
context,
|
||||||
|
).appBarTheme.backgroundColor,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
FlexibleSpaceBar(
|
||||||
|
title: Text(
|
||||||
|
realm.name,
|
||||||
|
style: TextStyle(
|
||||||
|
color:
|
||||||
|
appbarColor.value ??
|
||||||
|
Theme.of(
|
||||||
|
context,
|
||||||
|
).appBarTheme.foregroundColor,
|
||||||
|
shadows: [iconShadow],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
if (identity == null && realm.isCommunity)
|
background:
|
||||||
FilledButton.tonalIcon(
|
Container(), // Empty container since background is handled by Stack
|
||||||
onPressed: () async {
|
),
|
||||||
try {
|
],
|
||||||
final apiClient = ref.read(
|
|
||||||
apiClientProvider,
|
|
||||||
);
|
|
||||||
await apiClient.post(
|
|
||||||
'/sphere/realms/$slug/members/me',
|
|
||||||
);
|
|
||||||
ref.invalidate(
|
|
||||||
realmIdentityProvider(slug),
|
|
||||||
);
|
|
||||||
ref.invalidate(realmsJoinedProvider);
|
|
||||||
showSnackBar('realmJoinSuccess'.tr());
|
|
||||||
} catch (err) {
|
|
||||||
showErrorAlert(err);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
icon: const Icon(Symbols.add),
|
|
||||||
label: const Text('realmJoin').tr(),
|
|
||||||
).padding(horizontal: 16, vertical: 16)
|
|
||||||
else
|
|
||||||
const SizedBox.shrink(),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SliverToBoxAdapter(child: Divider(height: 1)),
|
|
||||||
Consumer(
|
|
||||||
builder: (context, ref, _) {
|
|
||||||
final chatRooms = ref.watch(realmChatRoomsProvider(slug));
|
|
||||||
return chatRooms.when(
|
|
||||||
loading:
|
|
||||||
() => const SliverToBoxAdapter(
|
|
||||||
child: Center(child: CircularProgressIndicator()),
|
|
||||||
),
|
),
|
||||||
error:
|
actions: [
|
||||||
(error, _) => SliverToBoxAdapter(
|
IconButton(
|
||||||
child: Center(child: Text('Error: $error')),
|
icon: Icon(Icons.people, shadows: [iconShadow]),
|
||||||
),
|
onPressed: () {
|
||||||
data: (rooms) {
|
showModalBottomSheet(
|
||||||
if (rooms.isEmpty) {
|
isScrollControlled: true,
|
||||||
return const SliverToBoxAdapter(
|
context: context,
|
||||||
child: SizedBox.shrink(),
|
builder:
|
||||||
);
|
(context) => _RealmMemberListSheet(
|
||||||
}
|
realmSlug: slug,
|
||||||
return SliverList(
|
),
|
||||||
delegate: SliverChildBuilderDelegate((
|
|
||||||
context,
|
|
||||||
index,
|
|
||||||
) {
|
|
||||||
return ChatRoomListTile(
|
|
||||||
room: rooms[index],
|
|
||||||
onTap: () {
|
|
||||||
context.pushNamed(
|
|
||||||
'chatRoom',
|
|
||||||
pathParameters: {'id': rooms[index].id},
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
),
|
||||||
}, childCount: rooms.length),
|
_RealmActionMenu(
|
||||||
);
|
realmSlug: slug,
|
||||||
},
|
iconShadow: iconShadow,
|
||||||
);
|
),
|
||||||
},
|
const Gap(8),
|
||||||
),
|
],
|
||||||
],
|
),
|
||||||
),
|
SliverGap(4),
|
||||||
|
SliverToBoxAdapter(
|
||||||
|
child: realmIdentity.when(
|
||||||
|
loading: () => const SizedBox.shrink(),
|
||||||
|
error: (_, _) => const SizedBox.shrink(),
|
||||||
|
data:
|
||||||
|
(identity) => Column(
|
||||||
|
crossAxisAlignment:
|
||||||
|
CrossAxisAlignment.stretch,
|
||||||
|
children: [
|
||||||
|
realmDescriptionWidget(realm),
|
||||||
|
if (identity == null && realm.isCommunity)
|
||||||
|
realmActionWidget(realm)
|
||||||
|
else
|
||||||
|
const SizedBox.shrink(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SliverToBoxAdapter(
|
||||||
|
child: realmChatRoomListWidget(realm),
|
||||||
|
),
|
||||||
|
SliverPostList(realm: slug),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -398,7 +533,11 @@ class RealmMemberListNotifier extends _$RealmMemberListNotifier
|
|||||||
|
|
||||||
final response = await apiClient.get(
|
final response = await apiClient.get(
|
||||||
'/sphere/realms/$realmSlug/members',
|
'/sphere/realms/$realmSlug/members',
|
||||||
queryParameters: {'offset': offset, 'take': _pageSize},
|
queryParameters: {
|
||||||
|
'offset': offset,
|
||||||
|
'take': _pageSize,
|
||||||
|
'withStatus': true,
|
||||||
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
final total = int.parse(response.headers.value('X-Total') ?? '0');
|
final total = int.parse(response.headers.value('X-Total') ?? '0');
|
||||||
@@ -441,7 +580,7 @@ class RealmMemberNotifier extends StateNotifier<RealmMemberState> {
|
|||||||
try {
|
try {
|
||||||
final response = await _apiClient.get(
|
final response = await _apiClient.get(
|
||||||
'/sphere/realms/$realmSlug/members',
|
'/sphere/realms/$realmSlug/members',
|
||||||
queryParameters: {'offset': offset, 'take': take},
|
queryParameters: {'offset': offset, 'take': take, 'withStatus': true},
|
||||||
);
|
);
|
||||||
|
|
||||||
final total = int.parse(response.headers.value('X-Total') ?? '0');
|
final total = int.parse(response.headers.value('X-Total') ?? '0');
|
||||||
@@ -508,146 +647,154 @@ class _RealmMemberListSheet extends HookConsumerWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget buildMemberListHeader() {
|
||||||
|
return Padding(
|
||||||
|
padding: EdgeInsets.only(top: 16, left: 20, right: 16, bottom: 12),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
'members'.plural(memberState.total),
|
||||||
|
style: Theme.of(context).textTheme.headlineSmall?.copyWith(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
letterSpacing: -0.5,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Spacer(),
|
||||||
|
IconButton(
|
||||||
|
icon: const Icon(Symbols.person_add),
|
||||||
|
onPressed: invitePerson,
|
||||||
|
style: IconButton.styleFrom(minimumSize: const Size(36, 36)),
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
icon: const Icon(Symbols.refresh),
|
||||||
|
onPressed: () {
|
||||||
|
// Refresh both providers
|
||||||
|
memberNotifier.reset();
|
||||||
|
memberNotifier.loadMore();
|
||||||
|
ref.invalidate(memberListProvider);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
icon: const Icon(Symbols.close),
|
||||||
|
onPressed: () => Navigator.pop(context),
|
||||||
|
style: IconButton.styleFrom(minimumSize: const Size(36, 36)),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget buildMemberListContent() {
|
||||||
|
return Expanded(
|
||||||
|
child: PagingHelperView(
|
||||||
|
provider: memberListProvider,
|
||||||
|
futureRefreshable: memberListProvider.future,
|
||||||
|
notifierRefreshable: memberListProvider.notifier,
|
||||||
|
contentBuilder: (data, widgetCount, endItemView) {
|
||||||
|
return ListView.builder(
|
||||||
|
itemCount: widgetCount,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
if (index == data.items.length) {
|
||||||
|
return endItemView;
|
||||||
|
}
|
||||||
|
|
||||||
|
final member = data.items[index];
|
||||||
|
return ListTile(
|
||||||
|
contentPadding: EdgeInsets.only(left: 16, right: 12),
|
||||||
|
leading: ProfilePictureWidget(
|
||||||
|
fileId: member.account!.profile.picture?.id,
|
||||||
|
),
|
||||||
|
title: Row(
|
||||||
|
spacing: 6,
|
||||||
|
children: [
|
||||||
|
Flexible(child: Text(member.account!.nick)),
|
||||||
|
if (member.status != null)
|
||||||
|
AccountStatusLabel(status: member.status!),
|
||||||
|
if (member.joinedAt == null)
|
||||||
|
const Icon(Symbols.pending_actions, size: 20),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
subtitle: Row(
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
member.role >= 100
|
||||||
|
? 'permissionOwner'
|
||||||
|
: member.role >= 50
|
||||||
|
? 'permissionModerator'
|
||||||
|
: 'permissionMember',
|
||||||
|
).tr(),
|
||||||
|
Text('·').bold().padding(horizontal: 6),
|
||||||
|
Expanded(child: Text("@${member.account!.name}")),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
trailing: Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
if ((realmIdentity.value?.role ?? 0) >= 50)
|
||||||
|
IconButton(
|
||||||
|
icon: const Icon(Symbols.edit),
|
||||||
|
onPressed: () {
|
||||||
|
showModalBottomSheet(
|
||||||
|
isScrollControlled: true,
|
||||||
|
context: context,
|
||||||
|
builder:
|
||||||
|
(context) => _RealmMemberRoleSheet(
|
||||||
|
realmSlug: realmSlug,
|
||||||
|
member: member,
|
||||||
|
),
|
||||||
|
).then((value) {
|
||||||
|
if (value != null) {
|
||||||
|
// Refresh both providers
|
||||||
|
memberNotifier.reset();
|
||||||
|
memberNotifier.loadMore();
|
||||||
|
ref.invalidate(memberListProvider);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
if ((realmIdentity.value?.role ?? 0) >= 50)
|
||||||
|
IconButton(
|
||||||
|
icon: const Icon(Symbols.delete),
|
||||||
|
onPressed: () {
|
||||||
|
showConfirmAlert(
|
||||||
|
'removeRealmMemberHint'.tr(),
|
||||||
|
'removeRealmMember'.tr(),
|
||||||
|
).then((confirm) async {
|
||||||
|
if (confirm != true) return;
|
||||||
|
try {
|
||||||
|
final apiClient = ref.watch(apiClientProvider);
|
||||||
|
await apiClient.delete(
|
||||||
|
'/sphere/realms/$realmSlug/members/${member.accountId}',
|
||||||
|
);
|
||||||
|
// Refresh both providers
|
||||||
|
memberNotifier.reset();
|
||||||
|
memberNotifier.loadMore();
|
||||||
|
ref.invalidate(memberListProvider);
|
||||||
|
} catch (err) {
|
||||||
|
showErrorAlert(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
constraints: BoxConstraints(
|
constraints: BoxConstraints(
|
||||||
maxHeight: MediaQuery.of(context).size.height * 0.8,
|
maxHeight: MediaQuery.of(context).size.height * 0.8,
|
||||||
),
|
),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
Padding(
|
buildMemberListHeader(),
|
||||||
padding: EdgeInsets.only(top: 16, left: 20, right: 16, bottom: 12),
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
'members'.plural(memberState.total),
|
|
||||||
style: Theme.of(context).textTheme.headlineSmall?.copyWith(
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
letterSpacing: -0.5,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const Spacer(),
|
|
||||||
IconButton(
|
|
||||||
icon: const Icon(Symbols.person_add),
|
|
||||||
onPressed: invitePerson,
|
|
||||||
style: IconButton.styleFrom(minimumSize: const Size(36, 36)),
|
|
||||||
),
|
|
||||||
IconButton(
|
|
||||||
icon: const Icon(Symbols.refresh),
|
|
||||||
onPressed: () {
|
|
||||||
// Refresh both providers
|
|
||||||
memberNotifier.reset();
|
|
||||||
memberNotifier.loadMore();
|
|
||||||
ref.invalidate(memberListProvider);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
IconButton(
|
|
||||||
icon: const Icon(Symbols.close),
|
|
||||||
onPressed: () => Navigator.pop(context),
|
|
||||||
style: IconButton.styleFrom(minimumSize: const Size(36, 36)),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const Divider(height: 1),
|
const Divider(height: 1),
|
||||||
Expanded(
|
buildMemberListContent(),
|
||||||
child: PagingHelperView(
|
|
||||||
provider: memberListProvider,
|
|
||||||
futureRefreshable: memberListProvider.future,
|
|
||||||
notifierRefreshable: memberListProvider.notifier,
|
|
||||||
contentBuilder: (data, widgetCount, endItemView) {
|
|
||||||
return ListView.builder(
|
|
||||||
itemCount: widgetCount,
|
|
||||||
itemBuilder: (context, index) {
|
|
||||||
if (index == data.items.length) {
|
|
||||||
return endItemView;
|
|
||||||
}
|
|
||||||
|
|
||||||
final member = data.items[index];
|
|
||||||
return ListTile(
|
|
||||||
contentPadding: EdgeInsets.only(left: 16, right: 12),
|
|
||||||
leading: ProfilePictureWidget(
|
|
||||||
fileId: member.account!.profile.picture?.id,
|
|
||||||
),
|
|
||||||
title: Row(
|
|
||||||
spacing: 6,
|
|
||||||
children: [
|
|
||||||
Flexible(child: Text(member.account!.nick)),
|
|
||||||
if (member.joinedAt == null)
|
|
||||||
const Icon(Symbols.pending_actions, size: 20),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
subtitle: Row(
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
member.role >= 100
|
|
||||||
? 'permissionOwner'
|
|
||||||
: member.role >= 50
|
|
||||||
? 'permissionModerator'
|
|
||||||
: 'permissionMember',
|
|
||||||
).tr(),
|
|
||||||
Text('·').bold().padding(horizontal: 6),
|
|
||||||
Expanded(child: Text("@${member.account!.name}")),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
trailing: Row(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
if ((realmIdentity.value?.role ?? 0) >= 50)
|
|
||||||
IconButton(
|
|
||||||
icon: const Icon(Symbols.edit),
|
|
||||||
onPressed: () {
|
|
||||||
showModalBottomSheet(
|
|
||||||
isScrollControlled: true,
|
|
||||||
context: context,
|
|
||||||
builder:
|
|
||||||
(context) => _RealmMemberRoleSheet(
|
|
||||||
realmSlug: realmSlug,
|
|
||||||
member: member,
|
|
||||||
),
|
|
||||||
).then((value) {
|
|
||||||
if (value != null) {
|
|
||||||
// Refresh both providers
|
|
||||||
memberNotifier.reset();
|
|
||||||
memberNotifier.loadMore();
|
|
||||||
ref.invalidate(memberListProvider);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
),
|
|
||||||
if ((realmIdentity.value?.role ?? 0) >= 50)
|
|
||||||
IconButton(
|
|
||||||
icon: const Icon(Symbols.delete),
|
|
||||||
onPressed: () {
|
|
||||||
showConfirmAlert(
|
|
||||||
'removeRealmMemberHint'.tr(),
|
|
||||||
'removeRealmMember'.tr(),
|
|
||||||
).then((confirm) async {
|
|
||||||
if (confirm != true) return;
|
|
||||||
try {
|
|
||||||
final apiClient = ref.watch(
|
|
||||||
apiClientProvider,
|
|
||||||
);
|
|
||||||
await apiClient.delete(
|
|
||||||
'/sphere/realms/$realmSlug/members/${member.accountId}',
|
|
||||||
);
|
|
||||||
// Refresh both providers
|
|
||||||
memberNotifier.reset();
|
|
||||||
memberNotifier.loadMore();
|
|
||||||
ref.invalidate(memberListProvider);
|
|
||||||
} catch (err) {
|
|
||||||
showErrorAlert(err);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@@ -399,7 +399,7 @@ class _RealmChatRoomsProviderElement
|
|||||||
}
|
}
|
||||||
|
|
||||||
String _$realmMemberListNotifierHash() =>
|
String _$realmMemberListNotifierHash() =>
|
||||||
r'022bcef5a90cbae05ff23b937851afc3ef913d42';
|
r'2f88f803b2e61e7287ed8a43025173e56ff6ca3b';
|
||||||
|
|
||||||
abstract class _$RealmMemberListNotifier
|
abstract class _$RealmMemberListNotifier
|
||||||
extends BuildlessAutoDisposeAsyncNotifier<CursorPagingData<SnRealmMember>> {
|
extends BuildlessAutoDisposeAsyncNotifier<CursorPagingData<SnRealmMember>> {
|
||||||
|
@@ -22,6 +22,7 @@ import 'package:island/screens/tabs.dart';
|
|||||||
import 'package:material_symbols_icons/symbols.dart';
|
import 'package:material_symbols_icons/symbols.dart';
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
import 'package:styled_widget/styled_widget.dart';
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
|
import 'package:island/widgets/realm/realm_list_tile.dart';
|
||||||
|
|
||||||
part 'realms.g.dart';
|
part 'realms.g.dart';
|
||||||
|
|
||||||
@@ -95,32 +96,19 @@ class RealmListScreen extends HookConsumerWidget {
|
|||||||
(value) => Column(
|
(value) => Column(
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: ListView.builder(
|
child: ListView.separated(
|
||||||
padding: getTabbedPadding(context),
|
padding: EdgeInsets.only(
|
||||||
|
top: 8,
|
||||||
|
bottom: getTabbedPadding(context).bottom + 8,
|
||||||
|
),
|
||||||
itemCount: value.length,
|
itemCount: value.length,
|
||||||
itemBuilder: (context, item) {
|
itemBuilder: (context, item) {
|
||||||
return ListTile(
|
return ConstrainedBox(
|
||||||
isThreeLine: true,
|
constraints: const BoxConstraints(maxWidth: 540),
|
||||||
leading: ProfilePictureWidget(
|
child: RealmListTile(realm: value[item]),
|
||||||
fileId: value[item].picture?.id,
|
).padding(horizontal: 8).center();
|
||||||
fallbackIcon: Symbols.group,
|
|
||||||
),
|
|
||||||
title: Text(value[item].name),
|
|
||||||
subtitle: Text(value[item].description),
|
|
||||||
onTap: () {
|
|
||||||
context.pushNamed(
|
|
||||||
'realmDetail',
|
|
||||||
pathParameters: {'slug': value[item].slug},
|
|
||||||
);
|
|
||||||
},
|
|
||||||
contentPadding: const EdgeInsets.only(
|
|
||||||
left: 16,
|
|
||||||
right: 14,
|
|
||||||
top: 8,
|
|
||||||
bottom: 8,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
|
separatorBuilder: (_, _) => const Gap(8),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@@ -26,7 +26,12 @@ StreamSubscription<WebSocketPacket> setupNotificationListener(
|
|||||||
final notification = SnNotification.fromJson(pkt.data!);
|
final notification = SnNotification.fromJson(pkt.data!);
|
||||||
showTopSnackBar(
|
showTopSnackBar(
|
||||||
globalOverlay.currentState!,
|
globalOverlay.currentState!,
|
||||||
NotificationCard(notification: notification),
|
Center(
|
||||||
|
child: ConstrainedBox(
|
||||||
|
constraints: const BoxConstraints(maxWidth: 480),
|
||||||
|
child: NotificationCard(notification: notification),
|
||||||
|
),
|
||||||
|
),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
if (notification.meta['action_uri'] != null) {
|
if (notification.meta['action_uri'] != null) {
|
||||||
var uri = notification.meta['action_uri'] as String;
|
var uri = notification.meta['action_uri'] as String;
|
||||||
@@ -53,9 +58,9 @@ StreamSubscription<WebSocketPacket> setupNotificationListener(
|
|||||||
(Platform.isMacOS ||
|
(Platform.isMacOS ||
|
||||||
Platform.isWindows ||
|
Platform.isWindows ||
|
||||||
Platform.isLinux))
|
Platform.isLinux))
|
||||||
? 24
|
? 28
|
||||||
// ignore: use_build_context_synchronously
|
// ignore: use_build_context_synchronously
|
||||||
: MediaQuery.of(context).padding.top + 8,
|
: MediaQuery.of(context).padding.top + 16,
|
||||||
bottom: 16,
|
bottom: 16,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@@ -162,7 +162,7 @@ class AccountSessionSheet extends HookConsumerWidget {
|
|||||||
try {
|
try {
|
||||||
final apiClient = ref.watch(apiClientProvider);
|
final apiClient = ref.watch(apiClientProvider);
|
||||||
await apiClient.patch(
|
await apiClient.patch(
|
||||||
'/accounts/me/devices/$sessionId/label',
|
'/id/accounts/me/devices/$sessionId/label',
|
||||||
data: jsonEncode(label),
|
data: jsonEncode(label),
|
||||||
);
|
);
|
||||||
ref.invalidate(authDevicesProvider);
|
ref.invalidate(authDevicesProvider);
|
||||||
|
@@ -158,3 +158,42 @@ class AccountStatusWidget extends HookConsumerWidget {
|
|||||||
).opacity((status.value?.isCustomized ?? false) ? 1 : 0.85);
|
).opacity((status.value?.isCustomized ?? false) ? 1 : 0.85);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class AccountStatusLabel extends StatelessWidget {
|
||||||
|
final SnAccountStatus status;
|
||||||
|
final TextStyle? style;
|
||||||
|
final int maxLines;
|
||||||
|
final TextOverflow overflow;
|
||||||
|
|
||||||
|
const AccountStatusLabel({
|
||||||
|
super.key,
|
||||||
|
required this.status,
|
||||||
|
this.style,
|
||||||
|
this.maxLines = 1,
|
||||||
|
this.overflow = TextOverflow.ellipsis,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Icon(
|
||||||
|
Symbols.circle,
|
||||||
|
fill: 1,
|
||||||
|
color: status.isOnline ? Colors.green : Colors.grey,
|
||||||
|
size: 14,
|
||||||
|
).padding(right: 4),
|
||||||
|
Flexible(
|
||||||
|
child: Text(
|
||||||
|
status.label,
|
||||||
|
style: style,
|
||||||
|
maxLines: maxLines,
|
||||||
|
overflow: overflow,
|
||||||
|
).fontSize(13),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -11,7 +11,12 @@ export 'content/alert.native.dart'
|
|||||||
void showSnackBar(String message, {SnackBarAction? action}) {
|
void showSnackBar(String message, {SnackBarAction? action}) {
|
||||||
showTopSnackBar(
|
showTopSnackBar(
|
||||||
globalOverlay.currentState!,
|
globalOverlay.currentState!,
|
||||||
Card(child: Text(message).padding(horizontal: 20, vertical: 16)),
|
ConstrainedBox(
|
||||||
|
constraints: const BoxConstraints(maxWidth: 480),
|
||||||
|
child: Center(
|
||||||
|
child: Card(child: Text(message).padding(horizontal: 20, vertical: 16)),
|
||||||
|
),
|
||||||
|
),
|
||||||
snackBarPosition: SnackBarPosition.bottom,
|
snackBarPosition: SnackBarPosition.bottom,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@@ -235,7 +235,11 @@ class PageBackButton extends StatelessWidget {
|
|||||||
return IconButton(
|
return IconButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
onWillPop?.call();
|
onWillPop?.call();
|
||||||
context.pop();
|
if (context.canPop()) {
|
||||||
|
context.pop();
|
||||||
|
} else {
|
||||||
|
context.go('/');
|
||||||
|
}
|
||||||
},
|
},
|
||||||
icon: Icon(
|
icon: Icon(
|
||||||
color: color,
|
color: color,
|
||||||
|
@@ -50,6 +50,6 @@ class AppWrapper extends HookConsumerWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return TourTriggerWidget(child: child);
|
return TourTriggerWidget(key: UniqueKey(), child: child);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -546,6 +546,26 @@ class _MessageItemContent extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
switch (item.type) {
|
switch (item.type) {
|
||||||
|
case 'deleted':
|
||||||
|
return Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Icon(
|
||||||
|
Symbols.delete,
|
||||||
|
size: 14,
|
||||||
|
color: Theme.of(context).colorScheme.onSurfaceVariant.withOpacity(0.6),
|
||||||
|
),
|
||||||
|
const Gap(4),
|
||||||
|
Text(
|
||||||
|
item.content!,
|
||||||
|
style: Theme.of(context).textTheme.bodySmall?.copyWith(
|
||||||
|
color: Theme.of(context).colorScheme.onSurfaceVariant.withOpacity(0.6),
|
||||||
|
fontStyle: FontStyle.italic,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
case 'call.start':
|
case 'call.start':
|
||||||
case 'call.ended':
|
case 'call.ended':
|
||||||
return _MessageContentCall(
|
return _MessageContentCall(
|
||||||
|
@@ -88,6 +88,7 @@ class AttachmentPreview extends HookConsumerWidget {
|
|||||||
final Function? onInsert;
|
final Function? onInsert;
|
||||||
final Function(UniversalFile)? onUpdate;
|
final Function(UniversalFile)? onUpdate;
|
||||||
final Function? onRequestUpload;
|
final Function? onRequestUpload;
|
||||||
|
final bool isCompact;
|
||||||
|
|
||||||
const AttachmentPreview({
|
const AttachmentPreview({
|
||||||
super.key,
|
super.key,
|
||||||
@@ -98,6 +99,7 @@ class AttachmentPreview extends HookConsumerWidget {
|
|||||||
this.onDelete,
|
this.onDelete,
|
||||||
this.onUpdate,
|
this.onUpdate,
|
||||||
this.onInsert,
|
this.onInsert,
|
||||||
|
this.isCompact = false,
|
||||||
});
|
});
|
||||||
|
|
||||||
// GlobalKey for selector
|
// GlobalKey for selector
|
||||||
@@ -361,7 +363,7 @@ class AttachmentPreview extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
).center(),
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
@@ -458,11 +460,12 @@ class AttachmentPreview extends HookConsumerWidget {
|
|||||||
size: 16,
|
size: 16,
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
),
|
),
|
||||||
const Gap(8),
|
if (!isCompact) const Gap(8),
|
||||||
Text(
|
if (!isCompact)
|
||||||
'On-cloud',
|
Text(
|
||||||
style: TextStyle(color: Colors.white),
|
'attachmentOnCloud'.tr(),
|
||||||
),
|
style: TextStyle(color: Colors.white),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
: Row(
|
: Row(
|
||||||
@@ -473,11 +476,12 @@ class AttachmentPreview extends HookConsumerWidget {
|
|||||||
size: 16,
|
size: 16,
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
),
|
),
|
||||||
const Gap(8),
|
if (!isCompact) const Gap(8),
|
||||||
Text(
|
if (!isCompact)
|
||||||
'On-device',
|
Text(
|
||||||
style: TextStyle(color: Colors.white),
|
'attachmentOnDevice'.tr(),
|
||||||
),
|
style: TextStyle(color: Colors.white),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@@ -1,9 +1,11 @@
|
|||||||
|
import 'dart:convert';
|
||||||
import 'dart:math' as math;
|
import 'dart:math' as math;
|
||||||
import 'dart:ui';
|
import 'dart:ui';
|
||||||
|
|
||||||
import 'package:dismissible_page/dismissible_page.dart';
|
import 'package:dismissible_page/dismissible_page.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_blurhash/flutter_blurhash.dart';
|
import 'package:flutter_blurhash/flutter_blurhash.dart';
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
import 'package:gap/gap.dart';
|
import 'package:gap/gap.dart';
|
||||||
@@ -326,7 +328,11 @@ class CloudFileZoomIn extends HookConsumerWidget {
|
|||||||
|
|
||||||
// Create a temporary file to save the image
|
// Create a temporary file to save the image
|
||||||
final tempDir = await getTemporaryDirectory();
|
final tempDir = await getTemporaryDirectory();
|
||||||
final filePath = '${tempDir.path}/${item.id}.${extension(item.name)}';
|
var extName = extension(item.name).trim();
|
||||||
|
if (extName.isEmpty) {
|
||||||
|
extName = item.mimeType?.split('/').lastOrNull ?? 'jpeg';
|
||||||
|
}
|
||||||
|
final filePath = '${tempDir.path}/${item.id}.$extName';
|
||||||
|
|
||||||
await client.download(
|
await client.download(
|
||||||
'/drive/files/${item.id}',
|
'/drive/files/${item.id}',
|
||||||
@@ -342,39 +348,6 @@ class CloudFileZoomIn extends HookConsumerWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget buildInfoRow(IconData icon, String label, String value) {
|
|
||||||
return Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 24),
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
Icon(
|
|
||||||
icon,
|
|
||||||
size: 20,
|
|
||||||
color: Theme.of(context).colorScheme.onSurface,
|
|
||||||
),
|
|
||||||
const SizedBox(width: 12),
|
|
||||||
Text(
|
|
||||||
label,
|
|
||||||
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
|
|
||||||
color: Theme.of(context).textTheme.bodySmall?.color,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const Spacer(),
|
|
||||||
Flexible(
|
|
||||||
child: Text(
|
|
||||||
value,
|
|
||||||
style: Theme.of(
|
|
||||||
context,
|
|
||||||
).textTheme.bodyMedium?.copyWith(fontWeight: FontWeight.w500),
|
|
||||||
textAlign: TextAlign.end,
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
String formatFileSize(int bytes) {
|
String formatFileSize(int bytes) {
|
||||||
if (bytes <= 0) return '0 B';
|
if (bytes <= 0) return '0 B';
|
||||||
if (bytes < 1024) return '$bytes B';
|
if (bytes < 1024) return '$bytes B';
|
||||||
@@ -400,57 +373,247 @@ class CloudFileZoomIn extends HookConsumerWidget {
|
|||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
buildInfoRow(Icons.description, 'Name', item.name),
|
Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Text('mimeType').tr(),
|
||||||
|
Text(
|
||||||
|
item.mimeType ?? 'unknown'.tr(),
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: theme.textTheme.titleMedium?.copyWith(
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(height: 28, child: const VerticalDivider()),
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Text('fileSize').tr(),
|
||||||
|
Text(
|
||||||
|
formatFileSize(item.size),
|
||||||
|
style: theme.textTheme.titleMedium?.copyWith(
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (item.hash != null)
|
||||||
|
SizedBox(height: 28, child: const VerticalDivider()),
|
||||||
|
if (item.hash != null)
|
||||||
|
Expanded(
|
||||||
|
child: GestureDetector(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Text('fileHash').tr(),
|
||||||
|
Text(
|
||||||
|
'${item.hash!.substring(0, 6)}...',
|
||||||
|
style: theme.textTheme.titleMedium
|
||||||
|
?.copyWith(fontWeight: FontWeight.bold),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
onLongPress: () {
|
||||||
|
Clipboard.setData(
|
||||||
|
ClipboardData(text: item.hash!),
|
||||||
|
);
|
||||||
|
showSnackBar('File hash copied to clipboard');
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
).padding(horizontal: 24, vertical: 16),
|
||||||
const Divider(height: 1),
|
const Divider(height: 1),
|
||||||
buildInfoRow(
|
ListTile(
|
||||||
Icons.storage,
|
leading: const Icon(Icons.file_present),
|
||||||
'Size',
|
title: Text('Name').tr(),
|
||||||
formatFileSize(item.size),
|
subtitle: Text(
|
||||||
),
|
item.name,
|
||||||
const Divider(height: 1),
|
maxLines: 1,
|
||||||
buildInfoRow(
|
overflow: TextOverflow.ellipsis,
|
||||||
Icons.category,
|
),
|
||||||
'Type',
|
contentPadding: EdgeInsets.symmetric(horizontal: 24),
|
||||||
item.mimeType?.toUpperCase() ?? 'UNKNOWN',
|
trailing: IconButton(
|
||||||
|
icon: const Icon(Icons.copy),
|
||||||
|
onPressed: () {
|
||||||
|
Clipboard.setData(ClipboardData(text: item.name));
|
||||||
|
showSnackBar('File name copied to clipboard');
|
||||||
|
},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
if (exifData.isNotEmpty) ...[
|
if (exifData.isNotEmpty) ...[
|
||||||
const SizedBox(height: 16),
|
const Divider(height: 1),
|
||||||
Text(
|
Theme(
|
||||||
'EXIF Data',
|
data: theme.copyWith(dividerColor: Colors.transparent),
|
||||||
style: theme.textTheme.titleMedium?.copyWith(
|
child: ExpansionTile(
|
||||||
fontWeight: FontWeight.bold,
|
tilePadding: const EdgeInsets.symmetric(
|
||||||
),
|
horizontal: 24,
|
||||||
).padding(horizontal: 24),
|
),
|
||||||
const SizedBox(height: 8),
|
title: Text(
|
||||||
Column(
|
'exifData'.tr(),
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
style: theme.textTheme.titleMedium?.copyWith(
|
||||||
children: [
|
fontWeight: FontWeight.bold,
|
||||||
...exifData.entries.map(
|
),
|
||||||
(entry) => Padding(
|
),
|
||||||
padding: const EdgeInsets.symmetric(vertical: 4),
|
children: [
|
||||||
child: Row(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
...exifData.entries.map(
|
||||||
'• ${entry.key.contains('-') ? entry.key.split('-').last : entry.key}: ',
|
(entry) => ListTile(
|
||||||
style: theme.textTheme.bodyMedium?.copyWith(
|
dense: true,
|
||||||
fontWeight: FontWeight.w500,
|
contentPadding: EdgeInsets.symmetric(
|
||||||
|
horizontal: 24,
|
||||||
),
|
),
|
||||||
),
|
title:
|
||||||
Expanded(
|
Text(
|
||||||
child: Text(
|
entry.key.contains('-')
|
||||||
|
? entry.key.split('-').last
|
||||||
|
: entry.key,
|
||||||
|
style: theme.textTheme.bodyMedium
|
||||||
|
?.copyWith(
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
),
|
||||||
|
).bold(),
|
||||||
|
subtitle: Text(
|
||||||
'${entry.value}'.isNotEmpty
|
'${entry.value}'.isNotEmpty
|
||||||
? '${entry.value}'
|
? '${entry.value}'
|
||||||
: 'N/A',
|
: 'N/A',
|
||||||
style: theme.textTheme.bodyMedium,
|
style: theme.textTheme.bodyMedium,
|
||||||
),
|
),
|
||||||
|
onTap: () {
|
||||||
|
Clipboard.setData(
|
||||||
|
ClipboardData(text: '${entry.value}'),
|
||||||
|
);
|
||||||
|
showSnackBar('Value copied to clipboard');
|
||||||
|
},
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
),
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
if (item.fileMeta != null && item.fileMeta!.isNotEmpty) ...[
|
||||||
|
const Divider(height: 1),
|
||||||
|
Theme(
|
||||||
|
data: theme.copyWith(dividerColor: Colors.transparent),
|
||||||
|
child: ExpansionTile(
|
||||||
|
tilePadding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 24,
|
||||||
|
),
|
||||||
|
title: Text(
|
||||||
|
'File Metadata',
|
||||||
|
style: theme.textTheme.titleMedium?.copyWith(
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
children: [
|
||||||
).padding(horizontal: 24),
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
...item.fileMeta!.entries.map(
|
||||||
|
(entry) => ListTile(
|
||||||
|
dense: true,
|
||||||
|
contentPadding: EdgeInsets.symmetric(
|
||||||
|
horizontal: 24,
|
||||||
|
),
|
||||||
|
title:
|
||||||
|
Text(
|
||||||
|
entry.key,
|
||||||
|
style: theme.textTheme.bodyMedium
|
||||||
|
?.copyWith(
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
),
|
||||||
|
).bold(),
|
||||||
|
subtitle: Text(
|
||||||
|
jsonEncode(entry.value),
|
||||||
|
style: theme.textTheme.bodyMedium,
|
||||||
|
maxLines: 3,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
onTap: () {
|
||||||
|
Clipboard.setData(
|
||||||
|
ClipboardData(
|
||||||
|
text: jsonEncode(entry.value),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
showSnackBar('Value copied to clipboard');
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
if (item.userMeta != null && item.userMeta!.isNotEmpty) ...[
|
||||||
|
const Divider(height: 1),
|
||||||
|
Theme(
|
||||||
|
data: theme.copyWith(dividerColor: Colors.transparent),
|
||||||
|
child: ExpansionTile(
|
||||||
|
tilePadding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 24,
|
||||||
|
),
|
||||||
|
title: Text(
|
||||||
|
'User Metadata',
|
||||||
|
style: theme.textTheme.titleMedium?.copyWith(
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
children: [
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
...item.userMeta!.entries.map(
|
||||||
|
(entry) => ListTile(
|
||||||
|
dense: true,
|
||||||
|
contentPadding: EdgeInsets.symmetric(
|
||||||
|
horizontal: 24,
|
||||||
|
),
|
||||||
|
title:
|
||||||
|
Text(
|
||||||
|
entry.key,
|
||||||
|
style: theme.textTheme.bodyMedium
|
||||||
|
?.copyWith(
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
),
|
||||||
|
).bold(),
|
||||||
|
subtitle: Text(
|
||||||
|
jsonEncode(entry.value),
|
||||||
|
style: theme.textTheme.bodyMedium,
|
||||||
|
maxLines: 3,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
onTap: () {
|
||||||
|
Clipboard.setData(
|
||||||
|
ClipboardData(
|
||||||
|
text: jsonEncode(entry.value),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
showSnackBar('Value copied to clipboard');
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
],
|
],
|
||||||
|
@@ -256,6 +256,7 @@ class ProfilePictureWidget extends ConsumerWidget {
|
|||||||
final String? fileId;
|
final String? fileId;
|
||||||
final SnCloudFile? file;
|
final SnCloudFile? file;
|
||||||
final double radius;
|
final double radius;
|
||||||
|
final double? borderRadius;
|
||||||
final IconData? fallbackIcon;
|
final IconData? fallbackIcon;
|
||||||
final Color? fallbackColor;
|
final Color? fallbackColor;
|
||||||
const ProfilePictureWidget({
|
const ProfilePictureWidget({
|
||||||
@@ -263,6 +264,7 @@ class ProfilePictureWidget extends ConsumerWidget {
|
|||||||
this.fileId,
|
this.fileId,
|
||||||
this.file,
|
this.file,
|
||||||
this.radius = 20,
|
this.radius = 20,
|
||||||
|
this.borderRadius,
|
||||||
this.fallbackIcon,
|
this.fallbackIcon,
|
||||||
this.fallbackColor,
|
this.fallbackColor,
|
||||||
});
|
});
|
||||||
@@ -273,7 +275,10 @@ class ProfilePictureWidget extends ConsumerWidget {
|
|||||||
final uri = '$serverUrl/drive/files/${file?.id ?? fileId}';
|
final uri = '$serverUrl/drive/files/${file?.id ?? fileId}';
|
||||||
|
|
||||||
return ClipRRect(
|
return ClipRRect(
|
||||||
borderRadius: BorderRadius.all(Radius.circular(radius)),
|
borderRadius:
|
||||||
|
borderRadius == null
|
||||||
|
? BorderRadius.all(Radius.circular(radius))
|
||||||
|
: BorderRadius.all(Radius.circular(borderRadius!)),
|
||||||
child: Container(
|
child: Container(
|
||||||
width: radius * 2,
|
width: radius * 2,
|
||||||
height: radius * 2,
|
height: radius * 2,
|
||||||
|
@@ -57,11 +57,11 @@ class EmbedLinkWidget extends StatelessWidget {
|
|||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
// Favicon
|
// Favicon
|
||||||
if (link.faviconUrl.isNotEmpty) ...[
|
if (link.faviconUrl?.isNotEmpty ?? false) ...[
|
||||||
ClipRRect(
|
ClipRRect(
|
||||||
borderRadius: BorderRadius.circular(4),
|
borderRadius: BorderRadius.circular(4),
|
||||||
child: UniversalImage(
|
child: UniversalImage(
|
||||||
uri: link.faviconUrl,
|
uri: link.faviconUrl!,
|
||||||
width: 16,
|
width: 16,
|
||||||
height: 16,
|
height: 16,
|
||||||
fit: BoxFit.cover,
|
fit: BoxFit.cover,
|
||||||
@@ -80,8 +80,8 @@ class EmbedLinkWidget extends StatelessWidget {
|
|||||||
// Site name
|
// Site name
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Text(
|
child: Text(
|
||||||
link.siteName.isNotEmpty
|
(link.siteName?.isNotEmpty ?? false)
|
||||||
? link.siteName
|
? link.siteName!
|
||||||
: Uri.parse(link.url).host,
|
: Uri.parse(link.url).host,
|
||||||
style: theme.textTheme.bodySmall?.copyWith(
|
style: theme.textTheme.bodySmall?.copyWith(
|
||||||
color: colorScheme.onSurfaceVariant,
|
color: colorScheme.onSurfaceVariant,
|
||||||
|
@@ -51,9 +51,13 @@ class UniversalImage extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
errorWidget: (context, url, error) {
|
errorWidget: (context, url, error) {
|
||||||
return const Center(
|
return Image.asset(
|
||||||
child: Icon(Icons.broken_image, color: Colors.white, size: 16),
|
'assets/images/media-offline.png',
|
||||||
|
fit: BoxFit.cover,
|
||||||
);
|
);
|
||||||
|
// return const Center(
|
||||||
|
// child: Icon(Icons.broken_image, color: Colors.white, size: 16),
|
||||||
|
// );
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@@ -183,9 +183,15 @@ class MarkdownTextContent extends HookConsumerWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
final content = ConstrainedBox(
|
final content = ClipRRect(
|
||||||
constraints: BoxConstraints(maxHeight: 360),
|
borderRadius: const BorderRadius.all(Radius.circular(8)),
|
||||||
child: UniversalImage(uri: uri.toString(), fit: BoxFit.contain),
|
child: ConstrainedBox(
|
||||||
|
constraints: BoxConstraints(maxHeight: 360),
|
||||||
|
child: UniversalImage(
|
||||||
|
uri: uri.toString(),
|
||||||
|
fit: BoxFit.contain,
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
return content;
|
return content;
|
||||||
},
|
},
|
||||||
|
@@ -73,6 +73,7 @@ class _UniversalVideoState extends ConsumerState<UniversalVideo> {
|
|||||||
return Video(
|
return Video(
|
||||||
controller: _videoController!,
|
controller: _videoController!,
|
||||||
aspectRatio: widget.aspectRatio != 1 ? widget.aspectRatio : null,
|
aspectRatio: widget.aspectRatio != 1 ? widget.aspectRatio : null,
|
||||||
|
fit: BoxFit.contain,
|
||||||
controls:
|
controls:
|
||||||
!kIsWeb && (Platform.isAndroid || Platform.isIOS)
|
!kIsWeb && (Platform.isAndroid || Platform.isIOS)
|
||||||
? MaterialVideoControls
|
? MaterialVideoControls
|
||||||
|
@@ -5,11 +5,15 @@ import 'package:flutter_hooks/flutter_hooks.dart';
|
|||||||
import 'package:gap/gap.dart';
|
import 'package:gap/gap.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:island/models/post_category.dart';
|
import 'package:island/models/post_category.dart';
|
||||||
|
import 'package:island/models/realm.dart';
|
||||||
import 'package:island/pods/network.dart';
|
import 'package:island/pods/network.dart';
|
||||||
|
import 'package:island/screens/realm/realms.dart';
|
||||||
|
import 'package:island/widgets/content/cloud_files.dart';
|
||||||
import 'package:island/widgets/content/sheet.dart';
|
import 'package:island/widgets/content/sheet.dart';
|
||||||
import 'package:island/widgets/post/compose_shared.dart';
|
import 'package:island/widgets/post/compose_shared.dart';
|
||||||
import 'package:material_symbols_icons/symbols.dart';
|
import 'package:material_symbols_icons/symbols.dart';
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
import 'package:textfield_tags/textfield_tags.dart';
|
import 'package:textfield_tags/textfield_tags.dart';
|
||||||
|
|
||||||
part 'compose_settings_sheet.g.dart';
|
part 'compose_settings_sheet.g.dart';
|
||||||
@@ -129,7 +133,9 @@ class ComposeSettingsSheet extends HookConsumerWidget {
|
|||||||
// Listen to visibility changes to trigger rebuilds
|
// Listen to visibility changes to trigger rebuilds
|
||||||
final currentVisibility = useValueListenable(state.visibility);
|
final currentVisibility = useValueListenable(state.visibility);
|
||||||
final currentCategories = useValueListenable(state.categories);
|
final currentCategories = useValueListenable(state.categories);
|
||||||
|
final currentRealm = useValueListenable(state.realm);
|
||||||
final postCategories = ref.watch(postCategoriesProvider);
|
final postCategories = ref.watch(postCategoriesProvider);
|
||||||
|
final userRealms = ref.watch(realmsJoinedProvider);
|
||||||
|
|
||||||
IconData getVisibilityIcon(int visibilityValue) {
|
IconData getVisibilityIcon(int visibilityValue) {
|
||||||
switch (visibilityValue) {
|
switch (visibilityValue) {
|
||||||
@@ -223,6 +229,24 @@ class ComposeSettingsSheet extends HookConsumerWidget {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
spacing: 16,
|
spacing: 16,
|
||||||
children: [
|
children: [
|
||||||
|
// Slug field
|
||||||
|
TextField(
|
||||||
|
controller: state.slugController,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
labelText: 'postSlug'.tr(),
|
||||||
|
hintText: 'postSlugHint'.tr(),
|
||||||
|
contentPadding: const EdgeInsets.symmetric(
|
||||||
|
vertical: 9,
|
||||||
|
horizontal: 16,
|
||||||
|
),
|
||||||
|
border: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onTapOutside:
|
||||||
|
(_) => FocusManager.instance.primaryFocus?.unfocus(),
|
||||||
|
),
|
||||||
|
|
||||||
// Tags field
|
// Tags field
|
||||||
TextFieldTags(
|
TextFieldTags(
|
||||||
textfieldTagsController: state.tagsController,
|
textfieldTagsController: state.tagsController,
|
||||||
@@ -244,7 +268,6 @@ class ComposeSettingsSheet extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
|
|
||||||
// Categories field
|
// Categories field
|
||||||
// FIXME: Sometimes the entire dropdown crashes: 'package:flutter/src/rendering/stack.dart': Failed assertion: line 799 pos 12: 'firstChild == null || child != null': is not true.
|
|
||||||
DropdownButtonFormField2<SnPostCategory>(
|
DropdownButtonFormField2<SnPostCategory>(
|
||||||
isExpanded: true,
|
isExpanded: true,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
@@ -306,7 +329,7 @@ class ComposeSettingsSheet extends HookConsumerWidget {
|
|||||||
value: currentCategories.isEmpty ? null : currentCategories.last,
|
value: currentCategories.isEmpty ? null : currentCategories.last,
|
||||||
onChanged: (_) {},
|
onChanged: (_) {},
|
||||||
selectedItemBuilder: (context) {
|
selectedItemBuilder: (context) {
|
||||||
return currentCategories.map((item) {
|
return (postCategories.value ?? []).map((item) {
|
||||||
return SingleChildScrollView(
|
return SingleChildScrollView(
|
||||||
scrollDirection: Axis.horizontal,
|
scrollDirection: Axis.horizontal,
|
||||||
child: Row(
|
child: Row(
|
||||||
@@ -335,12 +358,89 @@ class ComposeSettingsSheet extends HookConsumerWidget {
|
|||||||
);
|
);
|
||||||
}).toList();
|
}).toList();
|
||||||
},
|
},
|
||||||
|
buttonStyleData: const ButtonStyleData(
|
||||||
|
padding: EdgeInsets.only(left: 16, right: 8),
|
||||||
|
height: 38,
|
||||||
|
),
|
||||||
|
menuItemStyleData: const MenuItemStyleData(
|
||||||
|
height: 38,
|
||||||
|
padding: EdgeInsets.zero,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
// Realm selection
|
||||||
|
DropdownButtonFormField2<SnRealm?>(
|
||||||
|
isExpanded: true,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
contentPadding: const EdgeInsets.symmetric(vertical: 9),
|
||||||
|
border: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
hint: Text('realm'.tr(), style: const TextStyle(fontSize: 15)),
|
||||||
|
items: [
|
||||||
|
DropdownMenuItem<SnRealm?>(
|
||||||
|
value: null,
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
const CircleAvatar(
|
||||||
|
radius: 16,
|
||||||
|
child: Icon(Symbols.link_off, fill: 1),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 12),
|
||||||
|
Text('postUnlinkRealm').tr(),
|
||||||
|
],
|
||||||
|
).padding(left: 16, right: 8),
|
||||||
|
),
|
||||||
|
if (userRealms.hasValue)
|
||||||
|
...(userRealms.value ?? []).map(
|
||||||
|
(realm) => DropdownMenuItem<SnRealm?>(
|
||||||
|
value: realm,
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
ProfilePictureWidget(
|
||||||
|
fileId: realm.picture?.id,
|
||||||
|
fallbackIcon: Symbols.workspaces,
|
||||||
|
radius: 16,
|
||||||
|
),
|
||||||
|
const SizedBox(width: 12),
|
||||||
|
Text(realm.name),
|
||||||
|
],
|
||||||
|
).padding(left: 16, right: 8),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
value: currentRealm,
|
||||||
|
onChanged: (value) {
|
||||||
|
state.realm.value = value;
|
||||||
|
},
|
||||||
|
selectedItemBuilder: (context) {
|
||||||
|
return (userRealms.value ?? []).map((_) {
|
||||||
|
return Row(
|
||||||
|
children: [
|
||||||
|
if (currentRealm == null)
|
||||||
|
const CircleAvatar(
|
||||||
|
radius: 16,
|
||||||
|
child: Icon(Symbols.link_off, fill: 1),
|
||||||
|
)
|
||||||
|
else
|
||||||
|
ProfilePictureWidget(
|
||||||
|
fileId: currentRealm.picture?.id,
|
||||||
|
fallbackIcon: Symbols.workspaces,
|
||||||
|
radius: 16,
|
||||||
|
),
|
||||||
|
const SizedBox(width: 12),
|
||||||
|
Text(currentRealm?.name ?? 'postUnlinkRealm'.tr()),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}).toList();
|
||||||
|
},
|
||||||
buttonStyleData: const ButtonStyleData(
|
buttonStyleData: const ButtonStyleData(
|
||||||
padding: EdgeInsets.only(left: 16, right: 8),
|
padding: EdgeInsets.only(left: 16, right: 8),
|
||||||
height: 40,
|
height: 40,
|
||||||
),
|
),
|
||||||
menuItemStyleData: const MenuItemStyleData(
|
menuItemStyleData: const MenuItemStyleData(
|
||||||
height: 40,
|
height: 56,
|
||||||
padding: EdgeInsets.zero,
|
padding: EdgeInsets.zero,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@@ -9,6 +9,7 @@ import 'package:island/models/file.dart';
|
|||||||
import 'package:island/models/post.dart';
|
import 'package:island/models/post.dart';
|
||||||
import 'package:island/models/post_category.dart';
|
import 'package:island/models/post_category.dart';
|
||||||
import 'package:island/models/publisher.dart';
|
import 'package:island/models/publisher.dart';
|
||||||
|
import 'package:island/models/realm.dart';
|
||||||
import 'package:island/pods/config.dart';
|
import 'package:island/pods/config.dart';
|
||||||
import 'package:island/pods/network.dart';
|
import 'package:island/pods/network.dart';
|
||||||
import 'package:island/services/file.dart';
|
import 'package:island/services/file.dart';
|
||||||
@@ -26,6 +27,7 @@ class ComposeState {
|
|||||||
final TextEditingController titleController;
|
final TextEditingController titleController;
|
||||||
final TextEditingController descriptionController;
|
final TextEditingController descriptionController;
|
||||||
final TextEditingController contentController;
|
final TextEditingController contentController;
|
||||||
|
final TextEditingController slugController;
|
||||||
final ValueNotifier<int> visibility;
|
final ValueNotifier<int> visibility;
|
||||||
final ValueNotifier<List<UniversalFile>> attachments;
|
final ValueNotifier<List<UniversalFile>> attachments;
|
||||||
final ValueNotifier<Map<int, double>> attachmentProgress;
|
final ValueNotifier<Map<int, double>> attachmentProgress;
|
||||||
@@ -33,6 +35,7 @@ class ComposeState {
|
|||||||
final ValueNotifier<bool> submitting;
|
final ValueNotifier<bool> submitting;
|
||||||
final ValueNotifier<List<SnPostCategory>> categories;
|
final ValueNotifier<List<SnPostCategory>> categories;
|
||||||
StringTagController tagsController;
|
StringTagController tagsController;
|
||||||
|
final ValueNotifier<SnRealm?> realm;
|
||||||
final String draftId;
|
final String draftId;
|
||||||
int postType;
|
int postType;
|
||||||
// Linked poll id for this compose session (nullable)
|
// Linked poll id for this compose session (nullable)
|
||||||
@@ -43,6 +46,7 @@ class ComposeState {
|
|||||||
required this.titleController,
|
required this.titleController,
|
||||||
required this.descriptionController,
|
required this.descriptionController,
|
||||||
required this.contentController,
|
required this.contentController,
|
||||||
|
required this.slugController,
|
||||||
required this.visibility,
|
required this.visibility,
|
||||||
required this.attachments,
|
required this.attachments,
|
||||||
required this.attachmentProgress,
|
required this.attachmentProgress,
|
||||||
@@ -50,6 +54,7 @@ class ComposeState {
|
|||||||
required this.submitting,
|
required this.submitting,
|
||||||
required this.tagsController,
|
required this.tagsController,
|
||||||
required this.categories,
|
required this.categories,
|
||||||
|
required this.realm,
|
||||||
required this.draftId,
|
required this.draftId,
|
||||||
this.postType = 0,
|
this.postType = 0,
|
||||||
String? pollId,
|
String? pollId,
|
||||||
@@ -104,6 +109,7 @@ class ComposeLogic {
|
|||||||
text: originalPost?.description,
|
text: originalPost?.description,
|
||||||
),
|
),
|
||||||
contentController: TextEditingController(text: originalPost?.content),
|
contentController: TextEditingController(text: originalPost?.content),
|
||||||
|
slugController: TextEditingController(text: originalPost?.slug),
|
||||||
visibility: ValueNotifier<int>(originalPost?.visibility ?? 0),
|
visibility: ValueNotifier<int>(originalPost?.visibility ?? 0),
|
||||||
submitting: ValueNotifier<bool>(false),
|
submitting: ValueNotifier<bool>(false),
|
||||||
attachmentProgress: ValueNotifier<Map<int, double>>({}),
|
attachmentProgress: ValueNotifier<Map<int, double>>({}),
|
||||||
@@ -112,6 +118,7 @@ class ComposeLogic {
|
|||||||
categories: ValueNotifier<List<SnPostCategory>>(
|
categories: ValueNotifier<List<SnPostCategory>>(
|
||||||
originalPost?.categories ?? [],
|
originalPost?.categories ?? [],
|
||||||
),
|
),
|
||||||
|
realm: ValueNotifier(originalPost?.realm),
|
||||||
draftId: id,
|
draftId: id,
|
||||||
postType: postType,
|
postType: postType,
|
||||||
// initialize without poll by default
|
// initialize without poll by default
|
||||||
@@ -135,12 +142,14 @@ class ComposeLogic {
|
|||||||
titleController: TextEditingController(text: draft.title),
|
titleController: TextEditingController(text: draft.title),
|
||||||
descriptionController: TextEditingController(text: draft.description),
|
descriptionController: TextEditingController(text: draft.description),
|
||||||
contentController: TextEditingController(text: draft.content),
|
contentController: TextEditingController(text: draft.content),
|
||||||
|
slugController: TextEditingController(text: draft.slug),
|
||||||
visibility: ValueNotifier<int>(draft.visibility),
|
visibility: ValueNotifier<int>(draft.visibility),
|
||||||
submitting: ValueNotifier<bool>(false),
|
submitting: ValueNotifier<bool>(false),
|
||||||
attachmentProgress: ValueNotifier<Map<int, double>>({}),
|
attachmentProgress: ValueNotifier<Map<int, double>>({}),
|
||||||
currentPublisher: ValueNotifier<SnPublisher?>(null),
|
currentPublisher: ValueNotifier<SnPublisher?>(null),
|
||||||
tagsController: tagsController,
|
tagsController: tagsController,
|
||||||
categories: ValueNotifier<List<SnPostCategory>>([]),
|
categories: ValueNotifier<List<SnPostCategory>>([]),
|
||||||
|
realm: ValueNotifier(null),
|
||||||
draftId: draft.id,
|
draftId: draft.id,
|
||||||
postType: postType,
|
postType: postType,
|
||||||
pollId: null,
|
pollId: null,
|
||||||
@@ -629,6 +638,8 @@ class ComposeLogic {
|
|||||||
'title': state.titleController.text,
|
'title': state.titleController.text,
|
||||||
'description': state.descriptionController.text,
|
'description': state.descriptionController.text,
|
||||||
'content': state.contentController.text,
|
'content': state.contentController.text,
|
||||||
|
if (state.slugController.text.isNotEmpty)
|
||||||
|
'slug': state.slugController.text,
|
||||||
'visibility': state.visibility.value,
|
'visibility': state.visibility.value,
|
||||||
'attachments':
|
'attachments':
|
||||||
state.attachments.value
|
state.attachments.value
|
||||||
@@ -640,6 +651,7 @@ class ComposeLogic {
|
|||||||
if (forwardedPost != null) 'forwarded_post_id': forwardedPost.id,
|
if (forwardedPost != null) 'forwarded_post_id': forwardedPost.id,
|
||||||
'tags': state.tagsController.getTags,
|
'tags': state.tagsController.getTags,
|
||||||
'categories': state.categories.value.map((e) => e.slug).toList(),
|
'categories': state.categories.value.map((e) => e.slug).toList(),
|
||||||
|
if (state.realm.value != null) 'realm_id': state.realm.value?.id,
|
||||||
if (state.pollId.value != null) 'poll_id': state.pollId.value,
|
if (state.pollId.value != null) 'poll_id': state.pollId.value,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -733,6 +745,7 @@ class ComposeLogic {
|
|||||||
state.currentPublisher.dispose();
|
state.currentPublisher.dispose();
|
||||||
state.tagsController.dispose();
|
state.tagsController.dispose();
|
||||||
state.categories.dispose();
|
state.categories.dispose();
|
||||||
|
state.realm.dispose();
|
||||||
state.pollId.dispose();
|
state.pollId.dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -7,6 +7,7 @@ import 'package:material_symbols_icons/symbols.dart';
|
|||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
import 'package:island/widgets/post/post_item.dart';
|
import 'package:island/widgets/post/post_item.dart';
|
||||||
import 'package:styled_widget/styled_widget.dart';
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
|
import 'package:island/pods/config.dart'; // Import config.dart for shared preferences keys and provider
|
||||||
|
|
||||||
part 'post_featured.g.dart';
|
part 'post_featured.g.dart';
|
||||||
|
|
||||||
@@ -25,7 +26,13 @@ class PostFeaturedList extends HookConsumerWidget {
|
|||||||
final featuredPostsAsync = ref.watch(featuredPostsProvider);
|
final featuredPostsAsync = ref.watch(featuredPostsProvider);
|
||||||
|
|
||||||
final pageViewController = usePageController();
|
final pageViewController = usePageController();
|
||||||
|
final prefs = ref.watch(sharedPreferencesProvider);
|
||||||
final pageViewCurrent = useState(0);
|
final pageViewCurrent = useState(0);
|
||||||
|
final previousFirstPostId = useState<String?>(null);
|
||||||
|
final storedCollapsedId = useState<String?>(
|
||||||
|
prefs.getString(kFeaturedPostsCollapsedId),
|
||||||
|
);
|
||||||
|
final isCollapsed = useState(false);
|
||||||
|
|
||||||
useEffect(() {
|
useEffect(() {
|
||||||
pageViewController.addListener(() {
|
pageViewController.addListener(() {
|
||||||
@@ -34,6 +41,59 @@ class PostFeaturedList extends HookConsumerWidget {
|
|||||||
return null;
|
return null;
|
||||||
}, [pageViewController]);
|
}, [pageViewController]);
|
||||||
|
|
||||||
|
// Log isCollapsed state changes
|
||||||
|
useEffect(() {
|
||||||
|
debugPrint(
|
||||||
|
'PostFeaturedList: isCollapsed changed to ${isCollapsed.value}',
|
||||||
|
);
|
||||||
|
return null;
|
||||||
|
}, [isCollapsed.value]);
|
||||||
|
|
||||||
|
useEffect(() {
|
||||||
|
if (featuredPostsAsync.hasValue && featuredPostsAsync.value!.isNotEmpty) {
|
||||||
|
final currentFirstPostId = featuredPostsAsync.value!.first.id;
|
||||||
|
debugPrint(
|
||||||
|
'PostFeaturedList: Current first post ID: $currentFirstPostId',
|
||||||
|
);
|
||||||
|
debugPrint(
|
||||||
|
'PostFeaturedList: Previous first post ID: ${previousFirstPostId.value}',
|
||||||
|
);
|
||||||
|
debugPrint(
|
||||||
|
'PostFeaturedList: Stored collapsed ID: ${storedCollapsedId.value}',
|
||||||
|
);
|
||||||
|
|
||||||
|
if (previousFirstPostId.value == null) {
|
||||||
|
// Initial load
|
||||||
|
previousFirstPostId.value = currentFirstPostId;
|
||||||
|
isCollapsed.value = (storedCollapsedId.value == currentFirstPostId);
|
||||||
|
debugPrint(
|
||||||
|
'PostFeaturedList: Initial load. isCollapsed set to ${isCollapsed.value}',
|
||||||
|
);
|
||||||
|
} else if (previousFirstPostId.value != currentFirstPostId) {
|
||||||
|
// First post changed, expand by default
|
||||||
|
previousFirstPostId.value = currentFirstPostId;
|
||||||
|
isCollapsed.value = false;
|
||||||
|
prefs.remove(
|
||||||
|
kFeaturedPostsCollapsedId,
|
||||||
|
); // Clear stored ID if post changes
|
||||||
|
debugPrint(
|
||||||
|
'PostFeaturedList: First post changed. isCollapsed set to false.',
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// Same first post, maintain current collapse state
|
||||||
|
// No change needed for isCollapsed.value unless manually toggled
|
||||||
|
debugPrint(
|
||||||
|
'PostFeaturedList: Same first post. Maintaining current collapse state.',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
debugPrint(
|
||||||
|
'PostFeaturedList: featuredPostsAsync has no value or is empty.',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}, [featuredPostsAsync.value]);
|
||||||
|
|
||||||
return ClipRRect(
|
return ClipRRect(
|
||||||
borderRadius: const BorderRadius.all(Radius.circular(8)),
|
borderRadius: const BorderRadius.all(Radius.circular(8)),
|
||||||
child: Card(
|
child: Card(
|
||||||
@@ -73,29 +133,69 @@ class PostFeaturedList extends HookConsumerWidget {
|
|||||||
},
|
},
|
||||||
icon: const Icon(Symbols.arrow_right),
|
icon: const Icon(Symbols.arrow_right),
|
||||||
),
|
),
|
||||||
|
IconButton(
|
||||||
|
padding: EdgeInsets.zero,
|
||||||
|
visualDensity: VisualDensity.compact,
|
||||||
|
constraints: const BoxConstraints(),
|
||||||
|
onPressed: () {
|
||||||
|
isCollapsed.value = !isCollapsed.value;
|
||||||
|
debugPrint(
|
||||||
|
'PostFeaturedList: Manual toggle. isCollapsed set to ${isCollapsed.value}',
|
||||||
|
);
|
||||||
|
if (isCollapsed.value &&
|
||||||
|
featuredPostsAsync.hasValue &&
|
||||||
|
featuredPostsAsync.value!.isNotEmpty) {
|
||||||
|
prefs.setString(
|
||||||
|
kFeaturedPostsCollapsedId,
|
||||||
|
featuredPostsAsync.value!.first.id,
|
||||||
|
);
|
||||||
|
debugPrint(
|
||||||
|
'PostFeaturedList: Stored collapsed ID: ${featuredPostsAsync.value!.first.id}',
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
prefs.remove(kFeaturedPostsCollapsedId);
|
||||||
|
debugPrint(
|
||||||
|
'PostFeaturedList: Removed stored collapsed ID.',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
icon: Icon(
|
||||||
|
isCollapsed.value
|
||||||
|
? Symbols.expand_more
|
||||||
|
: Symbols.expand_less,
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
).padding(horizontal: 16, vertical: 8),
|
).padding(horizontal: 16, vertical: 8),
|
||||||
featuredPostsAsync.when(
|
AnimatedSize(
|
||||||
loading: () => const Center(child: CircularProgressIndicator()),
|
duration: const Duration(milliseconds: 300),
|
||||||
error: (error, stack) => Center(child: Text('Error: $error')),
|
curve: Curves.easeInOut,
|
||||||
data: (posts) {
|
child: Visibility(
|
||||||
return SizedBox(
|
visible: !isCollapsed.value,
|
||||||
height: 320,
|
child: featuredPostsAsync.when(
|
||||||
child: PageView.builder(
|
loading:
|
||||||
controller: pageViewController,
|
() => const Center(child: CircularProgressIndicator()),
|
||||||
scrollDirection: Axis.horizontal,
|
error: (error, stack) => Center(child: Text('Error: $error')),
|
||||||
itemCount: posts.length,
|
data: (posts) {
|
||||||
itemBuilder: (context, index) {
|
return SizedBox(
|
||||||
return SingleChildScrollView(
|
height: 320,
|
||||||
child: PostActionableItem(
|
child: PageView.builder(
|
||||||
item: posts[index],
|
controller: pageViewController,
|
||||||
borderRadius: 8,
|
scrollDirection: Axis.horizontal,
|
||||||
),
|
itemCount: posts.length,
|
||||||
);
|
itemBuilder: (context, index) {
|
||||||
},
|
return SingleChildScrollView(
|
||||||
),
|
child: PostActionableItem(
|
||||||
);
|
item: posts[index],
|
||||||
},
|
borderRadius: 8,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@@ -117,8 +117,12 @@ class PostActionableItem extends HookConsumerWidget {
|
|||||||
await File('${directory.path}/image.png').create();
|
await File('${directory.path}/image.png').create();
|
||||||
await imagePath.writeAsBytes(image);
|
await imagePath.writeAsBytes(image);
|
||||||
|
|
||||||
if (context.mounted) hideLoadingModal(context);
|
if (!context.mounted) return;
|
||||||
await Share.shareXFiles([XFile(imagePath.path)]);
|
hideLoadingModal(context);
|
||||||
|
final box = context.findRenderObject() as RenderBox?;
|
||||||
|
await Share.shareXFiles([
|
||||||
|
XFile(imagePath.path),
|
||||||
|
], sharePositionOrigin: box!.localToGlobal(Offset.zero) & box.size);
|
||||||
})
|
})
|
||||||
.catchError((err) {
|
.catchError((err) {
|
||||||
if (context.mounted) hideLoadingModal(context);
|
if (context.mounted) hideLoadingModal(context);
|
||||||
@@ -174,7 +178,7 @@ class PostActionableItem extends HookConsumerWidget {
|
|||||||
image: MenuImage.icon(Symbols.link),
|
image: MenuImage.icon(Symbols.link),
|
||||||
callback: () {
|
callback: () {
|
||||||
Clipboard.setData(
|
Clipboard.setData(
|
||||||
ClipboardData(text: 'https://solsynth.dev/posts/${item.id}'),
|
ClipboardData(text: 'https://solian.app/posts/${item.id}'),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@@ -94,7 +94,7 @@ class PostItemCreator extends HookConsumerWidget {
|
|||||||
borderRadius: BorderRadius.circular(12),
|
borderRadius: BorderRadius.circular(12),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
if (isOpenable) {
|
if (isOpenable) {
|
||||||
context.pushNamed('postDetail', pathParameters: {'id': item.id});
|
context.goNamed('postDetail', pathParameters: {'id': item.id});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
child: Padding(
|
child: Padding(
|
||||||
|
@@ -15,11 +15,13 @@ class PostListNotifier extends _$PostListNotifier
|
|||||||
static const int _pageSize = 20;
|
static const int _pageSize = 20;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<CursorPagingData<SnPost>> build(
|
Future<CursorPagingData<SnPost>> build({
|
||||||
String? pubName, {
|
String? pubName,
|
||||||
|
String? realm,
|
||||||
int? type,
|
int? type,
|
||||||
List<String>? categories,
|
List<String>? categories,
|
||||||
List<String>? tags,
|
List<String>? tags,
|
||||||
|
bool shuffle = false,
|
||||||
}) {
|
}) {
|
||||||
return fetch(cursor: null);
|
return fetch(cursor: null);
|
||||||
}
|
}
|
||||||
@@ -33,9 +35,11 @@ class PostListNotifier extends _$PostListNotifier
|
|||||||
'offset': offset,
|
'offset': offset,
|
||||||
'take': _pageSize,
|
'take': _pageSize,
|
||||||
if (pubName != null) 'pub': pubName,
|
if (pubName != null) 'pub': pubName,
|
||||||
|
if (realm != null) 'realm': realm,
|
||||||
if (type != null) 'type': type,
|
if (type != null) 'type': type,
|
||||||
if (tags != null) 'tags': tags,
|
if (tags != null) 'tags': tags,
|
||||||
if (categories != null) 'categories': categories,
|
if (categories != null) 'categories': categories,
|
||||||
|
if (shuffle) 'shuffle': true,
|
||||||
};
|
};
|
||||||
|
|
||||||
final response = await client.get(
|
final response = await client.get(
|
||||||
@@ -68,9 +72,11 @@ enum PostItemType {
|
|||||||
|
|
||||||
class SliverPostList extends HookConsumerWidget {
|
class SliverPostList extends HookConsumerWidget {
|
||||||
final String? pubName;
|
final String? pubName;
|
||||||
|
final String? realm;
|
||||||
final int? type;
|
final int? type;
|
||||||
final List<String>? categories;
|
final List<String>? categories;
|
||||||
final List<String>? tags;
|
final List<String>? tags;
|
||||||
|
final bool shuffle;
|
||||||
final PostItemType itemType;
|
final PostItemType itemType;
|
||||||
final Color? backgroundColor;
|
final Color? backgroundColor;
|
||||||
final EdgeInsets? padding;
|
final EdgeInsets? padding;
|
||||||
@@ -81,9 +87,11 @@ class SliverPostList extends HookConsumerWidget {
|
|||||||
const SliverPostList({
|
const SliverPostList({
|
||||||
super.key,
|
super.key,
|
||||||
this.pubName,
|
this.pubName,
|
||||||
|
this.realm,
|
||||||
this.type,
|
this.type,
|
||||||
this.categories,
|
this.categories,
|
||||||
this.tags,
|
this.tags,
|
||||||
|
this.shuffle = false,
|
||||||
this.itemType = PostItemType.regular,
|
this.itemType = PostItemType.regular,
|
||||||
this.backgroundColor,
|
this.backgroundColor,
|
||||||
this.padding,
|
this.padding,
|
||||||
@@ -96,24 +104,30 @@ class SliverPostList extends HookConsumerWidget {
|
|||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
return PagingHelperSliverView(
|
return PagingHelperSliverView(
|
||||||
provider: postListNotifierProvider(
|
provider: postListNotifierProvider(
|
||||||
pubName,
|
pubName: pubName,
|
||||||
|
realm: realm,
|
||||||
type: type,
|
type: type,
|
||||||
categories: categories,
|
categories: categories,
|
||||||
tags: tags,
|
tags: tags,
|
||||||
|
shuffle: shuffle,
|
||||||
),
|
),
|
||||||
futureRefreshable:
|
futureRefreshable:
|
||||||
postListNotifierProvider(
|
postListNotifierProvider(
|
||||||
pubName,
|
pubName: pubName,
|
||||||
|
realm: realm,
|
||||||
type: type,
|
type: type,
|
||||||
categories: categories,
|
categories: categories,
|
||||||
tags: tags,
|
tags: tags,
|
||||||
|
shuffle: shuffle,
|
||||||
).future,
|
).future,
|
||||||
notifierRefreshable:
|
notifierRefreshable:
|
||||||
postListNotifierProvider(
|
postListNotifierProvider(
|
||||||
pubName,
|
pubName: pubName,
|
||||||
|
realm: realm,
|
||||||
type: type,
|
type: type,
|
||||||
categories: categories,
|
categories: categories,
|
||||||
tags: tags,
|
tags: tags,
|
||||||
|
shuffle: shuffle,
|
||||||
).notifier,
|
).notifier,
|
||||||
contentBuilder:
|
contentBuilder:
|
||||||
(data, widgetCount, endItemView) => SliverList.builder(
|
(data, widgetCount, endItemView) => SliverList.builder(
|
||||||
|
@@ -6,7 +6,7 @@ part of 'post_list.dart';
|
|||||||
// RiverpodGenerator
|
// RiverpodGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
String _$postListNotifierHash() => r'2ca4f3cfbbcd04f3cc32e7f7bd511a5811042829';
|
String _$postListNotifierHash() => r'faa0b939fae56367ff120ce63d9deb17b1995c9c';
|
||||||
|
|
||||||
/// Copied from Dart SDK
|
/// Copied from Dart SDK
|
||||||
class _SystemHash {
|
class _SystemHash {
|
||||||
@@ -32,15 +32,19 @@ class _SystemHash {
|
|||||||
abstract class _$PostListNotifier
|
abstract class _$PostListNotifier
|
||||||
extends BuildlessAutoDisposeAsyncNotifier<CursorPagingData<SnPost>> {
|
extends BuildlessAutoDisposeAsyncNotifier<CursorPagingData<SnPost>> {
|
||||||
late final String? pubName;
|
late final String? pubName;
|
||||||
|
late final String? realm;
|
||||||
late final int? type;
|
late final int? type;
|
||||||
late final List<String>? categories;
|
late final List<String>? categories;
|
||||||
late final List<String>? tags;
|
late final List<String>? tags;
|
||||||
|
late final bool shuffle;
|
||||||
|
|
||||||
FutureOr<CursorPagingData<SnPost>> build(
|
FutureOr<CursorPagingData<SnPost>> build({
|
||||||
String? pubName, {
|
String? pubName,
|
||||||
|
String? realm,
|
||||||
int? type,
|
int? type,
|
||||||
List<String>? categories,
|
List<String>? categories,
|
||||||
List<String>? tags,
|
List<String>? tags,
|
||||||
|
bool shuffle = false,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,17 +59,21 @@ class PostListNotifierFamily
|
|||||||
const PostListNotifierFamily();
|
const PostListNotifierFamily();
|
||||||
|
|
||||||
/// See also [PostListNotifier].
|
/// See also [PostListNotifier].
|
||||||
PostListNotifierProvider call(
|
PostListNotifierProvider call({
|
||||||
String? pubName, {
|
String? pubName,
|
||||||
|
String? realm,
|
||||||
int? type,
|
int? type,
|
||||||
List<String>? categories,
|
List<String>? categories,
|
||||||
List<String>? tags,
|
List<String>? tags,
|
||||||
|
bool shuffle = false,
|
||||||
}) {
|
}) {
|
||||||
return PostListNotifierProvider(
|
return PostListNotifierProvider(
|
||||||
pubName,
|
pubName: pubName,
|
||||||
|
realm: realm,
|
||||||
type: type,
|
type: type,
|
||||||
categories: categories,
|
categories: categories,
|
||||||
tags: tags,
|
tags: tags,
|
||||||
|
shuffle: shuffle,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,10 +82,12 @@ class PostListNotifierFamily
|
|||||||
covariant PostListNotifierProvider provider,
|
covariant PostListNotifierProvider provider,
|
||||||
) {
|
) {
|
||||||
return call(
|
return call(
|
||||||
provider.pubName,
|
pubName: provider.pubName,
|
||||||
|
realm: provider.realm,
|
||||||
type: provider.type,
|
type: provider.type,
|
||||||
categories: provider.categories,
|
categories: provider.categories,
|
||||||
tags: provider.tags,
|
tags: provider.tags,
|
||||||
|
shuffle: provider.shuffle,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,18 +114,22 @@ class PostListNotifierProvider
|
|||||||
CursorPagingData<SnPost>
|
CursorPagingData<SnPost>
|
||||||
> {
|
> {
|
||||||
/// See also [PostListNotifier].
|
/// See also [PostListNotifier].
|
||||||
PostListNotifierProvider(
|
PostListNotifierProvider({
|
||||||
String? pubName, {
|
String? pubName,
|
||||||
|
String? realm,
|
||||||
int? type,
|
int? type,
|
||||||
List<String>? categories,
|
List<String>? categories,
|
||||||
List<String>? tags,
|
List<String>? tags,
|
||||||
|
bool shuffle = false,
|
||||||
}) : this._internal(
|
}) : this._internal(
|
||||||
() =>
|
() =>
|
||||||
PostListNotifier()
|
PostListNotifier()
|
||||||
..pubName = pubName
|
..pubName = pubName
|
||||||
|
..realm = realm
|
||||||
..type = type
|
..type = type
|
||||||
..categories = categories
|
..categories = categories
|
||||||
..tags = tags,
|
..tags = tags
|
||||||
|
..shuffle = shuffle,
|
||||||
from: postListNotifierProvider,
|
from: postListNotifierProvider,
|
||||||
name: r'postListNotifierProvider',
|
name: r'postListNotifierProvider',
|
||||||
debugGetCreateSourceHash:
|
debugGetCreateSourceHash:
|
||||||
@@ -126,9 +140,11 @@ class PostListNotifierProvider
|
|||||||
allTransitiveDependencies:
|
allTransitiveDependencies:
|
||||||
PostListNotifierFamily._allTransitiveDependencies,
|
PostListNotifierFamily._allTransitiveDependencies,
|
||||||
pubName: pubName,
|
pubName: pubName,
|
||||||
|
realm: realm,
|
||||||
type: type,
|
type: type,
|
||||||
categories: categories,
|
categories: categories,
|
||||||
tags: tags,
|
tags: tags,
|
||||||
|
shuffle: shuffle,
|
||||||
);
|
);
|
||||||
|
|
||||||
PostListNotifierProvider._internal(
|
PostListNotifierProvider._internal(
|
||||||
@@ -139,25 +155,31 @@ class PostListNotifierProvider
|
|||||||
required super.debugGetCreateSourceHash,
|
required super.debugGetCreateSourceHash,
|
||||||
required super.from,
|
required super.from,
|
||||||
required this.pubName,
|
required this.pubName,
|
||||||
|
required this.realm,
|
||||||
required this.type,
|
required this.type,
|
||||||
required this.categories,
|
required this.categories,
|
||||||
required this.tags,
|
required this.tags,
|
||||||
|
required this.shuffle,
|
||||||
}) : super.internal();
|
}) : super.internal();
|
||||||
|
|
||||||
final String? pubName;
|
final String? pubName;
|
||||||
|
final String? realm;
|
||||||
final int? type;
|
final int? type;
|
||||||
final List<String>? categories;
|
final List<String>? categories;
|
||||||
final List<String>? tags;
|
final List<String>? tags;
|
||||||
|
final bool shuffle;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
FutureOr<CursorPagingData<SnPost>> runNotifierBuild(
|
FutureOr<CursorPagingData<SnPost>> runNotifierBuild(
|
||||||
covariant PostListNotifier notifier,
|
covariant PostListNotifier notifier,
|
||||||
) {
|
) {
|
||||||
return notifier.build(
|
return notifier.build(
|
||||||
pubName,
|
pubName: pubName,
|
||||||
|
realm: realm,
|
||||||
type: type,
|
type: type,
|
||||||
categories: categories,
|
categories: categories,
|
||||||
tags: tags,
|
tags: tags,
|
||||||
|
shuffle: shuffle,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -169,18 +191,22 @@ class PostListNotifierProvider
|
|||||||
() =>
|
() =>
|
||||||
create()
|
create()
|
||||||
..pubName = pubName
|
..pubName = pubName
|
||||||
|
..realm = realm
|
||||||
..type = type
|
..type = type
|
||||||
..categories = categories
|
..categories = categories
|
||||||
..tags = tags,
|
..tags = tags
|
||||||
|
..shuffle = shuffle,
|
||||||
from: from,
|
from: from,
|
||||||
name: null,
|
name: null,
|
||||||
dependencies: null,
|
dependencies: null,
|
||||||
allTransitiveDependencies: null,
|
allTransitiveDependencies: null,
|
||||||
debugGetCreateSourceHash: null,
|
debugGetCreateSourceHash: null,
|
||||||
pubName: pubName,
|
pubName: pubName,
|
||||||
|
realm: realm,
|
||||||
type: type,
|
type: type,
|
||||||
categories: categories,
|
categories: categories,
|
||||||
tags: tags,
|
tags: tags,
|
||||||
|
shuffle: shuffle,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -198,18 +224,22 @@ class PostListNotifierProvider
|
|||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return other is PostListNotifierProvider &&
|
return other is PostListNotifierProvider &&
|
||||||
other.pubName == pubName &&
|
other.pubName == pubName &&
|
||||||
|
other.realm == realm &&
|
||||||
other.type == type &&
|
other.type == type &&
|
||||||
other.categories == categories &&
|
other.categories == categories &&
|
||||||
other.tags == tags;
|
other.tags == tags &&
|
||||||
|
other.shuffle == shuffle;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
int get hashCode {
|
int get hashCode {
|
||||||
var hash = _SystemHash.combine(0, runtimeType.hashCode);
|
var hash = _SystemHash.combine(0, runtimeType.hashCode);
|
||||||
hash = _SystemHash.combine(hash, pubName.hashCode);
|
hash = _SystemHash.combine(hash, pubName.hashCode);
|
||||||
|
hash = _SystemHash.combine(hash, realm.hashCode);
|
||||||
hash = _SystemHash.combine(hash, type.hashCode);
|
hash = _SystemHash.combine(hash, type.hashCode);
|
||||||
hash = _SystemHash.combine(hash, categories.hashCode);
|
hash = _SystemHash.combine(hash, categories.hashCode);
|
||||||
hash = _SystemHash.combine(hash, tags.hashCode);
|
hash = _SystemHash.combine(hash, tags.hashCode);
|
||||||
|
hash = _SystemHash.combine(hash, shuffle.hashCode);
|
||||||
|
|
||||||
return _SystemHash.finish(hash);
|
return _SystemHash.finish(hash);
|
||||||
}
|
}
|
||||||
@@ -222,6 +252,9 @@ mixin PostListNotifierRef
|
|||||||
/// The parameter `pubName` of this provider.
|
/// The parameter `pubName` of this provider.
|
||||||
String? get pubName;
|
String? get pubName;
|
||||||
|
|
||||||
|
/// The parameter `realm` of this provider.
|
||||||
|
String? get realm;
|
||||||
|
|
||||||
/// The parameter `type` of this provider.
|
/// The parameter `type` of this provider.
|
||||||
int? get type;
|
int? get type;
|
||||||
|
|
||||||
@@ -230,6 +263,9 @@ mixin PostListNotifierRef
|
|||||||
|
|
||||||
/// The parameter `tags` of this provider.
|
/// The parameter `tags` of this provider.
|
||||||
List<String>? get tags;
|
List<String>? get tags;
|
||||||
|
|
||||||
|
/// The parameter `shuffle` of this provider.
|
||||||
|
bool get shuffle;
|
||||||
}
|
}
|
||||||
|
|
||||||
class _PostListNotifierProviderElement
|
class _PostListNotifierProviderElement
|
||||||
@@ -244,12 +280,16 @@ class _PostListNotifierProviderElement
|
|||||||
@override
|
@override
|
||||||
String? get pubName => (origin as PostListNotifierProvider).pubName;
|
String? get pubName => (origin as PostListNotifierProvider).pubName;
|
||||||
@override
|
@override
|
||||||
|
String? get realm => (origin as PostListNotifierProvider).realm;
|
||||||
|
@override
|
||||||
int? get type => (origin as PostListNotifierProvider).type;
|
int? get type => (origin as PostListNotifierProvider).type;
|
||||||
@override
|
@override
|
||||||
List<String>? get categories =>
|
List<String>? get categories =>
|
||||||
(origin as PostListNotifierProvider).categories;
|
(origin as PostListNotifierProvider).categories;
|
||||||
@override
|
@override
|
||||||
List<String>? get tags => (origin as PostListNotifierProvider).tags;
|
List<String>? get tags => (origin as PostListNotifierProvider).tags;
|
||||||
|
@override
|
||||||
|
bool get shuffle => (origin as PostListNotifierProvider).shuffle;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ignore_for_file: type=lint
|
// ignore_for_file: type=lint
|
||||||
|
@@ -559,7 +559,11 @@ class PostHeader extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
child: ProfilePictureWidget(file: item.publisher.picture, radius: 16),
|
child: ProfilePictureWidget(
|
||||||
|
file: item.publisher.picture,
|
||||||
|
radius: 16,
|
||||||
|
borderRadius: item.publisher.type == 0 ? null : 6,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Column(
|
child: Column(
|
||||||
@@ -567,12 +571,46 @@ class PostHeader extends StatelessWidget {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Row(
|
Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
spacing: 4,
|
spacing: 4,
|
||||||
children: [
|
children: [
|
||||||
Text(item.publisher.nick).bold(),
|
Text(item.publisher.nick).bold(),
|
||||||
if (item.publisher.verification != null)
|
if (item.publisher.verification != null)
|
||||||
VerificationMark(mark: item.publisher.verification!),
|
VerificationMark(mark: item.publisher.verification!),
|
||||||
Text('@${item.publisher.name}').fontSize(11),
|
if (item.realm == null)
|
||||||
|
Text('@${item.publisher.name}').fontSize(11)
|
||||||
|
else
|
||||||
|
...([
|
||||||
|
const Icon(Symbols.arrow_right, size: 14),
|
||||||
|
Flexible(
|
||||||
|
child: InkWell(
|
||||||
|
child: Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
spacing: 5,
|
||||||
|
children: [
|
||||||
|
Flexible(
|
||||||
|
child: Text(
|
||||||
|
item.realm!.name,
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
ProfilePictureWidget(
|
||||||
|
file: item.realm!.picture,
|
||||||
|
fallbackIcon: Symbols.group,
|
||||||
|
radius: 9,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
onTap: () {
|
||||||
|
GoRouter.of(context).pushNamed(
|
||||||
|
'realmDetail',
|
||||||
|
pathParameters: {'slug': item.realm!.slug},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
Row(
|
Row(
|
||||||
|
108
lib/widgets/post/post_shuffle.dart
Normal file
108
lib/widgets/post/post_shuffle.dart
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_card_swiper/flutter_card_swiper.dart';
|
||||||
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:island/widgets/app_scaffold.dart';
|
||||||
|
import 'package:island/widgets/post/post_item.dart';
|
||||||
|
import 'package:island/widgets/post/post_list.dart';
|
||||||
|
import 'package:material_symbols_icons/symbols.dart';
|
||||||
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
|
|
||||||
|
class PostShuffleScreen extends HookConsumerWidget {
|
||||||
|
const PostShuffleScreen({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final postListState = ref.watch(postListNotifierProvider(shuffle: true));
|
||||||
|
final postListNotifier = ref.watch(
|
||||||
|
postListNotifierProvider(shuffle: true).notifier,
|
||||||
|
);
|
||||||
|
|
||||||
|
final cardSwiperController = useMemoized(() => CardSwiperController(), []);
|
||||||
|
|
||||||
|
useEffect(() {
|
||||||
|
return cardSwiperController.dispose;
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const kBottomControlHeight = 96.0;
|
||||||
|
|
||||||
|
return AppScaffold(
|
||||||
|
appBar: AppBar(title: const Text('postShuffle').tr()),
|
||||||
|
body: Stack(
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
bottom:
|
||||||
|
kBottomControlHeight + MediaQuery.of(context).padding.bottom,
|
||||||
|
),
|
||||||
|
child:
|
||||||
|
(postListState.value?.items.length ?? 0) > 0
|
||||||
|
? CardSwiper(
|
||||||
|
controller: cardSwiperController,
|
||||||
|
cardsCount: postListState.value!.items.length,
|
||||||
|
cardBuilder: (
|
||||||
|
context,
|
||||||
|
index,
|
||||||
|
horizontalOffsetPercentage,
|
||||||
|
verticalOffsetPercentage,
|
||||||
|
) {
|
||||||
|
return Center(
|
||||||
|
child: Card(
|
||||||
|
margin: EdgeInsets.zero,
|
||||||
|
child: ClipRRect(
|
||||||
|
borderRadius: const BorderRadius.all(
|
||||||
|
Radius.circular(8),
|
||||||
|
),
|
||||||
|
child: PostActionableItem(
|
||||||
|
item: postListState.value!.items[index],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
onEnd: () {
|
||||||
|
if (postListState.value?.hasMore ?? true) {
|
||||||
|
postListNotifier.fetch(
|
||||||
|
cursor: postListState.value?.nextCursor,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
: Center(child: CircularProgressIndicator()),
|
||||||
|
),
|
||||||
|
Positioned(
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
bottom: 0,
|
||||||
|
child: Container(
|
||||||
|
color: Theme.of(context).colorScheme.surfaceContainer,
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
bottom: MediaQuery.of(context).padding.bottom,
|
||||||
|
),
|
||||||
|
height: kBottomControlHeight,
|
||||||
|
child:
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
IconButton(
|
||||||
|
onPressed: () {
|
||||||
|
cardSwiperController.undo();
|
||||||
|
},
|
||||||
|
icon: const Icon(Symbols.arrow_left_alt),
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
onPressed: () {
|
||||||
|
cardSwiperController.swipe(CardSwiperDirection.right);
|
||||||
|
},
|
||||||
|
icon: const Icon(Symbols.arrow_right_alt),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
).padding(all: 8).center(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@@ -6,6 +6,7 @@ import 'package:island/pods/network.dart';
|
|||||||
import 'package:island/widgets/realm/realm_card.dart';
|
import 'package:island/widgets/realm/realm_card.dart';
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
import 'package:riverpod_paging_utils/riverpod_paging_utils.dart';
|
import 'package:riverpod_paging_utils/riverpod_paging_utils.dart';
|
||||||
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
|
|
||||||
part 'realm_list.g.dart';
|
part 'realm_list.g.dart';
|
||||||
|
|
||||||
@@ -78,7 +79,11 @@ class SliverRealmList extends HookConsumerWidget {
|
|||||||
horizontal: 16,
|
horizontal: 16,
|
||||||
vertical: 8,
|
vertical: 8,
|
||||||
),
|
),
|
||||||
child: RealmCard(realm: realm),
|
child:
|
||||||
|
ConstrainedBox(
|
||||||
|
constraints: const BoxConstraints(maxWidth: 540),
|
||||||
|
child: RealmCard(realm: realm),
|
||||||
|
).center(),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
separatorBuilder: (_, _) => const Gap(8),
|
separatorBuilder: (_, _) => const Gap(8),
|
||||||
|
76
lib/widgets/realm/realm_list_tile.dart
Normal file
76
lib/widgets/realm/realm_list_tile.dart
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:gap/gap.dart';
|
||||||
|
import 'package:go_router/go_router.dart';
|
||||||
|
import 'package:island/models/realm.dart';
|
||||||
|
import 'package:island/widgets/content/cloud_files.dart';
|
||||||
|
import 'package:material_symbols_icons/symbols.dart';
|
||||||
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
|
|
||||||
|
class RealmListTile extends StatelessWidget {
|
||||||
|
const RealmListTile({super.key, required this.realm});
|
||||||
|
|
||||||
|
final SnRealm realm;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Card(
|
||||||
|
margin: EdgeInsets.zero,
|
||||||
|
child: InkWell(
|
||||||
|
borderRadius: const BorderRadius.all(Radius.circular(8)),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
AspectRatio(
|
||||||
|
aspectRatio: 16 / 7,
|
||||||
|
child: Stack(
|
||||||
|
clipBehavior: Clip.none,
|
||||||
|
fit: StackFit.expand,
|
||||||
|
children: [
|
||||||
|
ClipRRect(
|
||||||
|
borderRadius: const BorderRadius.all(Radius.circular(8)),
|
||||||
|
child: Container(
|
||||||
|
color: Theme.of(context).colorScheme.surfaceContainer,
|
||||||
|
child:
|
||||||
|
realm.background == null
|
||||||
|
? const SizedBox.shrink()
|
||||||
|
: CloudImageWidget(file: realm.background),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Positioned(
|
||||||
|
bottom: -30,
|
||||||
|
left: 18,
|
||||||
|
child: ProfilePictureWidget(
|
||||||
|
fileId: realm.picture?.id,
|
||||||
|
fallbackIcon: Symbols.group,
|
||||||
|
radius: 24,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Gap(20 + 12),
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
realm.name,
|
||||||
|
).textStyle(Theme.of(context).textTheme.titleMedium!),
|
||||||
|
Text(
|
||||||
|
realm.description,
|
||||||
|
maxLines: 2,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
).textStyle(Theme.of(context).textTheme.bodySmall!),
|
||||||
|
],
|
||||||
|
).padding(horizontal: 24, bottom: 14),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
onTap: () {
|
||||||
|
context.pushNamed(
|
||||||
|
'realmDetail',
|
||||||
|
pathParameters: {'slug': realm.slug},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@@ -340,22 +340,33 @@ class _ShareSheetState extends ConsumerState<ShareSheet> {
|
|||||||
Future<void> _shareToSystem() async {
|
Future<void> _shareToSystem() async {
|
||||||
if (!widget.toSystem) return;
|
if (!widget.toSystem) return;
|
||||||
|
|
||||||
|
final box = context.findRenderObject() as RenderBox?;
|
||||||
|
|
||||||
setState(() => _isLoading = true);
|
setState(() => _isLoading = true);
|
||||||
try {
|
try {
|
||||||
switch (widget.content.type) {
|
switch (widget.content.type) {
|
||||||
case ShareContentType.text:
|
case ShareContentType.text:
|
||||||
if (widget.content.text?.isNotEmpty == true) {
|
if (widget.content.text?.isNotEmpty == true) {
|
||||||
await Share.share(widget.content.text!);
|
await Share.share(
|
||||||
|
widget.content.text!,
|
||||||
|
sharePositionOrigin: box!.localToGlobal(Offset.zero) & box.size,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ShareContentType.link:
|
case ShareContentType.link:
|
||||||
if (widget.content.link?.isNotEmpty == true) {
|
if (widget.content.link?.isNotEmpty == true) {
|
||||||
await Share.share(widget.content.link!);
|
await Share.share(
|
||||||
|
widget.content.link!,
|
||||||
|
sharePositionOrigin: box!.localToGlobal(Offset.zero) & box.size,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ShareContentType.file:
|
case ShareContentType.file:
|
||||||
if (widget.content.files?.isNotEmpty == true) {
|
if (widget.content.files?.isNotEmpty == true) {
|
||||||
await Share.shareXFiles(widget.content.files!);
|
await Share.shareXFiles(
|
||||||
|
widget.content.files!,
|
||||||
|
sharePositionOrigin: box!.localToGlobal(Offset.zero) & box.size,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -879,7 +890,8 @@ class _LinkPreview extends ConsumerWidget {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
// Favicon and image
|
// Favicon and image
|
||||||
if (embed.imageUrl != null || embed.faviconUrl.isNotEmpty)
|
if (embed.imageUrl != null ||
|
||||||
|
(embed.faviconUrl?.isNotEmpty ?? false))
|
||||||
Container(
|
Container(
|
||||||
width: 60,
|
width: 60,
|
||||||
height: 60,
|
height: 60,
|
||||||
@@ -899,11 +911,14 @@ class _LinkPreview extends ConsumerWidget {
|
|||||||
errorBuilder: (context, error, stackTrace) {
|
errorBuilder: (context, error, stackTrace) {
|
||||||
return _buildFaviconFallback(
|
return _buildFaviconFallback(
|
||||||
context,
|
context,
|
||||||
embed.faviconUrl,
|
embed.faviconUrl ?? '',
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
: _buildFaviconFallback(context, embed.faviconUrl),
|
: _buildFaviconFallback(
|
||||||
|
context,
|
||||||
|
embed.faviconUrl ?? '',
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
// Content
|
// Content
|
||||||
@@ -912,9 +927,9 @@ class _LinkPreview extends ConsumerWidget {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
// Site name
|
// Site name
|
||||||
if (embed.siteName.isNotEmpty)
|
if (embed.siteName?.isNotEmpty ?? false)
|
||||||
Text(
|
Text(
|
||||||
embed.siteName,
|
embed.siteName!,
|
||||||
style: Theme.of(context).textTheme.labelSmall?.copyWith(
|
style: Theme.of(context).textTheme.labelSmall?.copyWith(
|
||||||
color: Theme.of(context).colorScheme.primary,
|
color: Theme.of(context).colorScheme.primary,
|
||||||
),
|
),
|
||||||
|
@@ -41,7 +41,7 @@ endif()
|
|||||||
# of modifying this function.
|
# of modifying this function.
|
||||||
function(APPLY_STANDARD_SETTINGS TARGET)
|
function(APPLY_STANDARD_SETTINGS TARGET)
|
||||||
target_compile_features(${TARGET} PUBLIC cxx_std_14)
|
target_compile_features(${TARGET} PUBLIC cxx_std_14)
|
||||||
target_compile_options(${TARGET} PRIVATE -Wall -Werror)
|
target_compile_options(${TARGET} PRIVATE -Wall -Wextra)
|
||||||
target_compile_options(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:-O3>")
|
target_compile_options(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:-O3>")
|
||||||
target_compile_definitions(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:NDEBUG>")
|
target_compile_definitions(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:NDEBUG>")
|
||||||
endfunction()
|
endfunction()
|
||||||
|
@@ -195,7 +195,7 @@ PODS:
|
|||||||
- PromisesObjC (2.4.0)
|
- PromisesObjC (2.4.0)
|
||||||
- PromisesSwift (2.4.0):
|
- PromisesSwift (2.4.0):
|
||||||
- PromisesObjC (= 2.4.0)
|
- PromisesObjC (= 2.4.0)
|
||||||
- record_macos (1.0.0):
|
- record_macos (1.1.0):
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
- SAMKeychain (1.5.3)
|
- SAMKeychain (1.5.3)
|
||||||
- share_plus (0.0.1):
|
- share_plus (0.0.1):
|
||||||
@@ -422,7 +422,7 @@ SPEC CHECKSUMS:
|
|||||||
path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564
|
path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564
|
||||||
PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47
|
PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47
|
||||||
PromisesSwift: 9d77319bbe72ebf6d872900551f7eeba9bce2851
|
PromisesSwift: 9d77319bbe72ebf6d872900551f7eeba9bce2851
|
||||||
record_macos: 295d70bd5fb47145df78df7b80e6697cd18403c0
|
record_macos: 43194b6c06ca6f8fa132e2acea72b202b92a0f5b
|
||||||
SAMKeychain: 483e1c9f32984d50ca961e26818a534283b4cd5c
|
SAMKeychain: 483e1c9f32984d50ca961e26818a534283b4cd5c
|
||||||
share_plus: 510bf0af1a42cd602274b4629920c9649c52f4cc
|
share_plus: 510bf0af1a42cd602274b4629920c9649c52f4cc
|
||||||
shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7
|
shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7
|
||||||
|
116
pubspec.lock
116
pubspec.lock
@@ -565,10 +565,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: file_picker
|
name: file_picker
|
||||||
sha256: ef7d2a085c1b1d69d17b6842d0734aad90156de08df6bd3c12496d0bd6ddf8e2
|
sha256: e7e16c9d15c36330b94ca0e2ad8cb61f93cd5282d0158c09805aed13b5452f22
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "10.3.1"
|
version: "10.3.2"
|
||||||
file_selector_linux:
|
file_selector_linux:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -581,10 +581,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: file_selector_macos
|
name: file_selector_macos
|
||||||
sha256: "8c9250b2bd2d8d4268e39c82543bacbaca0fda7d29e0728c3c4bbb7c820fd711"
|
sha256: "19124ff4a3d8864fdc62072b6a2ef6c222d55a3404fe14893a3c02744907b60c"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.9.4+3"
|
version: "0.9.4+4"
|
||||||
file_selector_platform_interface:
|
file_selector_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -734,6 +734,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.4.1"
|
version: "3.4.1"
|
||||||
|
flutter_card_swiper:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: flutter_card_swiper
|
||||||
|
sha256: "1eacbfab31b572223042e03409726553aec431abe48af48c8d591d376d070d3d"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "7.0.2"
|
||||||
flutter_colorpicker:
|
flutter_colorpicker:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@@ -754,10 +762,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: flutter_hooks
|
name: flutter_hooks
|
||||||
sha256: c3df76c62bb3a9f9bee75c57cdab40abab6123b734c1cd7e9b26a5dbd436eceb
|
sha256: "8ae1f090e5f4ef5cfa6670ce1ab5dddadd33f3533a7f9ba19d9f958aa2a89f42"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.21.3"
|
version: "0.21.3+1"
|
||||||
flutter_inappwebview:
|
flutter_inappwebview:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@@ -1073,10 +1081,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: font_awesome_flutter
|
name: font_awesome_flutter
|
||||||
sha256: f50ce90dbe26d977415b9540400d6778bef00894aced6358ae578abd92b14b10
|
sha256: b738e35f8bb4957896c34957baf922f99c5d415b38ddc8b070d14b7fa95715d4
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "10.9.0"
|
version: "10.9.1"
|
||||||
freezed:
|
freezed:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
@@ -1137,10 +1145,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: go_router
|
name: go_router
|
||||||
sha256: "8b1f37dfaf6e958c6b872322db06f946509433bec3de753c3491a42ae9ec2b48"
|
sha256: ced3fdc143c1437234ac3b8e985f3286cf138968bb83ca9a6f94d22f2951c6b9
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "16.1.0"
|
version: "16.2.0"
|
||||||
google_fonts:
|
google_fonts:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@@ -1233,66 +1241,66 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: image_picker
|
name: image_picker
|
||||||
sha256: "021834d9c0c3de46bf0fe40341fa07168407f694d9b2bb18d532dc1261867f7a"
|
sha256: "736eb56a911cf24d1859315ad09ddec0b66104bc41a7f8c5b96b4e2620cf5041"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.2"
|
version: "1.2.0"
|
||||||
image_picker_android:
|
image_picker_android:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: image_picker_android
|
name: image_picker_android
|
||||||
sha256: b08e9a04d0f8d91f4a6e767a745b9871bfbc585410205c311d0492de20a7ccd6
|
sha256: e83b2b05141469c5e19d77e1dfa11096b6b1567d09065b2265d7c6904560050c
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.8.12+25"
|
version: "0.8.13"
|
||||||
image_picker_for_web:
|
image_picker_for_web:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: image_picker_for_web
|
name: image_picker_for_web
|
||||||
sha256: "717eb042ab08c40767684327be06a5d8dbb341fe791d514e4b92c7bbe1b7bb83"
|
sha256: "40c2a6a0da15556dc0f8e38a3246064a971a9f512386c3339b89f76db87269b6"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.6"
|
version: "3.1.0"
|
||||||
image_picker_ios:
|
image_picker_ios:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: image_picker_ios
|
name: image_picker_ios
|
||||||
sha256: "05da758e67bc7839e886b3959848aa6b44ff123ab4b28f67891008afe8ef9100"
|
sha256: eb06fe30bab4c4497bad449b66448f50edcc695f1c59408e78aa3a8059eb8f0e
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.8.12+2"
|
version: "0.8.13"
|
||||||
image_picker_linux:
|
image_picker_linux:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: image_picker_linux
|
name: image_picker_linux
|
||||||
sha256: "34a65f6740df08bbbeb0a1abd8e6d32107941fd4868f67a507b25601651022c9"
|
sha256: "1f81c5f2046b9ab724f85523e4af65be1d47b038160a8c8deed909762c308ed4"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.2.1+2"
|
version: "0.2.2"
|
||||||
image_picker_macos:
|
image_picker_macos:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: image_picker_macos
|
name: image_picker_macos
|
||||||
sha256: "1b90ebbd9dcf98fb6c1d01427e49a55bd96b5d67b8c67cf955d60a5de74207c1"
|
sha256: d58cd9d67793d52beefd6585b12050af0a7663c0c2a6ece0fb110a35d6955e04
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.2.1+2"
|
version: "0.2.2"
|
||||||
image_picker_platform_interface:
|
image_picker_platform_interface:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: image_picker_platform_interface
|
name: image_picker_platform_interface
|
||||||
sha256: "886d57f0be73c4b140004e78b9f28a8914a09e50c2d816bdd0520051a71236a0"
|
sha256: "9f143b0dba3e459553209e20cc425c9801af48e6dfa4f01a0fcf927be3f41665"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.10.1"
|
version: "2.11.0"
|
||||||
image_picker_windows:
|
image_picker_windows:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: image_picker_windows
|
name: image_picker_windows
|
||||||
sha256: "6ad07afc4eb1bc25f3a01084d28520496c4a3bb0cb13685435838167c9dcedeb"
|
sha256: d248c86554a72b5495a31c56f060cf73a41c7ff541689327b1a7dbccc33adfae
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.2.1+1"
|
version: "0.2.2"
|
||||||
intl:
|
intl:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -1497,10 +1505,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: material_symbols_icons
|
name: material_symbols_icons
|
||||||
sha256: ef20d86fb34c2b59eb7553c4d795bb8a7ec8c890c53ffd3148c64f7adc46ae50
|
sha256: b1342194e859b2774f920b484c46f54a37a845488e23d570385fbe3ede92ee9f
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.2858.1"
|
version: "4.2867.0"
|
||||||
media_kit:
|
media_kit:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@@ -1713,10 +1721,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: path_provider_foundation
|
name: path_provider_foundation
|
||||||
sha256: "4843174df4d288f5e29185bd6e72a6fbdf5a4a4602717eed565497429f179942"
|
sha256: "16eef174aacb07e09c351502740fa6254c165757638eba1e9116b0a781201bbd"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.4.1"
|
version: "2.4.2"
|
||||||
path_provider_linux:
|
path_provider_linux:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -1841,10 +1849,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: provider
|
name: provider
|
||||||
sha256: "4abbd070a04e9ddc287673bf5a030c7ca8b685ff70218720abab8b092f53dd84"
|
sha256: "4e82183fa20e5ca25703ead7e05de9e4cceed1fbd1eadc1ac3cb6f565a09f272"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "6.1.5"
|
version: "6.1.5+1"
|
||||||
pub_semver:
|
pub_semver:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -1897,66 +1905,66 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: record
|
name: record
|
||||||
sha256: daeb3f9b3fea9797094433fe6e49a879d8e4ca4207740bc6dc7e4a58764f0817
|
sha256: "9dbc6ff3e784612f90a9b001373c45ff76b7a08abd2bd9fdf72c242320c8911c"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "6.0.0"
|
version: "6.1.1"
|
||||||
record_android:
|
record_android:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: record_android
|
name: record_android
|
||||||
sha256: "97d7122455f30de89a01c6c244c839085be6b12abca251fc0e78f67fed73628b"
|
sha256: "8361a791c9a3fa5c065f0b8b5adb10f12531f8538c86b19474cf7b56ea80d426"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.3.3"
|
version: "1.4.1"
|
||||||
record_ios:
|
record_ios:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: record_ios
|
name: record_ios
|
||||||
sha256: "73706ebbece6150654c9d6f57897cf9b622c581148304132ba85dba15df0fdfb"
|
sha256: "895c9467faec72d8e718a3142b51114958f42f18053836a8b484a74f9372f51a"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.0"
|
version: "1.1.1"
|
||||||
record_linux:
|
record_linux:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: record_linux
|
name: record_linux
|
||||||
sha256: "0626678a092c75ce6af1e32fe7fd1dea709b92d308bc8e3b6d6348e2430beb95"
|
sha256: "235b1f1fb84e810f8149cc0c2c731d7d697f8d1c333b32cb820c449bf7bb72d8"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.1"
|
version: "1.2.1"
|
||||||
record_macos:
|
record_macos:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: record_macos
|
name: record_macos
|
||||||
sha256: "02240833fde16c33fcf2c589f3e08d4394b704761b4a3bb609d872ff3043fbbd"
|
sha256: "2849068bb59072f300ad63ed146e543d66afaef8263edba4de4834fc7c8d4d35"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.0"
|
version: "1.1.1"
|
||||||
record_platform_interface:
|
record_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: record_platform_interface
|
name: record_platform_interface
|
||||||
sha256: c1ad38f51e4af88a085b3e792a22c685cb3e7c23fc37aa7ce44c4cf18f25fe89
|
sha256: b0065fdf1ec28f5a634d676724d388a77e43ce7646fb049949f58c69f3fcb4ed
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.3.0"
|
version: "1.4.0"
|
||||||
record_web:
|
record_web:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: record_web
|
name: record_web
|
||||||
sha256: a12856d0b3dd03d336b4b10d7520a8b3e21649a06a8f95815318feaa8f07adbb
|
sha256: "4f0adf20c9ccafcc02d71111fd91fba1ca7b17a7453902593e5a9b25b74a5c56"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.9"
|
version: "1.2.0"
|
||||||
record_windows:
|
record_windows:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: record_windows
|
name: record_windows
|
||||||
sha256: "85a22fc97f6d73ecd67c8ba5f2f472b74ef1d906f795b7970f771a0914167e99"
|
sha256: "223258060a1d25c62bae18282c16783f28581ec19401d17e56b5205b9f039d78"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.6"
|
version: "1.0.7"
|
||||||
relative_time:
|
relative_time:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@@ -2496,10 +2504,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: url_launcher_ios
|
name: url_launcher_ios
|
||||||
sha256: "7f2022359d4c099eea7df3fdf739f7d3d3b9faf3166fb1dd390775176e0b76cb"
|
sha256: d80b3f567a617cb923546034cc94bfe44eb15f989fe670b37f26abdb9d939cb7
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "6.3.3"
|
version: "6.3.4"
|
||||||
url_launcher_linux:
|
url_launcher_linux:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -2512,10 +2520,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: url_launcher_macos
|
name: url_launcher_macos
|
||||||
sha256: "17ba2000b847f334f16626a574c702b196723af2a289e7a93ffcb79acff855c2"
|
sha256: c043a77d6600ac9c38300567f33ef12b0ef4f4783a2c1f00231d2b1941fea13f
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.2.2"
|
version: "3.2.3"
|
||||||
url_launcher_platform_interface:
|
url_launcher_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -2568,10 +2576,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: vector_graphics_compiler
|
name: vector_graphics_compiler
|
||||||
sha256: "557a315b7d2a6dbb0aaaff84d857967ce6bdc96a63dc6ee2a57ce5a6ee5d3331"
|
sha256: ca81fdfaf62a5ab45d7296614aea108d2c7d0efca8393e96174bf4d51e6725b0
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.17"
|
version: "1.1.18"
|
||||||
vector_math:
|
vector_math:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
19
pubspec.yaml
19
pubspec.yaml
@@ -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
|
# 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
|
# 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.
|
# of the product and file versions while build-number is used as the build suffix.
|
||||||
version: 3.2.0+125
|
version: 3.2.0+127
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ^3.7.2
|
sdk: ^3.7.2
|
||||||
@@ -36,10 +36,10 @@ dependencies:
|
|||||||
# The following adds the Cupertino Icons font to your application.
|
# The following adds the Cupertino Icons font to your application.
|
||||||
# Use with the CupertinoIcons class for iOS style icons.
|
# Use with the CupertinoIcons class for iOS style icons.
|
||||||
cupertino_icons: ^1.0.8
|
cupertino_icons: ^1.0.8
|
||||||
flutter_hooks: ^0.21.3
|
flutter_hooks: ^0.21.3+1
|
||||||
hooks_riverpod: ^2.6.1
|
hooks_riverpod: ^2.6.1
|
||||||
bitsdojo_window: ^0.1.6
|
bitsdojo_window: ^0.1.6
|
||||||
go_router: ^16.1.0
|
go_router: ^16.2.0
|
||||||
styled_widget: ^0.4.1
|
styled_widget: ^0.4.1
|
||||||
shared_preferences: ^2.5.3
|
shared_preferences: ^2.5.3
|
||||||
flutter_riverpod: ^2.6.1
|
flutter_riverpod: ^2.6.1
|
||||||
@@ -72,18 +72,18 @@ dependencies:
|
|||||||
tus_client_dart:
|
tus_client_dart:
|
||||||
git: https://github.com/LittleSheep2Code/tus_client.git
|
git: https://github.com/LittleSheep2Code/tus_client.git
|
||||||
cross_file: ^0.3.4+2
|
cross_file: ^0.3.4+2
|
||||||
image_picker: ^1.1.2
|
image_picker: ^1.2.0
|
||||||
file_picker: ^10.3.1
|
file_picker: ^10.3.2
|
||||||
riverpod_annotation: ^2.6.1
|
riverpod_annotation: ^2.6.1
|
||||||
image_picker_platform_interface: ^2.10.1
|
image_picker_platform_interface: ^2.11.0
|
||||||
image_picker_android: ^0.8.12+25
|
image_picker_android: ^0.8.13
|
||||||
super_context_menu: ^0.9.1
|
super_context_menu: ^0.9.1
|
||||||
modal_bottom_sheet: ^3.0.0
|
modal_bottom_sheet: ^3.0.0
|
||||||
firebase_messaging: ^16.0.0
|
firebase_messaging: ^16.0.0
|
||||||
flutter_udid: ^4.0.0
|
flutter_udid: ^4.0.0
|
||||||
firebase_core: ^4.0.0
|
firebase_core: ^4.0.0
|
||||||
web_socket_channel: ^3.0.3
|
web_socket_channel: ^3.0.3
|
||||||
material_symbols_icons: ^4.2858.1
|
material_symbols_icons: ^4.2867.0
|
||||||
drift: ^2.28.1
|
drift: ^2.28.1
|
||||||
drift_flutter: ^0.2.5
|
drift_flutter: ^0.2.5
|
||||||
path: ^1.9.1
|
path: ^1.9.1
|
||||||
@@ -107,7 +107,7 @@ dependencies:
|
|||||||
livekit_client: ^2.5.0+hotfix.1
|
livekit_client: ^2.5.0+hotfix.1
|
||||||
pasteboard: ^0.4.0
|
pasteboard: ^0.4.0
|
||||||
flutter_colorpicker: ^1.1.0
|
flutter_colorpicker: ^1.1.0
|
||||||
record: ^6.0.0
|
record: ^6.1.1
|
||||||
qr_flutter: ^4.1.0
|
qr_flutter: ^4.1.0
|
||||||
flutter_otp_text_field: ^1.5.1+1
|
flutter_otp_text_field: ^1.5.1+1
|
||||||
palette_generator: ^0.3.3+7
|
palette_generator: ^0.3.3+7
|
||||||
@@ -138,6 +138,7 @@ dependencies:
|
|||||||
firebase_analytics: ^12.0.0
|
firebase_analytics: ^12.0.0
|
||||||
material_color_utilities: ^0.11.1
|
material_color_utilities: ^0.11.1
|
||||||
screenshot: ^3.0.0
|
screenshot: ^3.0.0
|
||||||
|
flutter_card_swiper: ^7.0.2
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
Reference in New Issue
Block a user