Compare commits

...

16 Commits

Author SHA1 Message Date
fe8640a6db 🚀 Launch 3.0.0+109 2025-06-28 02:48:15 +08:00
ff475d43dd 🐛 Dozen of hot fixes 2025-06-28 02:40:50 +08:00
9e8f6d57df 🚀 Launch 3.0.0+108 2025-06-28 01:53:07 +08:00
79227a12e2 Android notification extension 2025-06-28 01:28:44 +08:00
a23dcfe702 🐛 Bug fixes android sharing, ios notifications and more 2025-06-28 01:10:44 +08:00
243ecb3f71 Searchable realms 2025-06-28 00:47:03 +08:00
b8dec9f798 Joindable chat, detailed realms, discovery mixed into explore
🐛 bunch of bugs fixes
2025-06-28 00:24:43 +08:00
536375729f 💄 Optimize the notification snackbar position 2025-06-27 22:18:16 +08:00
5939a1dc5b Can make the chat and realm public 2025-06-27 21:52:57 +08:00
9d115a5712 Realm discovery and more detailed realm 2025-06-27 21:10:53 +08:00
f511612a53 Chat rooms in realm detail page 2025-06-27 17:54:29 +08:00
180fbcc558 Join the realm by user own 2025-06-27 17:30:42 +08:00
047cb9dc0d Realms discovery in explore 2025-06-27 02:56:58 +08:00
786f851a97 🐛 Fixes on post route 2025-06-27 02:35:06 +08:00
4deff5a920 Post tags 2025-06-27 02:31:21 +08:00
0361f031db Post editor tags 2025-06-27 00:56:07 +08:00
83 changed files with 3343 additions and 651 deletions

View File

@ -3,7 +3,7 @@ name: Build Release
on:
push:
tags:
- '*'
- "*"
workflow_dispatch:
jobs:
@ -59,6 +59,7 @@ jobs:
sudo apt-get install -y libnotify-dev
sudo apt-get install -y libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev
sudo apt-get install -y gstreamer-1.0
sudo apt-get install -y libsecret-1
- run: flutter pub get
- run: flutter build linux
- name: Archive production artifacts
@ -80,4 +81,4 @@ jobs:
uses: actions/upload-artifact@v4
with:
name: build-output-linux-appimage
path: './*.AppImage*'
path: "./*.AppImage*"

View File

@ -57,6 +57,9 @@ android {
dependencies {
implementation("com.google.android.material:material:1.12.0")
implementation("com.github.bumptech.glide:glide:4.16.0")
implementation("com.squareup.okhttp3:okhttp:4.12.0")
implementation("com.google.firebase:firebase-messaging-ktx")
}
flutter {

View File

@ -46,12 +46,37 @@
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="*/*" />
<data android:mimeType="image/*" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND_MULTIPLE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="*/*" />
<data android:mimeType="image/*" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="video/*" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND_MULTIPLE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="video/*" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/*" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="application/*" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND_MULTIPLE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="application/*" />
</intent-filter>
</activity>
@ -70,6 +95,19 @@
</intent-filter>
</activity>
<receiver
android:name=".receiver.ReplyReceiver"
android:enabled="true"
android:exported="true" />
<service
android:name=".service.MessagingService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="dev.solsynth.solian.provider"

View File

@ -1,14 +0,0 @@
package dev.solsynth.solian
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugins.sharedpreferences.LegacySharedPreferencesPlugin
class MainActivity : FlutterActivity()
{
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
// https://github.com/flutter/flutter/issues/153075#issuecomment-2693189362
flutterEngine.plugins.add(LegacySharedPreferencesPlugin())
}
}

View File

@ -0,0 +1,39 @@
package dev.solsynth.solian
import android.content.Intent
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugins.sharedpreferences.LegacySharedPreferencesPlugin
class MainActivity : FlutterActivity()
{
private val CHANNEL = "dev.solsynth.solian/notifications"
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
// https://github.com/flutter/flutter/issues/153075#issuecomment-2693189362
flutterEngine.plugins.add(LegacySharedPreferencesPlugin())
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result ->
if (call.method == "initialLink") {
val roomId = intent.getStringExtra("room_id")
if (roomId != null) {
result.success("/rooms/$roomId")
} else {
result.success(null)
}
} else {
result.notImplemented()
}
}
}
override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
val roomId = intent.getStringExtra("room_id")
if (roomId != null) {
MethodChannel(flutterEngine!!.dartExecutor.binaryMessenger, CHANNEL).invokeMethod("newLink", "/rooms/$roomId")
}
}
}

View File

@ -0,0 +1,47 @@
package dev.solsynth.solian.network
import android.content.Context
import android.content.SharedPreferences
import okhttp3.Call
import okhttp3.Callback
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.Response
import org.json.JSONObject
import java.io.IOException
class ApiClient(private val context: Context) {
private val client = OkHttpClient()
private val sharedPreferences: SharedPreferences = context.getSharedPreferences("FlutterSharedPreferences", Context.MODE_PRIVATE)
fun sendMessage(roomId: String, message: String, replyTo: String, callback: (Boolean) -> Unit) {
val token = sharedPreferences.getString("flutter.token", null)
if (token == null) {
callback(false)
return
}
val json = JSONObject().apply {
put("content", message)
put("reply_to", replyTo)
}
val body = json.toString().toRequestBody("application/json; charset=utf-8".toMediaType())
val request = Request.Builder()
.url("https://solian.dev/api/rooms/$roomId/messages")
.header("Authorization", "Bearer $token")
.post(body)
.build()
client.newCall(request).enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
callback(false)
}
override fun onResponse(call: Call, response: Response) {
callback(response.isSuccessful)
}
})
}
}

View File

@ -0,0 +1,27 @@
package dev.solsynth.solian.receiver
import android.app.NotificationManager
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import androidx.core.app.RemoteInput
import dev.solsynth.solian.network.ApiClient
class ReplyReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val remoteInput = RemoteInput.getResultsFromIntent(intent)
if (remoteInput != null) {
val replyText = remoteInput.getCharSequence("key_text_reply").toString()
val roomId = intent.getStringExtra("room_id")
val messageId = intent.getStringExtra("message_id")
val notificationId = intent.getIntExtra("notification_id", 0)
if (roomId != null && messageId != null) {
ApiClient(context).sendMessage(roomId, replyText, messageId) {
val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.cancel(notificationId)
}
}
}
}
}

View File

@ -0,0 +1,102 @@
package dev.solsynth.solian.service
import android.app.PendingIntent
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.drawable.Drawable
import android.os.Build
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import androidx.core.app.RemoteInput
import com.bumptech.glide.Glide
import com.bumptech.glide.request.target.CustomTarget
import com.bumptech.glide.request.transition.Transition
import com.google.firebase.messaging.FirebaseMessagingService
import com.google.firebase.messaging.RemoteMessage
import dev.solsynth.solian.MainActivity
import dev.solsynth.solian.receiver.ReplyReceiver
import org.json.JSONObject
class MessagingService: FirebaseMessagingService() {
override fun onMessageReceived(remoteMessage: RemoteMessage) {
val type = remoteMessage.data["type"]
if (type == "messages.new") {
handleMessageNotification(remoteMessage)
} else {
// Handle other notification types
}
}
private fun handleMessageNotification(remoteMessage: RemoteMessage) {
val data = remoteMessage.data
val metaString = data["meta"] ?: return
val meta = JSONObject(metaString)
val pfp = meta.optString("pfp", null)
val roomId = meta.optString("room_id", null)
val messageId = meta.optString("message_id", null)
val notificationId = System.currentTimeMillis().toInt()
val replyLabel = "Reply"
val remoteInput = RemoteInput.Builder("key_text_reply")
.setLabel(replyLabel)
.build()
val replyIntent = Intent(this, ReplyReceiver::class.java).apply {
putExtra("room_id", roomId)
putExtra("message_id", messageId)
putExtra("notification_id", notificationId)
}
val pendingIntentFlags = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
} else {
PendingIntent.FLAG_UPDATE_CURRENT
}
val replyPendingIntent = PendingIntent.getBroadcast(
applicationContext,
notificationId,
replyIntent,
pendingIntentFlags
)
val action = NotificationCompat.Action.Builder(
android.R.drawable.ic_menu_send,
replyLabel,
replyPendingIntent
)
.addRemoteInput(remoteInput)
.build()
val intent = Intent(this, MainActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
intent.putExtra("room_id", roomId)
val pendingIntent = PendingIntent.getActivity(this, 0, intent, pendingIntentFlags)
val notificationBuilder = NotificationCompat.Builder(this, "messages")
.setSmallIcon(android.R.drawable.ic_dialog_info)
.setContentTitle(remoteMessage.notification?.title)
.setContentText(remoteMessage.notification?.body)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setContentIntent(pendingIntent)
.addAction(action)
if (pfp != null) {
Glide.with(applicationContext)
.asBitmap()
.load(pfp)
.into(object : CustomTarget<Bitmap>() {
override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) {
notificationBuilder.setLargeIcon(resource)
NotificationManagerCompat.from(applicationContext).notify(notificationId, notificationBuilder.build())
}
override fun onLoadCleared(placeholder: Drawable?) {}
})
} else {
NotificationManagerCompat.from(this).notify(notificationId, notificationBuilder.build())
}
}
}

View File

@ -98,6 +98,8 @@
"explore": "Explore",
"exploreFilterSubscriptions": "Subscriptions",
"exploreFilterFriends": "Friends",
"discover": "Discover",
"joinRealm": "Join Realm",
"account": "Account",
"name": "Name",
"slug": "Slug",
@ -405,15 +407,15 @@
"lastActiveAt": "Last active at {}",
"authDeviceLogout": "Logout",
"authDeviceLogoutHint": "Are you sure you want to logout this device? This will also disable the push notification to this device.",
"typingHint": {
"one": "{} is typing...",
"other": "{} are typing..."
},
"authDeviceEditLabel": "Edit Label",
"authDeviceLabelTitle": "Edit Device Label",
"authDeviceLabelHint": "Enter a name for this device",
"authDeviceSwipeEditHint": "Swipe left to edit label",
"authDeviceSwipeLogoutHint": "Swipe right to logout device",
"typingHint": {
"one": "{} is typing...",
"other": "{} are typing..."
},
"settingsAppearance": "Appearance",
"settingsServer": "Server",
"settingsBehavior": "Behavior",
@ -615,5 +617,17 @@
"abuseReportTypeOffensiveContent": "Offensive Content",
"abuseReportTypePrivacyViolation": "Privacy Violation",
"abuseReportTypeIllegalContent": "Illegal Content",
"abuseReportTypeOther": "Other"
"abuseReportTypeOther": "Other",
"tags": "Tags",
"tagsHint": "Enter tags, separated by commas",
"categories": "Categories",
"categoriesHint": "Enter categories, separated by commas",
"chatNotJoined": "You have not joined this chat yet.",
"chatUnableJoin": "You can't join this chat due to it's access control settings.",
"chatJoin": "Join the Chat",
"realmJoin": "Join the Realm",
"realmJoinSuccess": "Successfully joined the realm.",
"discoverRealms": "Discover Realms",
"discoverPublishers": "Discover Publishers",
"search": "Search"
}

View File

@ -857,7 +857,7 @@
INFOPLIST_FILE = SolianShareExtension/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = SolianShareExtension;
INFOPLIST_KEY_NSHumanReadableCopyright = "";
IPHONEOS_DEPLOYMENT_TARGET = 18.5;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
@ -900,7 +900,7 @@
INFOPLIST_FILE = SolianShareExtension/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = SolianShareExtension;
INFOPLIST_KEY_NSHumanReadableCopyright = "";
IPHONEOS_DEPLOYMENT_TARGET = 18.5;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
@ -940,7 +940,7 @@
INFOPLIST_FILE = SolianShareExtension/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = SolianShareExtension;
INFOPLIST_KEY_NSHumanReadableCopyright = "";
IPHONEOS_DEPLOYMENT_TARGET = 18.5;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
@ -979,7 +979,7 @@
INFOPLIST_FILE = SolianNotificationService/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = SolianNotificationService;
INFOPLIST_KEY_NSHumanReadableCopyright = "";
IPHONEOS_DEPLOYMENT_TARGET = 18.5;
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
@ -1021,7 +1021,7 @@
INFOPLIST_FILE = SolianNotificationService/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = SolianNotificationService;
INFOPLIST_KEY_NSHumanReadableCopyright = "";
IPHONEOS_DEPLOYMENT_TARGET = 18.5;
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
@ -1060,7 +1060,7 @@
INFOPLIST_FILE = SolianNotificationService/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = SolianNotificationService;
INFOPLIST_KEY_NSHumanReadableCopyright = "";
IPHONEOS_DEPLOYMENT_TARGET = 18.5;
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",

View File

@ -11,6 +11,21 @@ import UIKit
) -> Bool {
UNUserNotificationCenter.current().delegate = notifyDelegate
let replyableMessageCategory = UNNotificationCategory(
identifier: "REPLYABLE_MESSAGE",
actions: [
UNTextInputNotificationAction(
identifier: "reply_action",
title: "Reply",
options: []
),
],
intentIdentifiers: [],
options: []
)
UNUserNotificationCenter.current().setNotificationCategories([replyableMessageCategory])
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}

View File

@ -10,40 +10,51 @@ import Alamofire
class NotifyDelegate: UIResponder, UNUserNotificationCenterDelegate {
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
if let textResponse = response as? UNTextInputNotificationResponse {
let content = response.notification.request.content
guard let metadata = content.userInfo["meta"] as? [AnyHashable: Any] else {
return
}
var token: String? = UserDefaults.standard.getFlutterToken()
if token == nil {
return
}
let serverUrl = UserDefaults.standard.getServerUrl()
let url = "\(serverUrl)/chat/\(metadata["room_id"] ?? "")/messages"
let parameters: [String: Any?] = [
"content": textResponse.userText,
"replied_message_id": metadata["message_id"]
]
AF.request(url, method: .post, parameters: parameters, encoding: JSONEncoding.default, headers: HTTPHeaders(
[HTTPHeader(name: "Authorization", value: "AtField \(token!)")]
))
.validate()
.responseString { response in
switch response.result {
case .success(_):
break
case .failure(let error):
print("Failed to send chat reply message: \(error)")
break
}
}
guard let textResponse = response as? UNTextInputNotificationResponse else {
completionHandler()
return
}
let content = response.notification.request.content
// Only handle replies for new messages
guard let notificationType = content.userInfo["type"] as? String, notificationType == "messages.new" else {
completionHandler()
return
}
guard let metadata = content.userInfo["meta"] as? [AnyHashable: Any] else {
completionHandler()
return
}
completionHandler()
guard let token = UserDefaults.standard.getFlutterToken() else {
completionHandler()
return
}
let serverUrl = UserDefaults.standard.getServerUrl()
let url = "\(serverUrl)/chat/\(metadata["room_id"] ?? "")/messages"
let parameters: [String: Any?] = [
"content": textResponse.userText,
"replied_message_id": metadata["message_id"]
]
AF.request(url, method: .post, parameters: parameters, encoding: JSONEncoding.default, headers: HTTPHeaders(
[HTTPHeader(name: "Authorization", value: "AtField \(token)")]
))
.validate()
.responseString { response in
switch response.result {
case .success(_):
break
case .failure(let error):
print("Failed to send chat reply message: \(error)")
break
}
// Call completion handler after network request is finished
completionHandler()
}
}
}

View File

@ -60,21 +60,7 @@ class NotificationService: UNNotificationServiceExtension {
let pfpIdentifier = meta["pfp"] as? String
let replyableMessageCategory = UNNotificationCategory(
identifier: content.categoryIdentifier,
actions: [
UNTextInputNotificationAction(
identifier: "reply_action",
title: "Reply",
options: []
),
],
intentIdentifiers: [],
options: []
)
UNUserNotificationCenter.current().setNotificationCategories([replyableMessageCategory])
content.categoryIdentifier = replyableMessageCategory.identifier
content.categoryIdentifier = "REPLYABLE_MESSAGE"
let metaCopy = meta as? [String: Any] ?? [:]
let pfpUrl = pfpIdentifier != nil ? getAttachmentUrl(for: pfpIdentifier!) : nil

View File

@ -71,25 +71,32 @@ class MessageRepository {
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 it already synced with the remote, skip this
if (offset == 0 && !synced) {
// Fetch latest messages
_fetchAndCacheMessages(room.id, offset: offset, take: take);
if (localMessages.isNotEmpty) {
return localMessages;
}
// 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) {
// If API fails but we have local messages, return them
// Final fallback to cache in case of network errors during fetch.
final localMessages = await _getCachedMessages(
room.id,
offset: offset,
@ -117,24 +124,26 @@ class MessageRepository {
final dbLocalMessages =
dbMessages.map(_database.companionToMessage).toList();
// Combine with pending messages
final pendingForRoom =
pendingMessages.values.where((msg) => msg.roomId == roomId).toList();
// Combine with pending messages for the first page
if (offset == 0) {
final pendingForRoom =
pendingMessages.values.where((msg) => msg.roomId == roomId).toList();
// Sort by timestamp descending (newest first)
final allMessages = [...pendingForRoom, ...dbLocalMessages];
allMessages.sort((a, b) => b.createdAt.compareTo(a.createdAt));
final allMessages = [...pendingForRoom, ...dbLocalMessages];
allMessages.sort((a, b) => b.createdAt.compareTo(a.createdAt));
// Apply pagination
if (offset >= allMessages.length) {
return [];
// 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;
}
final end =
(offset + take) > allMessages.length
? allMessages.length
: (offset + take);
return allMessages.sublist(offset, end);
return dbLocalMessages;
}
Future<List<LocalChatMessage>> _fetchAndCacheMessages(

View File

@ -7,6 +7,7 @@ import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:image_picker_android/image_picker_android.dart';
@ -29,6 +30,12 @@ import 'package:image_picker_platform_interface/image_picker_platform_interface.
import 'package:flutter_native_splash/flutter_native_splash.dart';
import 'package:url_launcher/url_launcher_string.dart';
@pragma('vm:entry-point')
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
log('Handling a background message: ${message.messageId}');
}
void main() async {
final widgetsBinding = WidgetsFlutterBinding.ensureInitialized();
if (!kIsWeb && (Platform.isAndroid || Platform.isIOS)) {
@ -43,6 +50,7 @@ void main() async {
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
log("[SplashScreen] Firebase is ready!");
} catch (err) {
showErrorAlert(err);
@ -151,17 +159,52 @@ class IslandApp extends HookConsumerWidget {
}
useEffect(() {
Future(() async {
RemoteMessage? initialMessage =
await FirebaseMessaging.instance.getInitialMessage();
if (initialMessage != null) {
handleMessage(initialMessage);
}
const channel = MethodChannel('dev.solsynth.solian/notifications');
FirebaseMessaging.onMessageOpenedApp.listen(handleMessage);
Future<void> handleInitialLink() async {
final String? link = await channel.invokeMethod('initialLink');
if (link != null) {
final router = ref.read(routerProvider);
router.go(link);
}
}
if (!kIsWeb && (Platform.isAndroid || Platform.isIOS)) {
handleInitialLink();
}
channel.setMethodCallHandler((call) async {
if (call.method == 'newLink') {
final String link = call.arguments;
final router = ref.read(routerProvider);
router.go(link);
}
});
return null;
// When the app is opened from a terminated state.
FirebaseMessaging.instance.getInitialMessage().then((message) {
if (message != null) {
handleMessage(message);
}
});
// When the app is in the background and opened.
final onMessageOpenedAppSubscription = FirebaseMessaging
.onMessageOpenedApp
.listen(handleMessage);
// When the app is in the foreground.
final onMessageSubscription = FirebaseMessaging.onMessage.listen((
message,
) {
log('Foreground message received: ${message.messageId}');
handleMessage(message);
});
return () {
onMessageOpenedAppSubscription.cancel();
onMessageSubscription.cancel();
};
}, []);
useEffect(() {
@ -185,7 +228,7 @@ class IslandApp extends HookConsumerWidget {
}, []);
final router = ref.watch(routerProvider);
return MaterialApp.router(
theme: theme?.light,
darkTheme: theme?.dark,
@ -204,9 +247,8 @@ class IslandApp extends HookConsumerWidget {
initialEntries: [
OverlayEntry(
builder:
(_) => WindowScaffold(
child: child ?? const SizedBox.shrink(),
),
(_) =>
WindowScaffold(child: child ?? const SizedBox.shrink()),
),
],
);

View File

@ -26,6 +26,7 @@ $SnActivityCopyWith<SnActivity> get copyWith => _$SnActivityCopyWithImpl<SnActiv
/// Serializes this SnActivity to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnActivity&&(identical(other.id, id) || other.id == id)&&(identical(other.type, type) || other.type == type)&&(identical(other.resourceIdentifier, resourceIdentifier) || other.resourceIdentifier == resourceIdentifier)&&const DeepCollectionEquality().equals(other.data, data)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt));
@ -40,6 +41,7 @@ String toString() {
return 'SnActivity(id: $id, type: $type, resourceIdentifier: $resourceIdentifier, data: $data, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
}
}
/// @nodoc
@ -50,6 +52,9 @@ $Res call({
String id, String type, String resourceIdentifier, dynamic data, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
});
}
/// @nodoc
class _$SnActivityCopyWithImpl<$Res>
@ -76,6 +81,7 @@ as DateTime?,
}
/// @nodoc
@JsonSerializable()
@ -116,6 +122,7 @@ String toString() {
return 'SnActivity(id: $id, type: $type, resourceIdentifier: $resourceIdentifier, data: $data, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
}
}
/// @nodoc
@ -126,6 +133,9 @@ $Res call({
String id, String type, String resourceIdentifier, dynamic data, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
});
}
/// @nodoc
class __$SnActivityCopyWithImpl<$Res>
@ -150,8 +160,10 @@ as DateTime?,
));
}
}
/// @nodoc
mixin _$SnCheckInResult {
@ -165,6 +177,7 @@ $SnCheckInResultCopyWith<SnCheckInResult> get copyWith => _$SnCheckInResultCopyW
/// Serializes this SnCheckInResult to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnCheckInResult&&(identical(other.id, id) || other.id == id)&&(identical(other.level, level) || other.level == level)&&const DeepCollectionEquality().equals(other.tips, tips)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.account, account) || other.account == account)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt));
@ -179,6 +192,7 @@ String toString() {
return 'SnCheckInResult(id: $id, level: $level, tips: $tips, accountId: $accountId, account: $account, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
}
}
/// @nodoc
@ -189,6 +203,7 @@ $Res call({
String id, int level, List<SnFortuneTip> tips, String accountId, SnAccount? account, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
});
$SnAccountCopyWith<$Res>? get account;
}
@ -230,6 +245,7 @@ $SnAccountCopyWith<$Res>? get account {
}
}
/// @nodoc
@JsonSerializable()
@ -277,6 +293,7 @@ String toString() {
return 'SnCheckInResult(id: $id, level: $level, tips: $tips, accountId: $accountId, account: $account, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
}
}
/// @nodoc
@ -287,6 +304,7 @@ $Res call({
String id, int level, List<SnFortuneTip> tips, String accountId, SnAccount? account, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
});
@override $SnAccountCopyWith<$Res>? get account;
}
@ -329,6 +347,7 @@ $SnAccountCopyWith<$Res>? get account {
}
}
/// @nodoc
mixin _$SnFortuneTip {
@ -342,6 +361,7 @@ $SnFortuneTipCopyWith<SnFortuneTip> get copyWith => _$SnFortuneTipCopyWithImpl<S
/// Serializes this SnFortuneTip to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnFortuneTip&&(identical(other.isPositive, isPositive) || other.isPositive == isPositive)&&(identical(other.title, title) || other.title == title)&&(identical(other.content, content) || other.content == content));
@ -356,6 +376,7 @@ String toString() {
return 'SnFortuneTip(isPositive: $isPositive, title: $title, content: $content)';
}
}
/// @nodoc
@ -366,6 +387,9 @@ $Res call({
bool isPositive, String title, String content
});
}
/// @nodoc
class _$SnFortuneTipCopyWithImpl<$Res>
@ -388,6 +412,7 @@ as String,
}
/// @nodoc
@JsonSerializable()
@ -424,6 +449,7 @@ String toString() {
return 'SnFortuneTip(isPositive: $isPositive, title: $title, content: $content)';
}
}
/// @nodoc
@ -434,6 +460,9 @@ $Res call({
bool isPositive, String title, String content
});
}
/// @nodoc
class __$SnFortuneTipCopyWithImpl<$Res>
@ -454,8 +483,10 @@ as String,
));
}
}
/// @nodoc
mixin _$SnEventCalendarEntry {
@ -469,6 +500,7 @@ $SnEventCalendarEntryCopyWith<SnEventCalendarEntry> get copyWith => _$SnEventCal
/// Serializes this SnEventCalendarEntry to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnEventCalendarEntry&&(identical(other.date, date) || other.date == date)&&(identical(other.checkInResult, checkInResult) || other.checkInResult == checkInResult)&&const DeepCollectionEquality().equals(other.statuses, statuses));
@ -483,6 +515,7 @@ String toString() {
return 'SnEventCalendarEntry(date: $date, checkInResult: $checkInResult, statuses: $statuses)';
}
}
/// @nodoc
@ -493,6 +526,7 @@ $Res call({
DateTime date, SnCheckInResult? checkInResult, List<dynamic> statuses
});
$SnCheckInResultCopyWith<$Res>? get checkInResult;
}
@ -529,6 +563,7 @@ $SnCheckInResultCopyWith<$Res>? get checkInResult {
}
}
/// @nodoc
@JsonSerializable()
@ -545,6 +580,7 @@ class _SnEventCalendarEntry implements SnEventCalendarEntry {
return EqualUnmodifiableListView(_statuses);
}
/// Create a copy of SnEventCalendarEntry
/// with the given fields replaced by the non-null parameter values.
@override @JsonKey(includeFromJson: false, includeToJson: false)
@ -570,6 +606,7 @@ String toString() {
return 'SnEventCalendarEntry(date: $date, checkInResult: $checkInResult, statuses: $statuses)';
}
}
/// @nodoc
@ -580,6 +617,7 @@ $Res call({
DateTime date, SnCheckInResult? checkInResult, List<dynamic> statuses
});
@override $SnCheckInResultCopyWith<$Res>? get checkInResult;
}

View File

@ -26,6 +26,7 @@ $AppTokenCopyWith<AppToken> get copyWith => _$AppTokenCopyWithImpl<AppToken>(thi
/// Serializes this AppToken to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is AppToken&&(identical(other.token, token) || other.token == token));
@ -40,6 +41,7 @@ String toString() {
return 'AppToken(token: $token)';
}
}
/// @nodoc
@ -50,6 +52,9 @@ $Res call({
String token
});
}
/// @nodoc
class _$AppTokenCopyWithImpl<$Res>
@ -70,6 +75,7 @@ as String,
}
/// @nodoc
@JsonSerializable()
@ -104,6 +110,7 @@ String toString() {
return 'AppToken(token: $token)';
}
}
/// @nodoc
@ -114,6 +121,9 @@ $Res call({
String token
});
}
/// @nodoc
class __$AppTokenCopyWithImpl<$Res>
@ -132,8 +142,10 @@ as String,
));
}
}
/// @nodoc
mixin _$SnAuthChallenge {
@ -147,6 +159,7 @@ $SnAuthChallengeCopyWith<SnAuthChallenge> get copyWith => _$SnAuthChallengeCopyW
/// Serializes this SnAuthChallenge to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnAuthChallenge&&(identical(other.id, id) || other.id == id)&&(identical(other.expiredAt, expiredAt) || other.expiredAt == expiredAt)&&(identical(other.stepRemain, stepRemain) || other.stepRemain == stepRemain)&&(identical(other.stepTotal, stepTotal) || other.stepTotal == stepTotal)&&(identical(other.failedAttempts, failedAttempts) || other.failedAttempts == failedAttempts)&&(identical(other.platform, platform) || other.platform == platform)&&(identical(other.type, type) || other.type == type)&&const DeepCollectionEquality().equals(other.blacklistFactors, blacklistFactors)&&const DeepCollectionEquality().equals(other.audiences, audiences)&&const DeepCollectionEquality().equals(other.scopes, scopes)&&(identical(other.ipAddress, ipAddress) || other.ipAddress == ipAddress)&&(identical(other.userAgent, userAgent) || other.userAgent == userAgent)&&(identical(other.deviceId, deviceId) || other.deviceId == deviceId)&&(identical(other.nonce, nonce) || other.nonce == nonce)&&(identical(other.location, location) || other.location == location)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt));
@ -161,6 +174,7 @@ String toString() {
return 'SnAuthChallenge(id: $id, expiredAt: $expiredAt, stepRemain: $stepRemain, stepTotal: $stepTotal, failedAttempts: $failedAttempts, platform: $platform, type: $type, blacklistFactors: $blacklistFactors, audiences: $audiences, scopes: $scopes, ipAddress: $ipAddress, userAgent: $userAgent, deviceId: $deviceId, nonce: $nonce, location: $location, accountId: $accountId, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
}
}
/// @nodoc
@ -171,6 +185,9 @@ $Res call({
String id, DateTime expiredAt, int stepRemain, int stepTotal, int failedAttempts, int platform, int type, List<String> blacklistFactors, List<dynamic> audiences, List<dynamic> scopes, String ipAddress, String userAgent, String deviceId, String? nonce, String? location, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
});
}
/// @nodoc
class _$SnAuthChallengeCopyWithImpl<$Res>
@ -209,6 +226,7 @@ as DateTime?,
}
/// @nodoc
@JsonSerializable()
@ -279,6 +297,7 @@ String toString() {
return 'SnAuthChallenge(id: $id, expiredAt: $expiredAt, stepRemain: $stepRemain, stepTotal: $stepTotal, failedAttempts: $failedAttempts, platform: $platform, type: $type, blacklistFactors: $blacklistFactors, audiences: $audiences, scopes: $scopes, ipAddress: $ipAddress, userAgent: $userAgent, deviceId: $deviceId, nonce: $nonce, location: $location, accountId: $accountId, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
}
}
/// @nodoc
@ -289,6 +308,9 @@ $Res call({
String id, DateTime expiredAt, int stepRemain, int stepTotal, int failedAttempts, int platform, int type, List<String> blacklistFactors, List<dynamic> audiences, List<dynamic> scopes, String ipAddress, String userAgent, String deviceId, String? nonce, String? location, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
});
}
/// @nodoc
class __$SnAuthChallengeCopyWithImpl<$Res>
@ -325,8 +347,10 @@ as DateTime?,
));
}
}
/// @nodoc
mixin _$SnAuthSession {
@ -340,6 +364,7 @@ $SnAuthSessionCopyWith<SnAuthSession> get copyWith => _$SnAuthSessionCopyWithImp
/// Serializes this SnAuthSession to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnAuthSession&&(identical(other.id, id) || other.id == id)&&(identical(other.label, label) || other.label == label)&&(identical(other.lastGrantedAt, lastGrantedAt) || other.lastGrantedAt == lastGrantedAt)&&(identical(other.expiredAt, expiredAt) || other.expiredAt == expiredAt)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.challengeId, challengeId) || other.challengeId == challengeId)&&(identical(other.challenge, challenge) || other.challenge == challenge)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt));
@ -354,6 +379,7 @@ String toString() {
return 'SnAuthSession(id: $id, label: $label, lastGrantedAt: $lastGrantedAt, expiredAt: $expiredAt, accountId: $accountId, challengeId: $challengeId, challenge: $challenge, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
}
}
/// @nodoc
@ -364,6 +390,7 @@ $Res call({
String id, String? label, DateTime lastGrantedAt, DateTime expiredAt, String accountId, String challengeId, SnAuthChallenge challenge, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
});
$SnAuthChallengeCopyWith<$Res> get challenge;
}
@ -404,6 +431,7 @@ $SnAuthChallengeCopyWith<$Res> get challenge {
}
}
/// @nodoc
@JsonSerializable()
@ -447,6 +475,7 @@ String toString() {
return 'SnAuthSession(id: $id, label: $label, lastGrantedAt: $lastGrantedAt, expiredAt: $expiredAt, accountId: $accountId, challengeId: $challengeId, challenge: $challenge, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
}
}
/// @nodoc
@ -457,6 +486,7 @@ $Res call({
String id, String? label, DateTime lastGrantedAt, DateTime expiredAt, String accountId, String challengeId, SnAuthChallenge challenge, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
});
@override $SnAuthChallengeCopyWith<$Res> get challenge;
}
@ -498,6 +528,7 @@ $SnAuthChallengeCopyWith<$Res> get challenge {
}
}
/// @nodoc
mixin _$SnAuthFactor {
@ -511,6 +542,7 @@ $SnAuthFactorCopyWith<SnAuthFactor> get copyWith => _$SnAuthFactorCopyWithImpl<S
/// Serializes this SnAuthFactor to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnAuthFactor&&(identical(other.id, id) || other.id == id)&&(identical(other.type, type) || other.type == type)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)&&(identical(other.expiredAt, expiredAt) || other.expiredAt == expiredAt)&&(identical(other.enabledAt, enabledAt) || other.enabledAt == enabledAt)&&(identical(other.trustworthy, trustworthy) || other.trustworthy == trustworthy)&&const DeepCollectionEquality().equals(other.createdResponse, createdResponse));
@ -525,6 +557,7 @@ String toString() {
return 'SnAuthFactor(id: $id, type: $type, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, expiredAt: $expiredAt, enabledAt: $enabledAt, trustworthy: $trustworthy, createdResponse: $createdResponse)';
}
}
/// @nodoc
@ -535,6 +568,9 @@ $Res call({
String id, int type, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, DateTime? expiredAt, DateTime? enabledAt, int trustworthy, Map<String, dynamic>? createdResponse
});
}
/// @nodoc
class _$SnAuthFactorCopyWithImpl<$Res>
@ -563,6 +599,7 @@ as Map<String, dynamic>?,
}
/// @nodoc
@JsonSerializable()
@ -587,6 +624,7 @@ class _SnAuthFactor implements SnAuthFactor {
return EqualUnmodifiableMapView(value);
}
/// Create a copy of SnAuthFactor
/// with the given fields replaced by the non-null parameter values.
@override @JsonKey(includeFromJson: false, includeToJson: false)
@ -612,6 +650,7 @@ String toString() {
return 'SnAuthFactor(id: $id, type: $type, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, expiredAt: $expiredAt, enabledAt: $enabledAt, trustworthy: $trustworthy, createdResponse: $createdResponse)';
}
}
/// @nodoc
@ -622,6 +661,9 @@ $Res call({
String id, int type, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, DateTime? expiredAt, DateTime? enabledAt, int trustworthy, Map<String, dynamic>? createdResponse
});
}
/// @nodoc
class __$SnAuthFactorCopyWithImpl<$Res>
@ -648,8 +690,10 @@ as Map<String, dynamic>?,
));
}
}
/// @nodoc
mixin _$SnAuthDevice {
@ -664,6 +708,7 @@ $SnAuthDeviceCopyWith<SnAuthDevice> get copyWith => _$SnAuthDeviceCopyWithImpl<S
/// Serializes this SnAuthDevice to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnAuthDevice&&const DeepCollectionEquality().equals(other.label, label)&&(identical(other.userAgent, userAgent) || other.userAgent == userAgent)&&(identical(other.deviceId, deviceId) || other.deviceId == deviceId)&&(identical(other.platform, platform) || other.platform == platform)&&const DeepCollectionEquality().equals(other.sessions, sessions)&&(identical(other.isCurrent, isCurrent) || other.isCurrent == isCurrent));
@ -678,6 +723,7 @@ String toString() {
return 'SnAuthDevice(label: $label, userAgent: $userAgent, deviceId: $deviceId, platform: $platform, sessions: $sessions, isCurrent: $isCurrent)';
}
}
/// @nodoc
@ -688,6 +734,9 @@ $Res call({
dynamic label, String userAgent, String deviceId, int platform, List<SnAuthSession> sessions, bool isCurrent
});
}
/// @nodoc
class _$SnAuthDeviceCopyWithImpl<$Res>
@ -713,6 +762,7 @@ as bool,
}
/// @nodoc
@JsonSerializable()
@ -759,6 +809,7 @@ String toString() {
return 'SnAuthDevice(label: $label, userAgent: $userAgent, deviceId: $deviceId, platform: $platform, sessions: $sessions, isCurrent: $isCurrent)';
}
}
/// @nodoc
@ -769,6 +820,9 @@ $Res call({
dynamic label, String userAgent, String deviceId, int platform, List<SnAuthSession> sessions, bool isCurrent
});
}
/// @nodoc
class __$SnAuthDeviceCopyWithImpl<$Res>
@ -792,8 +846,10 @@ as bool,
));
}
}
/// @nodoc
mixin _$SnAccountConnection {
@ -807,6 +863,7 @@ $SnAccountConnectionCopyWith<SnAccountConnection> get copyWith => _$SnAccountCon
/// Serializes this SnAccountConnection to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnAccountConnection&&(identical(other.id, id) || other.id == id)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.provider, provider) || other.provider == provider)&&(identical(other.providedIdentifier, providedIdentifier) || other.providedIdentifier == providedIdentifier)&&const DeepCollectionEquality().equals(other.meta, meta)&&(identical(other.lastUsedAt, lastUsedAt) || other.lastUsedAt == lastUsedAt)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt));
@ -821,6 +878,7 @@ String toString() {
return 'SnAccountConnection(id: $id, accountId: $accountId, provider: $provider, providedIdentifier: $providedIdentifier, meta: $meta, lastUsedAt: $lastUsedAt, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
}
}
/// @nodoc
@ -831,6 +889,9 @@ $Res call({
String id, String accountId, String provider, String providedIdentifier, Map<String, dynamic> meta, DateTime lastUsedAt, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
});
}
/// @nodoc
class _$SnAccountConnectionCopyWithImpl<$Res>
@ -859,6 +920,7 @@ as DateTime?,
}
/// @nodoc
@JsonSerializable()
@ -907,6 +969,7 @@ String toString() {
return 'SnAccountConnection(id: $id, accountId: $accountId, provider: $provider, providedIdentifier: $providedIdentifier, meta: $meta, lastUsedAt: $lastUsedAt, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
}
}
/// @nodoc
@ -917,6 +980,9 @@ $Res call({
String id, String accountId, String provider, String providedIdentifier, Map<String, dynamic> meta, DateTime lastUsedAt, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
});
}
/// @nodoc
class __$SnAccountConnectionCopyWithImpl<$Res>
@ -943,6 +1009,7 @@ as DateTime?,
));
}
}
// dart format on

View File

@ -13,7 +13,8 @@ sealed class SnChatRoom with _$SnChatRoom {
required String? name,
required String? description,
required int type,
required bool isPublic,
@Default(false) bool isPublic,
@Default(false) bool isCommunity,
required SnCloudFile? picture,
required SnCloudFile? background,
required String? realmId,

View File

@ -16,7 +16,7 @@ T _$identity<T>(T value) => value;
/// @nodoc
mixin _$SnChatRoom {
String get id; String? get name; String? get description; int get type; bool get isPublic; SnCloudFile? get picture; SnCloudFile? get background; String? get realmId; SnRealm? get realm; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt; List<SnChatMember>? get members;
String get id; String? get name; String? get description; int get type; bool get isPublic; bool get isCommunity; SnCloudFile? get picture; SnCloudFile? get background; String? get realmId; SnRealm? get realm; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt; List<SnChatMember>? get members;
/// Create a copy of SnChatRoom
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@ -26,20 +26,22 @@ $SnChatRoomCopyWith<SnChatRoom> get copyWith => _$SnChatRoomCopyWithImpl<SnChatR
/// Serializes this SnChatRoom to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnChatRoom&&(identical(other.id, id) || other.id == id)&&(identical(other.name, name) || other.name == name)&&(identical(other.description, description) || other.description == description)&&(identical(other.type, type) || other.type == type)&&(identical(other.isPublic, isPublic) || other.isPublic == isPublic)&&(identical(other.picture, picture) || other.picture == picture)&&(identical(other.background, background) || other.background == background)&&(identical(other.realmId, realmId) || other.realmId == realmId)&&(identical(other.realm, realm) || other.realm == realm)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)&&const DeepCollectionEquality().equals(other.members, members));
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnChatRoom&&(identical(other.id, id) || other.id == id)&&(identical(other.name, name) || other.name == name)&&(identical(other.description, description) || other.description == description)&&(identical(other.type, type) || other.type == type)&&(identical(other.isPublic, isPublic) || other.isPublic == isPublic)&&(identical(other.isCommunity, isCommunity) || other.isCommunity == isCommunity)&&(identical(other.picture, picture) || other.picture == picture)&&(identical(other.background, background) || other.background == background)&&(identical(other.realmId, realmId) || other.realmId == realmId)&&(identical(other.realm, realm) || other.realm == realm)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)&&const DeepCollectionEquality().equals(other.members, members));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType,id,name,description,type,isPublic,picture,background,realmId,realm,createdAt,updatedAt,deletedAt,const DeepCollectionEquality().hash(members));
int get hashCode => Object.hash(runtimeType,id,name,description,type,isPublic,isCommunity,picture,background,realmId,realm,createdAt,updatedAt,deletedAt,const DeepCollectionEquality().hash(members));
@override
String toString() {
return 'SnChatRoom(id: $id, name: $name, description: $description, type: $type, isPublic: $isPublic, picture: $picture, background: $background, realmId: $realmId, realm: $realm, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, members: $members)';
return 'SnChatRoom(id: $id, name: $name, description: $description, type: $type, isPublic: $isPublic, isCommunity: $isCommunity, picture: $picture, background: $background, realmId: $realmId, realm: $realm, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, members: $members)';
}
}
/// @nodoc
@ -47,9 +49,10 @@ abstract mixin class $SnChatRoomCopyWith<$Res> {
factory $SnChatRoomCopyWith(SnChatRoom value, $Res Function(SnChatRoom) _then) = _$SnChatRoomCopyWithImpl;
@useResult
$Res call({
String id, String? name, String? description, int type, bool isPublic, SnCloudFile? picture, SnCloudFile? background, String? realmId, SnRealm? realm, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, List<SnChatMember>? members
String id, String? name, String? description, int type, bool isPublic, bool isCommunity, SnCloudFile? picture, SnCloudFile? background, String? realmId, SnRealm? realm, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, List<SnChatMember>? members
});
$SnCloudFileCopyWith<$Res>? get picture;$SnCloudFileCopyWith<$Res>? get background;$SnRealmCopyWith<$Res>? get realm;
}
@ -63,13 +66,14 @@ class _$SnChatRoomCopyWithImpl<$Res>
/// Create a copy of SnChatRoom
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? name = freezed,Object? description = freezed,Object? type = null,Object? isPublic = null,Object? picture = freezed,Object? background = freezed,Object? realmId = freezed,Object? realm = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,Object? members = freezed,}) {
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? name = freezed,Object? description = freezed,Object? type = null,Object? isPublic = null,Object? isCommunity = null,Object? picture = freezed,Object? background = freezed,Object? realmId = freezed,Object? realm = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,Object? members = freezed,}) {
return _then(_self.copyWith(
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
as String,name: freezed == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
as String?,description: freezed == description ? _self.description : description // ignore: cast_nullable_to_non_nullable
as String?,type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable
as int,isPublic: null == isPublic ? _self.isPublic : isPublic // ignore: cast_nullable_to_non_nullable
as bool,isCommunity: null == isCommunity ? _self.isCommunity : isCommunity // ignore: cast_nullable_to_non_nullable
as bool,picture: freezed == picture ? _self.picture : picture // ignore: cast_nullable_to_non_nullable
as SnCloudFile?,background: freezed == background ? _self.background : background // ignore: cast_nullable_to_non_nullable
as SnCloudFile?,realmId: freezed == realmId ? _self.realmId : realmId // ignore: cast_nullable_to_non_nullable
@ -120,18 +124,20 @@ $SnRealmCopyWith<$Res>? get realm {
}
}
/// @nodoc
@JsonSerializable()
class _SnChatRoom implements SnChatRoom {
const _SnChatRoom({required this.id, required this.name, required this.description, required this.type, required this.isPublic, required this.picture, required this.background, required this.realmId, required this.realm, required this.createdAt, required this.updatedAt, required this.deletedAt, required final List<SnChatMember>? members}): _members = members;
const _SnChatRoom({required this.id, required this.name, required this.description, required this.type, this.isPublic = false, this.isCommunity = false, required this.picture, required this.background, required this.realmId, required this.realm, required this.createdAt, required this.updatedAt, required this.deletedAt, required final List<SnChatMember>? members}): _members = members;
factory _SnChatRoom.fromJson(Map<String, dynamic> json) => _$SnChatRoomFromJson(json);
@override final String id;
@override final String? name;
@override final String? description;
@override final int type;
@override final bool isPublic;
@override@JsonKey() final bool isPublic;
@override@JsonKey() final bool isCommunity;
@override final SnCloudFile? picture;
@override final SnCloudFile? background;
@override final String? realmId;
@ -148,6 +154,7 @@ class _SnChatRoom implements SnChatRoom {
return EqualUnmodifiableListView(value);
}
/// Create a copy of SnChatRoom
/// with the given fields replaced by the non-null parameter values.
@override @JsonKey(includeFromJson: false, includeToJson: false)
@ -161,18 +168,19 @@ Map<String, dynamic> toJson() {
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnChatRoom&&(identical(other.id, id) || other.id == id)&&(identical(other.name, name) || other.name == name)&&(identical(other.description, description) || other.description == description)&&(identical(other.type, type) || other.type == type)&&(identical(other.isPublic, isPublic) || other.isPublic == isPublic)&&(identical(other.picture, picture) || other.picture == picture)&&(identical(other.background, background) || other.background == background)&&(identical(other.realmId, realmId) || other.realmId == realmId)&&(identical(other.realm, realm) || other.realm == realm)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)&&const DeepCollectionEquality().equals(other._members, _members));
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnChatRoom&&(identical(other.id, id) || other.id == id)&&(identical(other.name, name) || other.name == name)&&(identical(other.description, description) || other.description == description)&&(identical(other.type, type) || other.type == type)&&(identical(other.isPublic, isPublic) || other.isPublic == isPublic)&&(identical(other.isCommunity, isCommunity) || other.isCommunity == isCommunity)&&(identical(other.picture, picture) || other.picture == picture)&&(identical(other.background, background) || other.background == background)&&(identical(other.realmId, realmId) || other.realmId == realmId)&&(identical(other.realm, realm) || other.realm == realm)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)&&const DeepCollectionEquality().equals(other._members, _members));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType,id,name,description,type,isPublic,picture,background,realmId,realm,createdAt,updatedAt,deletedAt,const DeepCollectionEquality().hash(_members));
int get hashCode => Object.hash(runtimeType,id,name,description,type,isPublic,isCommunity,picture,background,realmId,realm,createdAt,updatedAt,deletedAt,const DeepCollectionEquality().hash(_members));
@override
String toString() {
return 'SnChatRoom(id: $id, name: $name, description: $description, type: $type, isPublic: $isPublic, picture: $picture, background: $background, realmId: $realmId, realm: $realm, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, members: $members)';
return 'SnChatRoom(id: $id, name: $name, description: $description, type: $type, isPublic: $isPublic, isCommunity: $isCommunity, picture: $picture, background: $background, realmId: $realmId, realm: $realm, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, members: $members)';
}
}
/// @nodoc
@ -180,9 +188,10 @@ abstract mixin class _$SnChatRoomCopyWith<$Res> implements $SnChatRoomCopyWith<$
factory _$SnChatRoomCopyWith(_SnChatRoom value, $Res Function(_SnChatRoom) _then) = __$SnChatRoomCopyWithImpl;
@override @useResult
$Res call({
String id, String? name, String? description, int type, bool isPublic, SnCloudFile? picture, SnCloudFile? background, String? realmId, SnRealm? realm, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, List<SnChatMember>? members
String id, String? name, String? description, int type, bool isPublic, bool isCommunity, SnCloudFile? picture, SnCloudFile? background, String? realmId, SnRealm? realm, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, List<SnChatMember>? members
});
@override $SnCloudFileCopyWith<$Res>? get picture;@override $SnCloudFileCopyWith<$Res>? get background;@override $SnRealmCopyWith<$Res>? get realm;
}
@ -196,13 +205,14 @@ class __$SnChatRoomCopyWithImpl<$Res>
/// Create a copy of SnChatRoom
/// with the given fields replaced by the non-null parameter values.
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? name = freezed,Object? description = freezed,Object? type = null,Object? isPublic = null,Object? picture = freezed,Object? background = freezed,Object? realmId = freezed,Object? realm = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,Object? members = freezed,}) {
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? name = freezed,Object? description = freezed,Object? type = null,Object? isPublic = null,Object? isCommunity = null,Object? picture = freezed,Object? background = freezed,Object? realmId = freezed,Object? realm = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,Object? members = freezed,}) {
return _then(_SnChatRoom(
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
as String,name: freezed == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
as String?,description: freezed == description ? _self.description : description // ignore: cast_nullable_to_non_nullable
as String?,type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable
as int,isPublic: null == isPublic ? _self.isPublic : isPublic // ignore: cast_nullable_to_non_nullable
as bool,isCommunity: null == isCommunity ? _self.isCommunity : isCommunity // ignore: cast_nullable_to_non_nullable
as bool,picture: freezed == picture ? _self.picture : picture // ignore: cast_nullable_to_non_nullable
as SnCloudFile?,background: freezed == background ? _self.background : background // ignore: cast_nullable_to_non_nullable
as SnCloudFile?,realmId: freezed == realmId ? _self.realmId : realmId // ignore: cast_nullable_to_non_nullable
@ -254,6 +264,7 @@ $SnRealmCopyWith<$Res>? get realm {
}
}
/// @nodoc
mixin _$SnChatMessage {
@ -267,6 +278,7 @@ $SnChatMessageCopyWith<SnChatMessage> get copyWith => _$SnChatMessageCopyWithImp
/// Serializes this SnChatMessage to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnChatMessage&&(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.type, type) || other.type == type)&&(identical(other.content, content) || other.content == content)&&(identical(other.nonce, nonce) || other.nonce == nonce)&&const DeepCollectionEquality().equals(other.meta, meta)&&const DeepCollectionEquality().equals(other.membersMetioned, membersMetioned)&&(identical(other.editedAt, editedAt) || other.editedAt == editedAt)&&const DeepCollectionEquality().equals(other.attachments, attachments)&&const DeepCollectionEquality().equals(other.reactions, reactions)&&(identical(other.repliedMessageId, repliedMessageId) || other.repliedMessageId == repliedMessageId)&&(identical(other.forwardedMessageId, forwardedMessageId) || other.forwardedMessageId == forwardedMessageId)&&(identical(other.senderId, senderId) || other.senderId == senderId)&&(identical(other.sender, sender) || other.sender == sender)&&(identical(other.chatRoomId, chatRoomId) || other.chatRoomId == chatRoomId));
@ -281,6 +293,7 @@ String toString() {
return 'SnChatMessage(createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, id: $id, type: $type, content: $content, nonce: $nonce, meta: $meta, membersMetioned: $membersMetioned, editedAt: $editedAt, attachments: $attachments, reactions: $reactions, repliedMessageId: $repliedMessageId, forwardedMessageId: $forwardedMessageId, senderId: $senderId, sender: $sender, chatRoomId: $chatRoomId)';
}
}
/// @nodoc
@ -291,6 +304,7 @@ $Res call({
DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, String id, String type, String? content, String? nonce, Map<String, dynamic> meta, List<String> membersMetioned, DateTime? editedAt, List<SnCloudFile> attachments, List<SnChatReaction> reactions, String? repliedMessageId, String? forwardedMessageId, String senderId, SnChatMember sender, String chatRoomId
});
$SnChatMemberCopyWith<$Res> get sender;
}
@ -338,6 +352,7 @@ $SnChatMemberCopyWith<$Res> get sender {
}
}
/// @nodoc
@JsonSerializable()
@ -412,6 +427,7 @@ String toString() {
return 'SnChatMessage(createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, id: $id, type: $type, content: $content, nonce: $nonce, meta: $meta, membersMetioned: $membersMetioned, editedAt: $editedAt, attachments: $attachments, reactions: $reactions, repliedMessageId: $repliedMessageId, forwardedMessageId: $forwardedMessageId, senderId: $senderId, sender: $sender, chatRoomId: $chatRoomId)';
}
}
/// @nodoc
@ -422,6 +438,7 @@ $Res call({
DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, String id, String type, String? content, String? nonce, Map<String, dynamic> meta, List<String> membersMetioned, DateTime? editedAt, List<SnCloudFile> attachments, List<SnChatReaction> reactions, String? repliedMessageId, String? forwardedMessageId, String senderId, SnChatMember sender, String chatRoomId
});
@override $SnChatMemberCopyWith<$Res> get sender;
}
@ -470,6 +487,7 @@ $SnChatMemberCopyWith<$Res> get sender {
}
}
/// @nodoc
mixin _$SnChatReaction {
@ -483,6 +501,7 @@ $SnChatReactionCopyWith<SnChatReaction> get copyWith => _$SnChatReactionCopyWith
/// Serializes this SnChatReaction to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnChatReaction&&(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.messageId, messageId) || other.messageId == messageId)&&(identical(other.senderId, senderId) || other.senderId == senderId)&&(identical(other.sender, sender) || other.sender == sender)&&(identical(other.symbol, symbol) || other.symbol == symbol)&&(identical(other.attitude, attitude) || other.attitude == attitude));
@ -497,6 +516,7 @@ String toString() {
return 'SnChatReaction(createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, id: $id, messageId: $messageId, senderId: $senderId, sender: $sender, symbol: $symbol, attitude: $attitude)';
}
}
/// @nodoc
@ -507,6 +527,7 @@ $Res call({
DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, String id, String messageId, String senderId, SnChatMember sender, String symbol, int attitude
});
$SnChatMemberCopyWith<$Res> get sender;
}
@ -546,6 +567,7 @@ $SnChatMemberCopyWith<$Res> get sender {
}
}
/// @nodoc
@JsonSerializable()
@ -588,6 +610,7 @@ String toString() {
return 'SnChatReaction(createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, id: $id, messageId: $messageId, senderId: $senderId, sender: $sender, symbol: $symbol, attitude: $attitude)';
}
}
/// @nodoc
@ -598,6 +621,7 @@ $Res call({
DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, String id, String messageId, String senderId, SnChatMember sender, String symbol, int attitude
});
@override $SnChatMemberCopyWith<$Res> get sender;
}
@ -638,6 +662,7 @@ $SnChatMemberCopyWith<$Res> get sender {
}
}
/// @nodoc
mixin _$SnChatMember {
@ -652,6 +677,7 @@ $SnChatMemberCopyWith<SnChatMember> get copyWith => _$SnChatMemberCopyWithImpl<S
/// Serializes this SnChatMember to a JSON map.
Map<String, dynamic> toJson();
@override
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));
@ -666,6 +692,7 @@ 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)';
}
}
/// @nodoc
@ -676,6 +703,7 @@ $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
});
$SnChatRoomCopyWith<$Res>? get chatRoom;$SnAccountCopyWith<$Res> get account;
}
@ -734,6 +762,7 @@ $SnAccountCopyWith<$Res> get account {
}
}
/// @nodoc
@JsonSerializable()
@ -784,6 +813,7 @@ 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)';
}
}
/// @nodoc
@ -794,6 +824,7 @@ $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
});
@override $SnChatRoomCopyWith<$Res>? get chatRoom;@override $SnAccountCopyWith<$Res> get account;
}
@ -853,6 +884,7 @@ $SnAccountCopyWith<$Res> get account {
}
}
/// @nodoc
mixin _$SnChatSummary {
@ -866,6 +898,7 @@ $SnChatSummaryCopyWith<SnChatSummary> get copyWith => _$SnChatSummaryCopyWithImp
/// Serializes this SnChatSummary to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnChatSummary&&(identical(other.unreadCount, unreadCount) || other.unreadCount == unreadCount)&&(identical(other.lastMessage, lastMessage) || other.lastMessage == lastMessage));
@ -880,6 +913,7 @@ String toString() {
return 'SnChatSummary(unreadCount: $unreadCount, lastMessage: $lastMessage)';
}
}
/// @nodoc
@ -890,6 +924,7 @@ $Res call({
int unreadCount, SnChatMessage lastMessage
});
$SnChatMessageCopyWith<$Res> get lastMessage;
}
@ -922,6 +957,7 @@ $SnChatMessageCopyWith<$Res> get lastMessage {
}
}
/// @nodoc
@JsonSerializable()
@ -957,6 +993,7 @@ String toString() {
return 'SnChatSummary(unreadCount: $unreadCount, lastMessage: $lastMessage)';
}
}
/// @nodoc
@ -967,6 +1004,7 @@ $Res call({
int unreadCount, SnChatMessage lastMessage
});
@override $SnChatMessageCopyWith<$Res> get lastMessage;
}
@ -1000,6 +1038,7 @@ $SnChatMessageCopyWith<$Res> get lastMessage {
}
}
/// @nodoc
mixin _$MessageChange {
@ -1013,6 +1052,7 @@ $MessageChangeCopyWith<MessageChange> get copyWith => _$MessageChangeCopyWithImp
/// Serializes this MessageChange to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is MessageChange&&(identical(other.messageId, messageId) || other.messageId == messageId)&&(identical(other.action, action) || other.action == action)&&(identical(other.message, message) || other.message == message)&&(identical(other.timestamp, timestamp) || other.timestamp == timestamp));
@ -1027,6 +1067,7 @@ String toString() {
return 'MessageChange(messageId: $messageId, action: $action, message: $message, timestamp: $timestamp)';
}
}
/// @nodoc
@ -1037,6 +1078,7 @@ $Res call({
String messageId, String action, SnChatMessage? message, DateTime timestamp
});
$SnChatMessageCopyWith<$Res>? get message;
}
@ -1074,6 +1116,7 @@ $SnChatMessageCopyWith<$Res>? get message {
}
}
/// @nodoc
@JsonSerializable()
@ -1111,6 +1154,7 @@ String toString() {
return 'MessageChange(messageId: $messageId, action: $action, message: $message, timestamp: $timestamp)';
}
}
/// @nodoc
@ -1121,6 +1165,7 @@ $Res call({
String messageId, String action, SnChatMessage? message, DateTime timestamp
});
@override $SnChatMessageCopyWith<$Res>? get message;
}
@ -1159,6 +1204,7 @@ $SnChatMessageCopyWith<$Res>? get message {
}
}
/// @nodoc
mixin _$MessageSyncResponse {
@ -1172,6 +1218,7 @@ $MessageSyncResponseCopyWith<MessageSyncResponse> get copyWith => _$MessageSyncR
/// Serializes this MessageSyncResponse to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is MessageSyncResponse&&const DeepCollectionEquality().equals(other.changes, changes)&&(identical(other.currentTimestamp, currentTimestamp) || other.currentTimestamp == currentTimestamp));
@ -1186,6 +1233,7 @@ String toString() {
return 'MessageSyncResponse(changes: $changes, currentTimestamp: $currentTimestamp)';
}
}
/// @nodoc
@ -1196,6 +1244,9 @@ $Res call({
List<MessageChange> changes, DateTime currentTimestamp
});
}
/// @nodoc
class _$MessageSyncResponseCopyWithImpl<$Res>
@ -1217,6 +1268,7 @@ as DateTime,
}
/// @nodoc
@JsonSerializable()
@ -1258,6 +1310,7 @@ String toString() {
return 'MessageSyncResponse(changes: $changes, currentTimestamp: $currentTimestamp)';
}
}
/// @nodoc
@ -1268,6 +1321,9 @@ $Res call({
List<MessageChange> changes, DateTime currentTimestamp
});
}
/// @nodoc
class __$MessageSyncResponseCopyWithImpl<$Res>
@ -1287,8 +1343,10 @@ as DateTime,
));
}
}
/// @nodoc
mixin _$ChatRealtimeJoinResponse {
@ -1302,6 +1360,7 @@ $ChatRealtimeJoinResponseCopyWith<ChatRealtimeJoinResponse> get copyWith => _$Ch
/// Serializes this ChatRealtimeJoinResponse to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is ChatRealtimeJoinResponse&&(identical(other.provider, provider) || other.provider == provider)&&(identical(other.endpoint, endpoint) || other.endpoint == endpoint)&&(identical(other.token, token) || other.token == token)&&(identical(other.callId, callId) || other.callId == callId)&&(identical(other.roomName, roomName) || other.roomName == roomName)&&(identical(other.isAdmin, isAdmin) || other.isAdmin == isAdmin)&&const DeepCollectionEquality().equals(other.participants, participants));
@ -1316,6 +1375,7 @@ String toString() {
return 'ChatRealtimeJoinResponse(provider: $provider, endpoint: $endpoint, token: $token, callId: $callId, roomName: $roomName, isAdmin: $isAdmin, participants: $participants)';
}
}
/// @nodoc
@ -1326,6 +1386,9 @@ $Res call({
String provider, String endpoint, String token, String callId, String roomName, bool isAdmin, List<CallParticipant> participants
});
}
/// @nodoc
class _$ChatRealtimeJoinResponseCopyWithImpl<$Res>
@ -1352,6 +1415,7 @@ as List<CallParticipant>,
}
/// @nodoc
@JsonSerializable()
@ -1372,6 +1436,7 @@ class _ChatRealtimeJoinResponse implements ChatRealtimeJoinResponse {
return EqualUnmodifiableListView(_participants);
}
/// Create a copy of ChatRealtimeJoinResponse
/// with the given fields replaced by the non-null parameter values.
@override @JsonKey(includeFromJson: false, includeToJson: false)
@ -1397,6 +1462,7 @@ String toString() {
return 'ChatRealtimeJoinResponse(provider: $provider, endpoint: $endpoint, token: $token, callId: $callId, roomName: $roomName, isAdmin: $isAdmin, participants: $participants)';
}
}
/// @nodoc
@ -1407,6 +1473,9 @@ $Res call({
String provider, String endpoint, String token, String callId, String roomName, bool isAdmin, List<CallParticipant> participants
});
}
/// @nodoc
class __$ChatRealtimeJoinResponseCopyWithImpl<$Res>
@ -1431,8 +1500,10 @@ as List<CallParticipant>,
));
}
}
/// @nodoc
mixin _$CallParticipant {
@ -1446,6 +1517,7 @@ $CallParticipantCopyWith<CallParticipant> get copyWith => _$CallParticipantCopyW
/// Serializes this CallParticipant to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is CallParticipant&&(identical(other.identity, identity) || other.identity == identity)&&(identical(other.name, name) || other.name == name)&&(identical(other.joinedAt, joinedAt) || other.joinedAt == joinedAt)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.profile, profile) || other.profile == profile));
@ -1460,6 +1532,7 @@ String toString() {
return 'CallParticipant(identity: $identity, name: $name, joinedAt: $joinedAt, accountId: $accountId, profile: $profile)';
}
}
/// @nodoc
@ -1470,6 +1543,7 @@ $Res call({
String identity, String name, DateTime joinedAt, String? accountId, SnChatMember? profile
});
$SnChatMemberCopyWith<$Res>? get profile;
}
@ -1508,6 +1582,7 @@ $SnChatMemberCopyWith<$Res>? get profile {
}
}
/// @nodoc
@JsonSerializable()
@ -1546,6 +1621,7 @@ String toString() {
return 'CallParticipant(identity: $identity, name: $name, joinedAt: $joinedAt, accountId: $accountId, profile: $profile)';
}
}
/// @nodoc
@ -1556,6 +1632,7 @@ $Res call({
String identity, String name, DateTime joinedAt, String? accountId, SnChatMember? profile
});
@override $SnChatMemberCopyWith<$Res>? get profile;
}
@ -1595,6 +1672,7 @@ $SnChatMemberCopyWith<$Res>? get profile {
}
}
/// @nodoc
mixin _$SnRealtimeCall {
@ -1608,6 +1686,7 @@ $SnRealtimeCallCopyWith<SnRealtimeCall> get copyWith => _$SnRealtimeCallCopyWith
/// Serializes this SnRealtimeCall to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnRealtimeCall&&(identical(other.id, id) || other.id == id)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)&&(identical(other.endedAt, endedAt) || other.endedAt == endedAt)&&(identical(other.senderId, senderId) || other.senderId == senderId)&&(identical(other.sender, sender) || other.sender == sender)&&(identical(other.roomId, roomId) || other.roomId == roomId)&&(identical(other.room, room) || other.room == room)&&const DeepCollectionEquality().equals(other.upstreamConfig, upstreamConfig)&&(identical(other.providerName, providerName) || other.providerName == providerName)&&(identical(other.sessionId, sessionId) || other.sessionId == sessionId));
@ -1622,6 +1701,7 @@ String toString() {
return 'SnRealtimeCall(id: $id, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, endedAt: $endedAt, senderId: $senderId, sender: $sender, roomId: $roomId, room: $room, upstreamConfig: $upstreamConfig, providerName: $providerName, sessionId: $sessionId)';
}
}
/// @nodoc
@ -1632,6 +1712,7 @@ $Res call({
String id, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, DateTime? endedAt, String senderId, SnChatMember sender, String roomId, SnChatRoom room, Map<String, dynamic> upstreamConfig, String? providerName, String? sessionId
});
$SnChatMemberCopyWith<$Res> get sender;$SnChatRoomCopyWith<$Res> get room;
}
@ -1683,6 +1764,7 @@ $SnChatRoomCopyWith<$Res> get room {
}
}
/// @nodoc
@JsonSerializable()
@ -1734,6 +1816,7 @@ String toString() {
return 'SnRealtimeCall(id: $id, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, endedAt: $endedAt, senderId: $senderId, sender: $sender, roomId: $roomId, room: $room, upstreamConfig: $upstreamConfig, providerName: $providerName, sessionId: $sessionId)';
}
}
/// @nodoc
@ -1744,6 +1827,7 @@ $Res call({
String id, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, DateTime? endedAt, String senderId, SnChatMember sender, String roomId, SnChatRoom room, Map<String, dynamic> upstreamConfig, String? providerName, String? sessionId
});
@override $SnChatMemberCopyWith<$Res> get sender;@override $SnChatRoomCopyWith<$Res> get room;
}

View File

@ -11,7 +11,8 @@ _SnChatRoom _$SnChatRoomFromJson(Map<String, dynamic> json) => _SnChatRoom(
name: json['name'] as String?,
description: json['description'] as String?,
type: (json['type'] as num).toInt(),
isPublic: json['is_public'] as bool,
isPublic: json['is_public'] as bool? ?? false,
isCommunity: json['is_community'] as bool? ?? false,
picture:
json['picture'] == null
? null
@ -44,6 +45,7 @@ Map<String, dynamic> _$SnChatRoomToJson(_SnChatRoom instance) =>
'description': instance.description,
'type': instance.type,
'is_public': instance.isPublic,
'is_community': instance.isCommunity,
'picture': instance.picture?.toJson(),
'background': instance.background?.toJson(),
'realm_id': instance.realmId,

View File

@ -26,6 +26,7 @@ $SnEmbedLinkCopyWith<SnEmbedLink> get copyWith => _$SnEmbedLinkCopyWithImpl<SnEm
/// Serializes this SnEmbedLink to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnEmbedLink&&(identical(other.type, type) || other.type == type)&&(identical(other.url, url) || other.url == url)&&(identical(other.title, title) || other.title == title)&&(identical(other.description, description) || other.description == description)&&(identical(other.imageUrl, imageUrl) || other.imageUrl == imageUrl)&&(identical(other.faviconUrl, faviconUrl) || other.faviconUrl == faviconUrl)&&(identical(other.siteName, siteName) || other.siteName == siteName)&&(identical(other.contentType, contentType) || other.contentType == contentType)&&(identical(other.author, author) || other.author == author)&&(identical(other.publishedDate, publishedDate) || other.publishedDate == publishedDate));
@ -40,6 +41,7 @@ String toString() {
return 'SnEmbedLink(type: $type, url: $url, title: $title, description: $description, imageUrl: $imageUrl, faviconUrl: $faviconUrl, siteName: $siteName, contentType: $contentType, author: $author, publishedDate: $publishedDate)';
}
}
/// @nodoc
@ -50,6 +52,9 @@ $Res call({
@JsonKey(name: 'Type') String type,@JsonKey(name: 'Url') String url,@JsonKey(name: 'Title') String title,@JsonKey(name: 'Description') String? description,@JsonKey(name: 'ImageUrl') String? imageUrl,@JsonKey(name: 'FaviconUrl') String faviconUrl,@JsonKey(name: 'SiteName') String siteName,@JsonKey(name: 'ContentType') String? contentType,@JsonKey(name: 'Author') String? author,@JsonKey(name: 'PublishedDate') DateTime? publishedDate
});
}
/// @nodoc
class _$SnEmbedLinkCopyWithImpl<$Res>
@ -79,6 +84,7 @@ as DateTime?,
}
/// @nodoc
@JsonSerializable()
@ -122,6 +128,7 @@ String toString() {
return 'SnEmbedLink(type: $type, url: $url, title: $title, description: $description, imageUrl: $imageUrl, faviconUrl: $faviconUrl, siteName: $siteName, contentType: $contentType, author: $author, publishedDate: $publishedDate)';
}
}
/// @nodoc
@ -132,6 +139,9 @@ $Res call({
@JsonKey(name: 'Type') String type,@JsonKey(name: 'Url') String url,@JsonKey(name: 'Title') String title,@JsonKey(name: 'Description') String? description,@JsonKey(name: 'ImageUrl') String? imageUrl,@JsonKey(name: 'FaviconUrl') String faviconUrl,@JsonKey(name: 'SiteName') String siteName,@JsonKey(name: 'ContentType') String? contentType,@JsonKey(name: 'Author') String? author,@JsonKey(name: 'PublishedDate') DateTime? publishedDate
});
}
/// @nodoc
class __$SnEmbedLinkCopyWithImpl<$Res>
@ -159,8 +169,10 @@ as DateTime?,
));
}
}
/// @nodoc
mixin _$SnScrappedLink {
@ -174,6 +186,7 @@ $SnScrappedLinkCopyWith<SnScrappedLink> get copyWith => _$SnScrappedLinkCopyWith
/// Serializes this SnScrappedLink to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnScrappedLink&&(identical(other.type, type) || other.type == type)&&(identical(other.url, url) || other.url == url)&&(identical(other.title, title) || other.title == title)&&(identical(other.description, description) || other.description == description)&&(identical(other.imageUrl, imageUrl) || other.imageUrl == imageUrl)&&(identical(other.faviconUrl, faviconUrl) || other.faviconUrl == faviconUrl)&&(identical(other.siteName, siteName) || other.siteName == siteName)&&(identical(other.contentType, contentType) || other.contentType == contentType)&&(identical(other.author, author) || other.author == author)&&(identical(other.publishedDate, publishedDate) || other.publishedDate == publishedDate));
@ -188,6 +201,7 @@ String toString() {
return 'SnScrappedLink(type: $type, url: $url, title: $title, description: $description, imageUrl: $imageUrl, faviconUrl: $faviconUrl, siteName: $siteName, contentType: $contentType, author: $author, publishedDate: $publishedDate)';
}
}
/// @nodoc
@ -198,6 +212,9 @@ $Res call({
String type, String url, String title, String? description, String? imageUrl, String faviconUrl, String siteName, String? contentType, String? author, DateTime? publishedDate
});
}
/// @nodoc
class _$SnScrappedLinkCopyWithImpl<$Res>
@ -227,6 +244,7 @@ as DateTime?,
}
/// @nodoc
@JsonSerializable()
@ -270,6 +288,7 @@ String toString() {
return 'SnScrappedLink(type: $type, url: $url, title: $title, description: $description, imageUrl: $imageUrl, faviconUrl: $faviconUrl, siteName: $siteName, contentType: $contentType, author: $author, publishedDate: $publishedDate)';
}
}
/// @nodoc
@ -280,6 +299,9 @@ $Res call({
String type, String url, String title, String? description, String? imageUrl, String faviconUrl, String siteName, String? contentType, String? author, DateTime? publishedDate
});
}
/// @nodoc
class __$SnScrappedLinkCopyWithImpl<$Res>
@ -307,6 +329,7 @@ as DateTime?,
));
}
}
// dart format on

View File

@ -26,6 +26,7 @@ $UniversalFileCopyWith<UniversalFile> get copyWith => _$UniversalFileCopyWithImp
/// Serializes this UniversalFile to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is UniversalFile&&const DeepCollectionEquality().equals(other.data, data)&&(identical(other.type, type) || other.type == type));
@ -40,6 +41,7 @@ String toString() {
return 'UniversalFile(data: $data, type: $type)';
}
}
/// @nodoc
@ -50,6 +52,9 @@ $Res call({
dynamic data, UniversalFileType type
});
}
/// @nodoc
class _$UniversalFileCopyWithImpl<$Res>
@ -71,6 +76,7 @@ as UniversalFileType,
}
/// @nodoc
@JsonSerializable()
@ -106,6 +112,7 @@ String toString() {
return 'UniversalFile(data: $data, type: $type)';
}
}
/// @nodoc
@ -116,6 +123,9 @@ $Res call({
dynamic data, UniversalFileType type
});
}
/// @nodoc
class __$UniversalFileCopyWithImpl<$Res>
@ -135,8 +145,10 @@ as UniversalFileType,
));
}
}
/// @nodoc
mixin _$SnCloudFile {
@ -150,6 +162,7 @@ $SnCloudFileCopyWith<SnCloudFile> get copyWith => _$SnCloudFileCopyWithImpl<SnCl
/// Serializes this SnCloudFile to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnCloudFile&&(identical(other.id, id) || other.id == id)&&(identical(other.name, name) || other.name == name)&&(identical(other.description, description) || other.description == description)&&const DeepCollectionEquality().equals(other.fileMeta, fileMeta)&&const DeepCollectionEquality().equals(other.userMeta, userMeta)&&(identical(other.mimeType, mimeType) || other.mimeType == mimeType)&&(identical(other.hash, hash) || other.hash == hash)&&(identical(other.size, size) || other.size == size)&&(identical(other.uploadedAt, uploadedAt) || other.uploadedAt == uploadedAt)&&(identical(other.uploadedTo, uploadedTo) || other.uploadedTo == uploadedTo)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt));
@ -164,6 +177,7 @@ String toString() {
return 'SnCloudFile(id: $id, name: $name, description: $description, fileMeta: $fileMeta, userMeta: $userMeta, mimeType: $mimeType, hash: $hash, size: $size, uploadedAt: $uploadedAt, uploadedTo: $uploadedTo, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
}
}
/// @nodoc
@ -174,6 +188,9 @@ $Res call({
String id, String name, String? description, Map<String, dynamic>? fileMeta, Map<String, dynamic>? userMeta, String? mimeType, String? hash, int size, DateTime? uploadedAt, String? uploadedTo, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
});
}
/// @nodoc
class _$SnCloudFileCopyWithImpl<$Res>
@ -206,6 +223,7 @@ as DateTime?,
}
/// @nodoc
@JsonSerializable()
@ -268,6 +286,7 @@ String toString() {
return 'SnCloudFile(id: $id, name: $name, description: $description, fileMeta: $fileMeta, userMeta: $userMeta, mimeType: $mimeType, hash: $hash, size: $size, uploadedAt: $uploadedAt, uploadedTo: $uploadedTo, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
}
}
/// @nodoc
@ -278,6 +297,9 @@ $Res call({
String id, String name, String? description, Map<String, dynamic>? fileMeta, Map<String, dynamic>? userMeta, String? mimeType, String? hash, int size, DateTime? uploadedAt, String? uploadedTo, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
});
}
/// @nodoc
class __$SnCloudFileCopyWithImpl<$Res>
@ -308,6 +330,7 @@ as DateTime?,
));
}
}
// dart format on

View File

@ -1,5 +1,7 @@
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:island/models/file.dart';
import 'package:island/models/post_category.dart';
import 'package:island/models/post_tag.dart';
import 'package:island/models/user.dart';
part 'post.freezed.dart';
@ -33,8 +35,8 @@ sealed class SnPost with _$SnPost {
@Default(SnPublisher()) SnPublisher publisher,
@Default({}) Map<String, int> reactionsCount,
@Default([]) List<dynamic> reactions,
@Default([]) List<dynamic> tags,
@Default([]) List<dynamic> categories,
@Default([]) List<PostTag> tags,
@Default([]) List<PostCategory> categories,
@Default([]) List<dynamic> collections,
@Default(null) DateTime? createdAt,
@Default(null) DateTime? updatedAt,

View File

@ -16,7 +16,7 @@ T _$identity<T>(T value) => value;
/// @nodoc
mixin _$SnPost {
String get id; String? get title; String? get description; String? get language; DateTime? get editedAt; DateTime? get publishedAt; int get visibility; String? get content; 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; List<dynamic> get reactions; List<dynamic> get tags; List<dynamic> 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; 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; List<dynamic> get reactions; List<PostTag> get tags; List<PostCategory> get categories; List<dynamic> get collections; DateTime? get createdAt; DateTime? get updatedAt; DateTime? get deletedAt; bool get isTruncated;
/// Create a copy of SnPost
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@ -26,6 +26,7 @@ $SnPostCopyWith<SnPost> get copyWith => _$SnPostCopyWithImpl<SnPost>(this as SnP
/// Serializes this SnPost to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnPost&&(identical(other.id, id) || other.id == id)&&(identical(other.title, title) || other.title == title)&&(identical(other.description, description) || other.description == description)&&(identical(other.language, language) || other.language == language)&&(identical(other.editedAt, editedAt) || other.editedAt == editedAt)&&(identical(other.publishedAt, publishedAt) || other.publishedAt == publishedAt)&&(identical(other.visibility, visibility) || other.visibility == visibility)&&(identical(other.content, content) || other.content == content)&&(identical(other.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.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));
@ -40,6 +41,7 @@ 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, reactions: $reactions, tags: $tags, categories: $categories, collections: $collections, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, isTruncated: $isTruncated)';
}
}
/// @nodoc
@ -47,9 +49,10 @@ abstract mixin class $SnPostCopyWith<$Res> {
factory $SnPostCopyWith(SnPost value, $Res Function(SnPost) _then) = _$SnPostCopyWithImpl;
@useResult
$Res call({
String id, String? title, String? description, String? language, DateTime? editedAt, DateTime? publishedAt, int visibility, String? content, 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, List<dynamic> reactions, List<dynamic> tags, List<dynamic> 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, 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, List<dynamic> reactions, List<PostTag> tags, List<PostCategory> 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;
}
@ -91,8 +94,8 @@ as List<SnCloudFile>,publisher: null == publisher ? _self.publisher : publisher
as SnPublisher,reactionsCount: null == reactionsCount ? _self.reactionsCount : reactionsCount // ignore: cast_nullable_to_non_nullable
as Map<String, int>,reactions: null == reactions ? _self.reactions : reactions // ignore: cast_nullable_to_non_nullable
as List<dynamic>,tags: null == tags ? _self.tags : tags // ignore: cast_nullable_to_non_nullable
as List<dynamic>,categories: null == categories ? _self.categories : categories // ignore: cast_nullable_to_non_nullable
as List<dynamic>,collections: null == collections ? _self.collections : collections // ignore: cast_nullable_to_non_nullable
as List<PostTag>,categories: null == categories ? _self.categories : categories // ignore: cast_nullable_to_non_nullable
as List<PostCategory>,collections: null == collections ? _self.collections : collections // ignore: cast_nullable_to_non_nullable
as List<dynamic>,createdAt: freezed == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
as DateTime?,updatedAt: freezed == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
as DateTime?,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
@ -148,11 +151,12 @@ $SnPublisherCopyWith<$Res> get publisher {
}
}
/// @nodoc
@JsonSerializable()
class _SnPost implements SnPost {
const _SnPost({required this.id, this.title, this.description, this.language, this.editedAt, this.publishedAt = null, this.visibility = 0, this.content, this.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 [], this.publisher = const SnPublisher(), final Map<String, int> reactionsCount = const {}, final List<dynamic> reactions = const [], final List<dynamic> tags = const [], final List<dynamic> categories = const [], final List<dynamic> collections = const [], this.createdAt = null, this.updatedAt = null, this.deletedAt, this.isTruncated = false}): _meta = meta,_attachments = attachments,_reactionsCount = reactionsCount,_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.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 [], this.publisher = const SnPublisher(), final Map<String, int> reactionsCount = const {}, final List<dynamic> reactions = const [], final List<PostTag> tags = const [], final List<PostCategory> categories = const [], final List<dynamic> collections = const [], this.createdAt = null, this.updatedAt = null, this.deletedAt, this.isTruncated = false}): _meta = meta,_attachments = attachments,_reactionsCount = reactionsCount,_reactions = reactions,_tags = tags,_categories = categories,_collections = collections;
factory _SnPost.fromJson(Map<String, dynamic> json) => _$SnPostFromJson(json);
@override final String id;
@ -206,15 +210,15 @@ class _SnPost implements SnPost {
return EqualUnmodifiableListView(_reactions);
}
final List<dynamic> _tags;
@override@JsonKey() List<dynamic> get tags {
final List<PostTag> _tags;
@override@JsonKey() List<PostTag> get tags {
if (_tags is EqualUnmodifiableListView) return _tags;
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(_tags);
}
final List<dynamic> _categories;
@override@JsonKey() List<dynamic> get categories {
final List<PostCategory> _categories;
@override@JsonKey() List<PostCategory> get categories {
if (_categories is EqualUnmodifiableListView) return _categories;
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(_categories);
@ -257,6 +261,7 @@ 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, reactions: $reactions, tags: $tags, categories: $categories, collections: $collections, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, isTruncated: $isTruncated)';
}
}
/// @nodoc
@ -264,9 +269,10 @@ abstract mixin class _$SnPostCopyWith<$Res> implements $SnPostCopyWith<$Res> {
factory _$SnPostCopyWith(_SnPost value, $Res Function(_SnPost) _then) = __$SnPostCopyWithImpl;
@override @useResult
$Res call({
String id, String? title, String? description, String? language, DateTime? editedAt, DateTime? publishedAt, int visibility, String? content, 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, List<dynamic> reactions, List<dynamic> tags, List<dynamic> 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, 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, List<dynamic> reactions, List<PostTag> tags, List<PostCategory> 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;
}
@ -308,8 +314,8 @@ as List<SnCloudFile>,publisher: null == publisher ? _self.publisher : publisher
as SnPublisher,reactionsCount: null == reactionsCount ? _self._reactionsCount : reactionsCount // ignore: cast_nullable_to_non_nullable
as Map<String, int>,reactions: null == reactions ? _self._reactions : reactions // ignore: cast_nullable_to_non_nullable
as List<dynamic>,tags: null == tags ? _self._tags : tags // ignore: cast_nullable_to_non_nullable
as List<dynamic>,categories: null == categories ? _self._categories : categories // ignore: cast_nullable_to_non_nullable
as List<dynamic>,collections: null == collections ? _self._collections : collections // ignore: cast_nullable_to_non_nullable
as List<PostTag>,categories: null == categories ? _self._categories : categories // ignore: cast_nullable_to_non_nullable
as List<PostCategory>,collections: null == collections ? _self._collections : collections // ignore: cast_nullable_to_non_nullable
as List<dynamic>,createdAt: freezed == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
as DateTime?,updatedAt: freezed == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
as DateTime?,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
@ -366,6 +372,7 @@ $SnPublisherCopyWith<$Res> get publisher {
}
}
/// @nodoc
mixin _$SnPublisher {
@ -379,6 +386,7 @@ $SnPublisherCopyWith<SnPublisher> get copyWith => _$SnPublisherCopyWithImpl<SnPu
/// Serializes this SnPublisher to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnPublisher&&(identical(other.id, id) || other.id == id)&&(identical(other.type, type) || other.type == type)&&(identical(other.name, name) || other.name == name)&&(identical(other.nick, nick) || other.nick == nick)&&(identical(other.bio, bio) || other.bio == bio)&&(identical(other.picture, picture) || other.picture == picture)&&(identical(other.background, background) || other.background == background)&&(identical(other.account, account) || other.account == account)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)&&(identical(other.realmId, realmId) || other.realmId == realmId)&&(identical(other.verification, verification) || other.verification == verification));
@ -393,6 +401,7 @@ String toString() {
return 'SnPublisher(id: $id, type: $type, name: $name, nick: $nick, bio: $bio, picture: $picture, background: $background, account: $account, accountId: $accountId, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, realmId: $realmId, verification: $verification)';
}
}
/// @nodoc
@ -403,6 +412,7 @@ $Res call({
String id, int type, String name, String nick, String bio, SnCloudFile? picture, SnCloudFile? background, SnAccount? account, String? accountId, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, String? realmId, SnVerificationMark? verification
});
$SnCloudFileCopyWith<$Res>? get picture;$SnCloudFileCopyWith<$Res>? get background;$SnAccountCopyWith<$Res>? get account;$SnVerificationMarkCopyWith<$Res>? get verification;
}
@ -486,6 +496,7 @@ $SnVerificationMarkCopyWith<$Res>? get verification {
}
}
/// @nodoc
@JsonSerializable()
@ -533,6 +544,7 @@ String toString() {
return 'SnPublisher(id: $id, type: $type, name: $name, nick: $nick, bio: $bio, picture: $picture, background: $background, account: $account, accountId: $accountId, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, realmId: $realmId, verification: $verification)';
}
}
/// @nodoc
@ -543,6 +555,7 @@ $Res call({
String id, int type, String name, String nick, String bio, SnCloudFile? picture, SnCloudFile? background, SnAccount? account, String? accountId, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, String? realmId, SnVerificationMark? verification
});
@override $SnCloudFileCopyWith<$Res>? get picture;@override $SnCloudFileCopyWith<$Res>? get background;@override $SnAccountCopyWith<$Res>? get account;@override $SnVerificationMarkCopyWith<$Res>? get verification;
}
@ -627,6 +640,7 @@ $SnVerificationMarkCopyWith<$Res>? get verification {
}
}
/// @nodoc
mixin _$SnPublisherStats {
@ -640,6 +654,7 @@ $SnPublisherStatsCopyWith<SnPublisherStats> get copyWith => _$SnPublisherStatsCo
/// Serializes this SnPublisherStats to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnPublisherStats&&(identical(other.postsCreated, postsCreated) || other.postsCreated == postsCreated)&&(identical(other.stickerPacksCreated, stickerPacksCreated) || other.stickerPacksCreated == stickerPacksCreated)&&(identical(other.stickersCreated, stickersCreated) || other.stickersCreated == stickersCreated)&&(identical(other.upvoteReceived, upvoteReceived) || other.upvoteReceived == upvoteReceived)&&(identical(other.downvoteReceived, downvoteReceived) || other.downvoteReceived == downvoteReceived));
@ -654,6 +669,7 @@ String toString() {
return 'SnPublisherStats(postsCreated: $postsCreated, stickerPacksCreated: $stickerPacksCreated, stickersCreated: $stickersCreated, upvoteReceived: $upvoteReceived, downvoteReceived: $downvoteReceived)';
}
}
/// @nodoc
@ -664,6 +680,9 @@ $Res call({
int postsCreated, int stickerPacksCreated, int stickersCreated, int upvoteReceived, int downvoteReceived
});
}
/// @nodoc
class _$SnPublisherStatsCopyWithImpl<$Res>
@ -688,6 +707,7 @@ as int,
}
/// @nodoc
@JsonSerializable()
@ -726,6 +746,7 @@ String toString() {
return 'SnPublisherStats(postsCreated: $postsCreated, stickerPacksCreated: $stickerPacksCreated, stickersCreated: $stickersCreated, upvoteReceived: $upvoteReceived, downvoteReceived: $downvoteReceived)';
}
}
/// @nodoc
@ -736,6 +757,9 @@ $Res call({
int postsCreated, int stickerPacksCreated, int stickersCreated, int upvoteReceived, int downvoteReceived
});
}
/// @nodoc
class __$SnPublisherStatsCopyWithImpl<$Res>
@ -758,8 +782,10 @@ as int,
));
}
}
/// @nodoc
mixin _$SnSubscriptionStatus {
@ -773,6 +799,7 @@ $SnSubscriptionStatusCopyWith<SnSubscriptionStatus> get copyWith => _$SnSubscrip
/// Serializes this SnSubscriptionStatus to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnSubscriptionStatus&&(identical(other.isSubscribed, isSubscribed) || other.isSubscribed == isSubscribed)&&(identical(other.publisherId, publisherId) || other.publisherId == publisherId)&&(identical(other.publisherName, publisherName) || other.publisherName == publisherName));
@ -787,6 +814,7 @@ String toString() {
return 'SnSubscriptionStatus(isSubscribed: $isSubscribed, publisherId: $publisherId, publisherName: $publisherName)';
}
}
/// @nodoc
@ -797,6 +825,9 @@ $Res call({
bool isSubscribed, String publisherId, String publisherName
});
}
/// @nodoc
class _$SnSubscriptionStatusCopyWithImpl<$Res>
@ -819,6 +850,7 @@ as String,
}
/// @nodoc
@JsonSerializable()
@ -855,6 +887,7 @@ String toString() {
return 'SnSubscriptionStatus(isSubscribed: $isSubscribed, publisherId: $publisherId, publisherName: $publisherName)';
}
}
/// @nodoc
@ -865,6 +898,9 @@ $Res call({
bool isSubscribed, String publisherId, String publisherName
});
}
/// @nodoc
class __$SnSubscriptionStatusCopyWithImpl<$Res>
@ -885,6 +921,7 @@ as String,
));
}
}
/// @nodoc
@ -897,11 +934,14 @@ mixin _$ReactInfo {
@pragma('vm:prefer-inline')
$ReactInfoCopyWith<ReactInfo> get copyWith => _$ReactInfoCopyWithImpl<ReactInfo>(this as ReactInfo, _$identity);
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is ReactInfo&&(identical(other.icon, icon) || other.icon == icon)&&(identical(other.attitude, attitude) || other.attitude == attitude));
}
@override
int get hashCode => Object.hash(runtimeType,icon,attitude);
@ -910,6 +950,7 @@ String toString() {
return 'ReactInfo(icon: $icon, attitude: $attitude)';
}
}
/// @nodoc
@ -920,6 +961,9 @@ $Res call({
String icon, int attitude
});
}
/// @nodoc
class _$ReactInfoCopyWithImpl<$Res>
@ -941,8 +985,10 @@ as int,
}
/// @nodoc
class _ReactInfo implements ReactInfo {
const _ReactInfo({required this.icon, required this.attitude});
@ -956,11 +1002,14 @@ class _ReactInfo implements ReactInfo {
@pragma('vm:prefer-inline')
_$ReactInfoCopyWith<_ReactInfo> get copyWith => __$ReactInfoCopyWithImpl<_ReactInfo>(this, _$identity);
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _ReactInfo&&(identical(other.icon, icon) || other.icon == icon)&&(identical(other.attitude, attitude) || other.attitude == attitude));
}
@override
int get hashCode => Object.hash(runtimeType,icon,attitude);
@ -969,6 +1018,7 @@ String toString() {
return 'ReactInfo(icon: $icon, attitude: $attitude)';
}
}
/// @nodoc
@ -979,6 +1029,9 @@ $Res call({
String icon, int attitude
});
}
/// @nodoc
class __$ReactInfoCopyWithImpl<$Res>
@ -998,6 +1051,7 @@ as int,
));
}
}
// dart format on

View File

@ -58,8 +58,16 @@ _SnPost _$SnPostFromJson(Map<String, dynamic> json) => _SnPost(
) ??
const {},
reactions: json['reactions'] as List<dynamic>? ?? const [],
tags: json['tags'] as List<dynamic>? ?? const [],
categories: json['categories'] as List<dynamic>? ?? const [],
tags:
(json['tags'] as List<dynamic>?)
?.map((e) => PostTag.fromJson(e as Map<String, dynamic>))
.toList() ??
const [],
categories:
(json['categories'] as List<dynamic>?)
?.map((e) => PostCategory.fromJson(e as Map<String, dynamic>))
.toList() ??
const [],
collections: json['collections'] as List<dynamic>? ?? const [],
createdAt:
json['created_at'] == null
@ -102,8 +110,8 @@ Map<String, dynamic> _$SnPostToJson(_SnPost instance) => <String, dynamic>{
'publisher': instance.publisher.toJson(),
'reactions_count': instance.reactionsCount,
'reactions': instance.reactions,
'tags': instance.tags,
'categories': instance.categories,
'tags': instance.tags.map((e) => e.toJson()).toList(),
'categories': instance.categories.map((e) => e.toJson()).toList(),
'collections': instance.collections,
'created_at': instance.createdAt?.toIso8601String(),
'updated_at': instance.updatedAt?.toIso8601String(),

View File

@ -0,0 +1,19 @@
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:island/models/post.dart';
part 'post_category.freezed.dart';
part 'post_category.g.dart';
@freezed
sealed class PostCategory with _$PostCategory {
const factory PostCategory({
required String id,
required String slug,
String? name,
@Default([]) List<SnPost> posts,
}) = _PostCategory;
factory PostCategory.fromJson(Map<String, dynamic> json) =>
_$PostCategoryFromJson(json);
}

View File

@ -0,0 +1,163 @@
// dart format width=80
// coverage:ignore-file
// GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: type=lint
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
part of 'post_category.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
// dart format off
T _$identity<T>(T value) => value;
/// @nodoc
mixin _$PostCategory {
String get id; String get slug; String? get name; List<SnPost> get posts;
/// Create a copy of PostCategory
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
$PostCategoryCopyWith<PostCategory> get copyWith => _$PostCategoryCopyWithImpl<PostCategory>(this as PostCategory, _$identity);
/// Serializes this PostCategory to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is PostCategory&&(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));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType,id,slug,name,const DeepCollectionEquality().hash(posts));
@override
String toString() {
return 'PostCategory(id: $id, slug: $slug, name: $name, posts: $posts)';
}
}
/// @nodoc
abstract mixin class $PostCategoryCopyWith<$Res> {
factory $PostCategoryCopyWith(PostCategory value, $Res Function(PostCategory) _then) = _$PostCategoryCopyWithImpl;
@useResult
$Res call({
String id, String slug, String? name, List<SnPost> posts
});
}
/// @nodoc
class _$PostCategoryCopyWithImpl<$Res>
implements $PostCategoryCopyWith<$Res> {
_$PostCategoryCopyWithImpl(this._self, this._then);
final PostCategory _self;
final $Res Function(PostCategory) _then;
/// Create a copy of PostCategory
/// 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,}) {
return _then(_self.copyWith(
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,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 List<SnPost>,
));
}
}
/// @nodoc
@JsonSerializable()
class _PostCategory implements PostCategory {
const _PostCategory({required this.id, required this.slug, this.name, final List<SnPost> posts = const []}): _posts = posts;
factory _PostCategory.fromJson(Map<String, dynamic> json) => _$PostCategoryFromJson(json);
@override final String id;
@override final String slug;
@override final String? name;
final List<SnPost> _posts;
@override@JsonKey() List<SnPost> get posts {
if (_posts is EqualUnmodifiableListView) return _posts;
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(_posts);
}
/// Create a copy of PostCategory
/// with the given fields replaced by the non-null parameter values.
@override @JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
_$PostCategoryCopyWith<_PostCategory> get copyWith => __$PostCategoryCopyWithImpl<_PostCategory>(this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$PostCategoryToJson(this, );
}
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _PostCategory&&(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));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType,id,slug,name,const DeepCollectionEquality().hash(_posts));
@override
String toString() {
return 'PostCategory(id: $id, slug: $slug, name: $name, posts: $posts)';
}
}
/// @nodoc
abstract mixin class _$PostCategoryCopyWith<$Res> implements $PostCategoryCopyWith<$Res> {
factory _$PostCategoryCopyWith(_PostCategory value, $Res Function(_PostCategory) _then) = __$PostCategoryCopyWithImpl;
@override @useResult
$Res call({
String id, String slug, String? name, List<SnPost> posts
});
}
/// @nodoc
class __$PostCategoryCopyWithImpl<$Res>
implements _$PostCategoryCopyWith<$Res> {
__$PostCategoryCopyWithImpl(this._self, this._then);
final _PostCategory _self;
final $Res Function(_PostCategory) _then;
/// Create a copy of PostCategory
/// 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,}) {
return _then(_PostCategory(
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,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 List<SnPost>,
));
}
}
// dart format on

View File

@ -0,0 +1,27 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'post_category.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
_PostCategory _$PostCategoryFromJson(Map<String, dynamic> json) =>
_PostCategory(
id: json['id'] as String,
slug: json['slug'] as String,
name: json['name'] as String?,
posts:
(json['posts'] as List<dynamic>?)
?.map((e) => SnPost.fromJson(e as Map<String, dynamic>))
.toList() ??
const [],
);
Map<String, dynamic> _$PostCategoryToJson(_PostCategory instance) =>
<String, dynamic>{
'id': instance.id,
'slug': instance.slug,
'name': instance.name,
'posts': instance.posts.map((e) => e.toJson()).toList(),
};

19
lib/models/post_tag.dart Normal file
View File

@ -0,0 +1,19 @@
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:island/models/post.dart';
part 'post_tag.freezed.dart';
part 'post_tag.g.dart';
@freezed
sealed class PostTag with _$PostTag {
const factory PostTag({
required String id,
required String slug,
String? name,
@Default([]) List<SnPost> posts,
}) = _PostTag;
factory PostTag.fromJson(Map<String, dynamic> json) =>
_$PostTagFromJson(json);
}

View File

@ -0,0 +1,163 @@
// dart format width=80
// coverage:ignore-file
// GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: type=lint
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
part of 'post_tag.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
// dart format off
T _$identity<T>(T value) => value;
/// @nodoc
mixin _$PostTag {
String get id; String get slug; String? get name; List<SnPost> get posts;
/// Create a copy of PostTag
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
$PostTagCopyWith<PostTag> get copyWith => _$PostTagCopyWithImpl<PostTag>(this as PostTag, _$identity);
/// Serializes this PostTag to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is PostTag&&(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));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType,id,slug,name,const DeepCollectionEquality().hash(posts));
@override
String toString() {
return 'PostTag(id: $id, slug: $slug, name: $name, posts: $posts)';
}
}
/// @nodoc
abstract mixin class $PostTagCopyWith<$Res> {
factory $PostTagCopyWith(PostTag value, $Res Function(PostTag) _then) = _$PostTagCopyWithImpl;
@useResult
$Res call({
String id, String slug, String? name, List<SnPost> posts
});
}
/// @nodoc
class _$PostTagCopyWithImpl<$Res>
implements $PostTagCopyWith<$Res> {
_$PostTagCopyWithImpl(this._self, this._then);
final PostTag _self;
final $Res Function(PostTag) _then;
/// Create a copy of PostTag
/// 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,}) {
return _then(_self.copyWith(
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,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 List<SnPost>,
));
}
}
/// @nodoc
@JsonSerializable()
class _PostTag implements PostTag {
const _PostTag({required this.id, required this.slug, this.name, final List<SnPost> posts = const []}): _posts = posts;
factory _PostTag.fromJson(Map<String, dynamic> json) => _$PostTagFromJson(json);
@override final String id;
@override final String slug;
@override final String? name;
final List<SnPost> _posts;
@override@JsonKey() List<SnPost> get posts {
if (_posts is EqualUnmodifiableListView) return _posts;
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(_posts);
}
/// Create a copy of PostTag
/// with the given fields replaced by the non-null parameter values.
@override @JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
_$PostTagCopyWith<_PostTag> get copyWith => __$PostTagCopyWithImpl<_PostTag>(this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$PostTagToJson(this, );
}
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _PostTag&&(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));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType,id,slug,name,const DeepCollectionEquality().hash(_posts));
@override
String toString() {
return 'PostTag(id: $id, slug: $slug, name: $name, posts: $posts)';
}
}
/// @nodoc
abstract mixin class _$PostTagCopyWith<$Res> implements $PostTagCopyWith<$Res> {
factory _$PostTagCopyWith(_PostTag value, $Res Function(_PostTag) _then) = __$PostTagCopyWithImpl;
@override @useResult
$Res call({
String id, String slug, String? name, List<SnPost> posts
});
}
/// @nodoc
class __$PostTagCopyWithImpl<$Res>
implements _$PostTagCopyWith<$Res> {
__$PostTagCopyWithImpl(this._self, this._then);
final _PostTag _self;
final $Res Function(_PostTag) _then;
/// Create a copy of PostTag
/// 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,}) {
return _then(_PostTag(
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,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 List<SnPost>,
));
}
}
// dart format on

View File

@ -0,0 +1,25 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'post_tag.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
_PostTag _$PostTagFromJson(Map<String, dynamic> json) => _PostTag(
id: json['id'] as String,
slug: json['slug'] as String,
name: json['name'] as String?,
posts:
(json['posts'] as List<dynamic>?)
?.map((e) => SnPost.fromJson(e as Map<String, dynamic>))
.toList() ??
const [],
);
Map<String, dynamic> _$PostTagToJson(_PostTag instance) => <String, dynamic>{
'id': instance.id,
'slug': instance.slug,
'name': instance.name,
'posts': instance.posts.map((e) => e.toJson()).toList(),
};

View File

@ -10,8 +10,8 @@ sealed class SnRealm with _$SnRealm {
const factory SnRealm({
required String id,
required String slug,
required String name,
required String description,
@Default('') String name,
@Default('') String description,
required String? verifiedAs,
required DateTime? verifiedAt,
required bool isCommunity,

View File

@ -26,6 +26,7 @@ $SnRealmCopyWith<SnRealm> get copyWith => _$SnRealmCopyWithImpl<SnRealm>(this as
/// Serializes this SnRealm to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnRealm&&(identical(other.id, id) || other.id == id)&&(identical(other.slug, slug) || other.slug == slug)&&(identical(other.name, name) || other.name == name)&&(identical(other.description, description) || other.description == description)&&(identical(other.verifiedAs, verifiedAs) || other.verifiedAs == verifiedAs)&&(identical(other.verifiedAt, verifiedAt) || other.verifiedAt == verifiedAt)&&(identical(other.isCommunity, isCommunity) || other.isCommunity == isCommunity)&&(identical(other.isPublic, isPublic) || other.isPublic == isPublic)&&(identical(other.picture, picture) || other.picture == picture)&&(identical(other.background, background) || other.background == background)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt));
@ -40,6 +41,7 @@ String toString() {
return 'SnRealm(id: $id, slug: $slug, name: $name, description: $description, verifiedAs: $verifiedAs, verifiedAt: $verifiedAt, isCommunity: $isCommunity, isPublic: $isPublic, picture: $picture, background: $background, accountId: $accountId, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
}
}
/// @nodoc
@ -50,6 +52,7 @@ $Res call({
String id, String slug, String name, String description, String? verifiedAs, DateTime? verifiedAt, bool isCommunity, bool isPublic, SnCloudFile? picture, SnCloudFile? background, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
});
$SnCloudFileCopyWith<$Res>? get picture;$SnCloudFileCopyWith<$Res>? get background;
}
@ -109,17 +112,18 @@ $SnCloudFileCopyWith<$Res>? get background {
}
}
/// @nodoc
@JsonSerializable()
class _SnRealm implements SnRealm {
const _SnRealm({required this.id, required this.slug, required this.name, required this.description, required this.verifiedAs, required this.verifiedAt, required this.isCommunity, required this.isPublic, required this.picture, required this.background, required this.accountId, required this.createdAt, required this.updatedAt, required this.deletedAt});
const _SnRealm({required this.id, required this.slug, this.name = '', this.description = '', required this.verifiedAs, required this.verifiedAt, required this.isCommunity, required this.isPublic, required this.picture, required this.background, required this.accountId, required this.createdAt, required this.updatedAt, required this.deletedAt});
factory _SnRealm.fromJson(Map<String, dynamic> json) => _$SnRealmFromJson(json);
@override final String id;
@override final String slug;
@override final String name;
@override final String description;
@override@JsonKey() final String name;
@override@JsonKey() final String description;
@override final String? verifiedAs;
@override final DateTime? verifiedAt;
@override final bool isCommunity;
@ -156,6 +160,7 @@ String toString() {
return 'SnRealm(id: $id, slug: $slug, name: $name, description: $description, verifiedAs: $verifiedAs, verifiedAt: $verifiedAt, isCommunity: $isCommunity, isPublic: $isPublic, picture: $picture, background: $background, accountId: $accountId, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
}
}
/// @nodoc
@ -166,6 +171,7 @@ $Res call({
String id, String slug, String name, String description, String? verifiedAs, DateTime? verifiedAt, bool isCommunity, bool isPublic, SnCloudFile? picture, SnCloudFile? background, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
});
@override $SnCloudFileCopyWith<$Res>? get picture;@override $SnCloudFileCopyWith<$Res>? get background;
}
@ -226,6 +232,7 @@ $SnCloudFileCopyWith<$Res>? get background {
}
}
/// @nodoc
mixin _$SnRealmMember {
@ -239,6 +246,7 @@ $SnRealmMemberCopyWith<SnRealmMember> get copyWith => _$SnRealmMemberCopyWithImp
/// Serializes this SnRealmMember to a JSON map.
Map<String, dynamic> toJson();
@override
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));
@ -253,6 +261,7 @@ String toString() {
return 'SnRealmMember(realmId: $realmId, realm: $realm, accountId: $accountId, account: $account, role: $role, joinedAt: $joinedAt, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
}
}
/// @nodoc
@ -263,6 +272,7 @@ $Res call({
String realmId, SnRealm? realm, String accountId, SnAccount? account, int role, DateTime? joinedAt, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
});
$SnRealmCopyWith<$Res>? get realm;$SnAccountCopyWith<$Res>? get account;
}
@ -317,6 +327,7 @@ $SnAccountCopyWith<$Res>? get account {
}
}
/// @nodoc
@JsonSerializable()
@ -359,6 +370,7 @@ String toString() {
return 'SnRealmMember(realmId: $realmId, realm: $realm, accountId: $accountId, account: $account, role: $role, joinedAt: $joinedAt, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
}
}
/// @nodoc
@ -369,6 +381,7 @@ $Res call({
String realmId, SnRealm? realm, String accountId, SnAccount? account, int role, DateTime? joinedAt, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
});
@override $SnRealmCopyWith<$Res>? get realm;@override $SnAccountCopyWith<$Res>? get account;
}

View File

@ -9,8 +9,8 @@ part of 'realm.dart';
_SnRealm _$SnRealmFromJson(Map<String, dynamic> json) => _SnRealm(
id: json['id'] as String,
slug: json['slug'] as String,
name: json['name'] as String,
description: json['description'] as String,
name: json['name'] as String? ?? '',
description: json['description'] as String? ?? '',
verifiedAs: json['verified_as'] as String?,
verifiedAt:
json['verified_at'] == null

View File

@ -26,6 +26,7 @@ $SnRelationshipCopyWith<SnRelationship> get copyWith => _$SnRelationshipCopyWith
/// Serializes this SnRelationship to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnRelationship&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.account, account) || other.account == account)&&(identical(other.relatedId, relatedId) || other.relatedId == relatedId)&&(identical(other.related, related) || other.related == related)&&(identical(other.expiredAt, expiredAt) || other.expiredAt == expiredAt)&&(identical(other.status, status) || other.status == status));
@ -40,6 +41,7 @@ String toString() {
return 'SnRelationship(createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, accountId: $accountId, account: $account, relatedId: $relatedId, related: $related, expiredAt: $expiredAt, status: $status)';
}
}
/// @nodoc
@ -50,6 +52,7 @@ $Res call({
DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, String accountId, SnAccount account, String relatedId, SnAccount related, DateTime? expiredAt, int status
});
$SnAccountCopyWith<$Res> get account;$SnAccountCopyWith<$Res> get related;
}
@ -98,6 +101,7 @@ $SnAccountCopyWith<$Res> get related {
}
}
/// @nodoc
@JsonSerializable()
@ -140,6 +144,7 @@ String toString() {
return 'SnRelationship(createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, accountId: $accountId, account: $account, relatedId: $relatedId, related: $related, expiredAt: $expiredAt, status: $status)';
}
}
/// @nodoc
@ -150,6 +155,7 @@ $Res call({
DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, String accountId, SnAccount account, String relatedId, SnAccount related, DateTime? expiredAt, int status
});
@override $SnAccountCopyWith<$Res> get account;@override $SnAccountCopyWith<$Res> get related;
}

View File

@ -26,6 +26,7 @@ $SnStickerCopyWith<SnSticker> get copyWith => _$SnStickerCopyWithImpl<SnSticker>
/// Serializes this SnSticker to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnSticker&&(identical(other.id, id) || other.id == id)&&(identical(other.slug, slug) || other.slug == slug)&&(identical(other.imageId, imageId) || other.imageId == imageId)&&(identical(other.image, image) || other.image == image)&&(identical(other.packId, packId) || other.packId == packId)&&(identical(other.pack, pack) || other.pack == pack)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt));
@ -40,6 +41,7 @@ String toString() {
return 'SnSticker(id: $id, slug: $slug, imageId: $imageId, image: $image, packId: $packId, pack: $pack, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
}
}
/// @nodoc
@ -50,6 +52,7 @@ $Res call({
String id, String slug, String imageId, SnCloudFile image, String packId, SnStickerPack? pack, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
});
$SnCloudFileCopyWith<$Res> get image;$SnStickerPackCopyWith<$Res>? get pack;
}
@ -101,6 +104,7 @@ $SnStickerPackCopyWith<$Res>? get pack {
}
}
/// @nodoc
@JsonSerializable()
@ -143,6 +147,7 @@ String toString() {
return 'SnSticker(id: $id, slug: $slug, imageId: $imageId, image: $image, packId: $packId, pack: $pack, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
}
}
/// @nodoc
@ -153,6 +158,7 @@ $Res call({
String id, String slug, String imageId, SnCloudFile image, String packId, SnStickerPack? pack, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
});
@override $SnCloudFileCopyWith<$Res> get image;@override $SnStickerPackCopyWith<$Res>? get pack;
}
@ -205,6 +211,7 @@ $SnStickerPackCopyWith<$Res>? get pack {
}
}
/// @nodoc
mixin _$SnStickerPack {
@ -218,6 +225,7 @@ $SnStickerPackCopyWith<SnStickerPack> get copyWith => _$SnStickerPackCopyWithImp
/// Serializes this SnStickerPack to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnStickerPack&&(identical(other.id, id) || other.id == id)&&(identical(other.name, name) || other.name == name)&&(identical(other.description, description) || other.description == description)&&(identical(other.prefix, prefix) || other.prefix == prefix)&&(identical(other.publisherId, publisherId) || other.publisherId == publisherId)&&(identical(other.publisher, publisher) || other.publisher == publisher)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt));
@ -232,6 +240,7 @@ String toString() {
return 'SnStickerPack(id: $id, name: $name, description: $description, prefix: $prefix, publisherId: $publisherId, publisher: $publisher, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
}
}
/// @nodoc
@ -242,6 +251,7 @@ $Res call({
String id, String name, String description, String prefix, String publisherId, SnPublisher? publisher, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
});
$SnPublisherCopyWith<$Res>? get publisher;
}
@ -284,6 +294,7 @@ $SnPublisherCopyWith<$Res>? get publisher {
}
}
/// @nodoc
@JsonSerializable()
@ -326,6 +337,7 @@ String toString() {
return 'SnStickerPack(id: $id, name: $name, description: $description, prefix: $prefix, publisherId: $publisherId, publisher: $publisher, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
}
}
/// @nodoc
@ -336,6 +348,7 @@ $Res call({
String id, String name, String description, String prefix, String publisherId, SnPublisher? publisher, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
});
@override $SnPublisherCopyWith<$Res>? get publisher;
}

View File

@ -26,6 +26,7 @@ $SnAccountCopyWith<SnAccount> get copyWith => _$SnAccountCopyWithImpl<SnAccount>
/// Serializes this SnAccount to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnAccount&&(identical(other.id, id) || other.id == id)&&(identical(other.name, name) || other.name == name)&&(identical(other.nick, nick) || other.nick == nick)&&(identical(other.language, language) || other.language == language)&&(identical(other.isSuperuser, isSuperuser) || other.isSuperuser == isSuperuser)&&(identical(other.profile, profile) || other.profile == profile)&&const DeepCollectionEquality().equals(other.badges, badges)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt));
@ -40,6 +41,7 @@ String toString() {
return 'SnAccount(id: $id, name: $name, nick: $nick, language: $language, isSuperuser: $isSuperuser, profile: $profile, badges: $badges, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
}
}
/// @nodoc
@ -50,6 +52,7 @@ $Res call({
String id, String name, String nick, String language, bool isSuperuser, SnAccountProfile profile, List<SnAccountBadge> badges, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
});
$SnAccountProfileCopyWith<$Res> get profile;
}
@ -90,6 +93,7 @@ $SnAccountProfileCopyWith<$Res> get profile {
}
}
/// @nodoc
@JsonSerializable()
@ -139,6 +143,7 @@ String toString() {
return 'SnAccount(id: $id, name: $name, nick: $nick, language: $language, isSuperuser: $isSuperuser, profile: $profile, badges: $badges, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
}
}
/// @nodoc
@ -149,6 +154,7 @@ $Res call({
String id, String name, String nick, String language, bool isSuperuser, SnAccountProfile profile, List<SnAccountBadge> badges, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
});
@override $SnAccountProfileCopyWith<$Res> get profile;
}
@ -190,6 +196,7 @@ $SnAccountProfileCopyWith<$Res> get profile {
}
}
/// @nodoc
mixin _$SnAccountProfile {
@ -203,6 +210,7 @@ $SnAccountProfileCopyWith<SnAccountProfile> get copyWith => _$SnAccountProfileCo
/// Serializes this SnAccountProfile to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnAccountProfile&&(identical(other.id, id) || other.id == id)&&(identical(other.firstName, firstName) || other.firstName == firstName)&&(identical(other.middleName, middleName) || other.middleName == middleName)&&(identical(other.lastName, lastName) || other.lastName == lastName)&&(identical(other.bio, bio) || other.bio == bio)&&(identical(other.gender, gender) || other.gender == gender)&&(identical(other.pronouns, pronouns) || other.pronouns == pronouns)&&(identical(other.location, location) || other.location == location)&&(identical(other.timeZone, timeZone) || other.timeZone == timeZone)&&(identical(other.birthday, birthday) || other.birthday == birthday)&&(identical(other.lastSeenAt, lastSeenAt) || other.lastSeenAt == lastSeenAt)&&(identical(other.activeBadge, activeBadge) || other.activeBadge == activeBadge)&&(identical(other.experience, experience) || other.experience == experience)&&(identical(other.level, level) || other.level == level)&&(identical(other.levelingProgress, levelingProgress) || other.levelingProgress == levelingProgress)&&(identical(other.picture, picture) || other.picture == picture)&&(identical(other.background, background) || other.background == background)&&(identical(other.verification, verification) || other.verification == verification)&&(identical(other.stellarMembership, stellarMembership) || other.stellarMembership == stellarMembership)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt));
@ -217,6 +225,7 @@ String toString() {
return 'SnAccountProfile(id: $id, firstName: $firstName, middleName: $middleName, lastName: $lastName, bio: $bio, gender: $gender, pronouns: $pronouns, location: $location, timeZone: $timeZone, birthday: $birthday, lastSeenAt: $lastSeenAt, activeBadge: $activeBadge, experience: $experience, level: $level, levelingProgress: $levelingProgress, picture: $picture, background: $background, verification: $verification, stellarMembership: $stellarMembership, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
}
}
/// @nodoc
@ -227,6 +236,7 @@ $Res call({
String id, String firstName, String middleName, String lastName, String bio, String gender, String pronouns, String location, String timeZone, DateTime? birthday, DateTime? lastSeenAt, SnAccountBadge? activeBadge, int experience, int level, double levelingProgress, SnCloudFile? picture, SnCloudFile? background, SnVerificationMark? verification, SnWalletSubscriptionRef? stellarMembership, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
});
$SnAccountBadgeCopyWith<$Res>? get activeBadge;$SnCloudFileCopyWith<$Res>? get picture;$SnCloudFileCopyWith<$Res>? get background;$SnVerificationMarkCopyWith<$Res>? get verification;$SnWalletSubscriptionRefCopyWith<$Res>? get stellarMembership;
}
@ -330,6 +340,7 @@ $SnWalletSubscriptionRefCopyWith<$Res>? get stellarMembership {
}
}
/// @nodoc
@JsonSerializable()
@ -385,6 +396,7 @@ String toString() {
return 'SnAccountProfile(id: $id, firstName: $firstName, middleName: $middleName, lastName: $lastName, bio: $bio, gender: $gender, pronouns: $pronouns, location: $location, timeZone: $timeZone, birthday: $birthday, lastSeenAt: $lastSeenAt, activeBadge: $activeBadge, experience: $experience, level: $level, levelingProgress: $levelingProgress, picture: $picture, background: $background, verification: $verification, stellarMembership: $stellarMembership, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
}
}
/// @nodoc
@ -395,6 +407,7 @@ $Res call({
String id, String firstName, String middleName, String lastName, String bio, String gender, String pronouns, String location, String timeZone, DateTime? birthday, DateTime? lastSeenAt, SnAccountBadge? activeBadge, int experience, int level, double levelingProgress, SnCloudFile? picture, SnCloudFile? background, SnVerificationMark? verification, SnWalletSubscriptionRef? stellarMembership, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
});
@override $SnAccountBadgeCopyWith<$Res>? get activeBadge;@override $SnCloudFileCopyWith<$Res>? get picture;@override $SnCloudFileCopyWith<$Res>? get background;@override $SnVerificationMarkCopyWith<$Res>? get verification;@override $SnWalletSubscriptionRefCopyWith<$Res>? get stellarMembership;
}
@ -499,6 +512,7 @@ $SnWalletSubscriptionRefCopyWith<$Res>? get stellarMembership {
}
}
/// @nodoc
mixin _$SnAccountStatus {
@ -512,6 +526,7 @@ $SnAccountStatusCopyWith<SnAccountStatus> get copyWith => _$SnAccountStatusCopyW
/// Serializes this SnAccountStatus to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnAccountStatus&&(identical(other.id, id) || other.id == id)&&(identical(other.attitude, attitude) || other.attitude == attitude)&&(identical(other.isOnline, isOnline) || other.isOnline == isOnline)&&(identical(other.isInvisible, isInvisible) || other.isInvisible == isInvisible)&&(identical(other.isNotDisturb, isNotDisturb) || other.isNotDisturb == isNotDisturb)&&(identical(other.isCustomized, isCustomized) || other.isCustomized == isCustomized)&&(identical(other.label, label) || other.label == label)&&(identical(other.clearedAt, clearedAt) || other.clearedAt == clearedAt)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt));
@ -526,6 +541,7 @@ String toString() {
return 'SnAccountStatus(id: $id, attitude: $attitude, isOnline: $isOnline, isInvisible: $isInvisible, isNotDisturb: $isNotDisturb, isCustomized: $isCustomized, label: $label, clearedAt: $clearedAt, accountId: $accountId, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
}
}
/// @nodoc
@ -536,6 +552,9 @@ $Res call({
String id, int attitude, bool isOnline, bool isInvisible, bool isNotDisturb, bool isCustomized, String label, DateTime? clearedAt, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
});
}
/// @nodoc
class _$SnAccountStatusCopyWithImpl<$Res>
@ -567,6 +586,7 @@ as DateTime?,
}
/// @nodoc
@JsonSerializable()
@ -612,6 +632,7 @@ String toString() {
return 'SnAccountStatus(id: $id, attitude: $attitude, isOnline: $isOnline, isInvisible: $isInvisible, isNotDisturb: $isNotDisturb, isCustomized: $isCustomized, label: $label, clearedAt: $clearedAt, accountId: $accountId, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
}
}
/// @nodoc
@ -622,6 +643,9 @@ $Res call({
String id, int attitude, bool isOnline, bool isInvisible, bool isNotDisturb, bool isCustomized, String label, DateTime? clearedAt, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
});
}
/// @nodoc
class __$SnAccountStatusCopyWithImpl<$Res>
@ -651,8 +675,10 @@ as DateTime?,
));
}
}
/// @nodoc
mixin _$SnAccountBadge {
@ -666,6 +692,7 @@ $SnAccountBadgeCopyWith<SnAccountBadge> get copyWith => _$SnAccountBadgeCopyWith
/// Serializes this SnAccountBadge to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnAccountBadge&&(identical(other.id, id) || other.id == id)&&(identical(other.type, type) || other.type == type)&&(identical(other.label, label) || other.label == label)&&(identical(other.caption, caption) || other.caption == caption)&&const DeepCollectionEquality().equals(other.meta, meta)&&(identical(other.expiredAt, expiredAt) || other.expiredAt == expiredAt)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.activatedAt, activatedAt) || other.activatedAt == activatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt));
@ -680,6 +707,7 @@ String toString() {
return 'SnAccountBadge(id: $id, type: $type, label: $label, caption: $caption, meta: $meta, expiredAt: $expiredAt, accountId: $accountId, createdAt: $createdAt, updatedAt: $updatedAt, activatedAt: $activatedAt, deletedAt: $deletedAt)';
}
}
/// @nodoc
@ -690,6 +718,9 @@ $Res call({
String id, String type, String? label, String? caption, Map<String, dynamic> meta, DateTime? expiredAt, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? activatedAt, DateTime? deletedAt
});
}
/// @nodoc
class _$SnAccountBadgeCopyWithImpl<$Res>
@ -720,6 +751,7 @@ as DateTime?,
}
/// @nodoc
@JsonSerializable()
@ -770,6 +802,7 @@ String toString() {
return 'SnAccountBadge(id: $id, type: $type, label: $label, caption: $caption, meta: $meta, expiredAt: $expiredAt, accountId: $accountId, createdAt: $createdAt, updatedAt: $updatedAt, activatedAt: $activatedAt, deletedAt: $deletedAt)';
}
}
/// @nodoc
@ -780,6 +813,9 @@ $Res call({
String id, String type, String? label, String? caption, Map<String, dynamic> meta, DateTime? expiredAt, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? activatedAt, DateTime? deletedAt
});
}
/// @nodoc
class __$SnAccountBadgeCopyWithImpl<$Res>
@ -808,8 +844,10 @@ as DateTime?,
));
}
}
/// @nodoc
mixin _$SnContactMethod {
@ -823,6 +861,7 @@ $SnContactMethodCopyWith<SnContactMethod> get copyWith => _$SnContactMethodCopyW
/// Serializes this SnContactMethod to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnContactMethod&&(identical(other.id, id) || other.id == id)&&(identical(other.type, type) || other.type == type)&&(identical(other.verifiedAt, verifiedAt) || other.verifiedAt == verifiedAt)&&(identical(other.isPrimary, isPrimary) || other.isPrimary == isPrimary)&&(identical(other.content, content) || other.content == content)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt));
@ -837,6 +876,7 @@ String toString() {
return 'SnContactMethod(id: $id, type: $type, verifiedAt: $verifiedAt, isPrimary: $isPrimary, content: $content, accountId: $accountId, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
}
}
/// @nodoc
@ -847,6 +887,9 @@ $Res call({
String id, int type, DateTime? verifiedAt, bool isPrimary, String content, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
});
}
/// @nodoc
class _$SnContactMethodCopyWithImpl<$Res>
@ -875,6 +918,7 @@ as DateTime?,
}
/// @nodoc
@JsonSerializable()
@ -917,6 +961,7 @@ String toString() {
return 'SnContactMethod(id: $id, type: $type, verifiedAt: $verifiedAt, isPrimary: $isPrimary, content: $content, accountId: $accountId, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
}
}
/// @nodoc
@ -927,6 +972,9 @@ $Res call({
String id, int type, DateTime? verifiedAt, bool isPrimary, String content, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
});
}
/// @nodoc
class __$SnContactMethodCopyWithImpl<$Res>
@ -953,8 +1001,10 @@ as DateTime?,
));
}
}
/// @nodoc
mixin _$SnNotification {
@ -968,6 +1018,7 @@ $SnNotificationCopyWith<SnNotification> get copyWith => _$SnNotificationCopyWith
/// Serializes this SnNotification to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnNotification&&(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.topic, topic) || other.topic == topic)&&(identical(other.title, title) || other.title == title)&&(identical(other.subtitle, subtitle) || other.subtitle == subtitle)&&(identical(other.content, content) || other.content == content)&&const DeepCollectionEquality().equals(other.meta, meta)&&(identical(other.priority, priority) || other.priority == priority)&&(identical(other.viewedAt, viewedAt) || other.viewedAt == viewedAt)&&(identical(other.accountId, accountId) || other.accountId == accountId));
@ -982,6 +1033,7 @@ String toString() {
return 'SnNotification(createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, id: $id, topic: $topic, title: $title, subtitle: $subtitle, content: $content, meta: $meta, priority: $priority, viewedAt: $viewedAt, accountId: $accountId)';
}
}
/// @nodoc
@ -992,6 +1044,9 @@ $Res call({
DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, String id, String topic, String title, String subtitle, String content, Map<String, dynamic> meta, int priority, DateTime? viewedAt, String accountId
});
}
/// @nodoc
class _$SnNotificationCopyWithImpl<$Res>
@ -1023,6 +1078,7 @@ as String,
}
/// @nodoc
@JsonSerializable()
@ -1074,6 +1130,7 @@ String toString() {
return 'SnNotification(createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, id: $id, topic: $topic, title: $title, subtitle: $subtitle, content: $content, meta: $meta, priority: $priority, viewedAt: $viewedAt, accountId: $accountId)';
}
}
/// @nodoc
@ -1084,6 +1141,9 @@ $Res call({
DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, String id, String topic, String title, String subtitle, String content, Map<String, dynamic> meta, int priority, DateTime? viewedAt, String accountId
});
}
/// @nodoc
class __$SnNotificationCopyWithImpl<$Res>
@ -1113,8 +1173,10 @@ as String,
));
}
}
/// @nodoc
mixin _$SnVerificationMark {
@ -1128,6 +1190,7 @@ $SnVerificationMarkCopyWith<SnVerificationMark> get copyWith => _$SnVerification
/// Serializes this SnVerificationMark to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnVerificationMark&&(identical(other.type, type) || other.type == type)&&(identical(other.title, title) || other.title == title)&&(identical(other.description, description) || other.description == description)&&(identical(other.verifiedBy, verifiedBy) || other.verifiedBy == verifiedBy));
@ -1142,6 +1205,7 @@ String toString() {
return 'SnVerificationMark(type: $type, title: $title, description: $description, verifiedBy: $verifiedBy)';
}
}
/// @nodoc
@ -1152,6 +1216,9 @@ $Res call({
int type, String? title, String? description, String? verifiedBy
});
}
/// @nodoc
class _$SnVerificationMarkCopyWithImpl<$Res>
@ -1175,6 +1242,7 @@ as String?,
}
/// @nodoc
@JsonSerializable()
@ -1212,6 +1280,7 @@ String toString() {
return 'SnVerificationMark(type: $type, title: $title, description: $description, verifiedBy: $verifiedBy)';
}
}
/// @nodoc
@ -1222,6 +1291,9 @@ $Res call({
int type, String? title, String? description, String? verifiedBy
});
}
/// @nodoc
class __$SnVerificationMarkCopyWithImpl<$Res>
@ -1243,6 +1315,7 @@ as String?,
));
}
}
// dart format on

View File

@ -26,6 +26,7 @@ $SnWalletCopyWith<SnWallet> get copyWith => _$SnWalletCopyWithImpl<SnWallet>(thi
/// Serializes this SnWallet to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnWallet&&(identical(other.id, id) || other.id == id)&&const DeepCollectionEquality().equals(other.pockets, pockets)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.account, account) || other.account == account)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt));
@ -40,6 +41,7 @@ String toString() {
return 'SnWallet(id: $id, pockets: $pockets, accountId: $accountId, account: $account, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
}
}
/// @nodoc
@ -50,6 +52,7 @@ $Res call({
String id, List<SnWalletPocket> pockets, String accountId, SnAccount? account, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
});
$SnAccountCopyWith<$Res>? get account;
}
@ -90,6 +93,7 @@ $SnAccountCopyWith<$Res>? get account {
}
}
/// @nodoc
@JsonSerializable()
@ -136,6 +140,7 @@ String toString() {
return 'SnWallet(id: $id, pockets: $pockets, accountId: $accountId, account: $account, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
}
}
/// @nodoc
@ -146,6 +151,7 @@ $Res call({
String id, List<SnWalletPocket> pockets, String accountId, SnAccount? account, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
});
@override $SnAccountCopyWith<$Res>? get account;
}
@ -187,6 +193,7 @@ $SnAccountCopyWith<$Res>? get account {
}
}
/// @nodoc
mixin _$SnWalletPocket {
@ -200,6 +207,7 @@ $SnWalletPocketCopyWith<SnWalletPocket> get copyWith => _$SnWalletPocketCopyWith
/// Serializes this SnWalletPocket to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnWalletPocket&&(identical(other.id, id) || other.id == id)&&(identical(other.currency, currency) || other.currency == currency)&&(identical(other.amount, amount) || other.amount == amount)&&(identical(other.walletId, walletId) || other.walletId == walletId)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt));
@ -214,6 +222,7 @@ String toString() {
return 'SnWalletPocket(id: $id, currency: $currency, amount: $amount, walletId: $walletId, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
}
}
/// @nodoc
@ -224,6 +233,9 @@ $Res call({
String id, String currency, double amount, String walletId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
});
}
/// @nodoc
class _$SnWalletPocketCopyWithImpl<$Res>
@ -250,6 +262,7 @@ as DateTime?,
}
/// @nodoc
@JsonSerializable()
@ -290,6 +303,7 @@ String toString() {
return 'SnWalletPocket(id: $id, currency: $currency, amount: $amount, walletId: $walletId, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
}
}
/// @nodoc
@ -300,6 +314,9 @@ $Res call({
String id, String currency, double amount, String walletId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
});
}
/// @nodoc
class __$SnWalletPocketCopyWithImpl<$Res>
@ -324,8 +341,10 @@ as DateTime?,
));
}
}
/// @nodoc
mixin _$SnTransaction {
@ -339,6 +358,7 @@ $SnTransactionCopyWith<SnTransaction> get copyWith => _$SnTransactionCopyWithImp
/// Serializes this SnTransaction to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnTransaction&&(identical(other.id, id) || other.id == id)&&(identical(other.currency, currency) || other.currency == currency)&&(identical(other.amount, amount) || other.amount == amount)&&(identical(other.remarks, remarks) || other.remarks == remarks)&&(identical(other.type, type) || other.type == type)&&(identical(other.payerWalletId, payerWalletId) || other.payerWalletId == payerWalletId)&&(identical(other.payerWallet, payerWallet) || other.payerWallet == payerWallet)&&(identical(other.payeeWalletId, payeeWalletId) || other.payeeWalletId == payeeWalletId)&&(identical(other.payeeWallet, payeeWallet) || other.payeeWallet == payeeWallet)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt));
@ -353,6 +373,7 @@ String toString() {
return 'SnTransaction(id: $id, currency: $currency, amount: $amount, remarks: $remarks, type: $type, payerWalletId: $payerWalletId, payerWallet: $payerWallet, payeeWalletId: $payeeWalletId, payeeWallet: $payeeWallet, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
}
}
/// @nodoc
@ -363,6 +384,7 @@ $Res call({
String id, String currency, double amount, String? remarks, int type, String? payerWalletId, SnWallet? payerWallet, String? payeeWalletId, SnWallet? payeeWallet, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
});
$SnWalletCopyWith<$Res>? get payerWallet;$SnWalletCopyWith<$Res>? get payeeWallet;
}
@ -420,6 +442,7 @@ $SnWalletCopyWith<$Res>? get payeeWallet {
}
}
/// @nodoc
@JsonSerializable()
@ -465,6 +488,7 @@ String toString() {
return 'SnTransaction(id: $id, currency: $currency, amount: $amount, remarks: $remarks, type: $type, payerWalletId: $payerWalletId, payerWallet: $payerWallet, payeeWalletId: $payeeWalletId, payeeWallet: $payeeWallet, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
}
}
/// @nodoc
@ -475,6 +499,7 @@ $Res call({
String id, String currency, double amount, String? remarks, int type, String? payerWalletId, SnWallet? payerWallet, String? payeeWalletId, SnWallet? payeeWallet, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
});
@override $SnWalletCopyWith<$Res>? get payerWallet;@override $SnWalletCopyWith<$Res>? get payeeWallet;
}
@ -533,6 +558,7 @@ $SnWalletCopyWith<$Res>? get payeeWallet {
}
}
/// @nodoc
mixin _$SnWalletSubscription {
@ -546,6 +572,7 @@ $SnWalletSubscriptionCopyWith<SnWalletSubscription> get copyWith => _$SnWalletSu
/// Serializes this SnWalletSubscription to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnWalletSubscription&&(identical(other.id, id) || other.id == id)&&(identical(other.begunAt, begunAt) || other.begunAt == begunAt)&&(identical(other.endedAt, endedAt) || other.endedAt == endedAt)&&(identical(other.identifier, identifier) || other.identifier == identifier)&&(identical(other.isActive, isActive) || other.isActive == isActive)&&(identical(other.isFreeTrial, isFreeTrial) || other.isFreeTrial == isFreeTrial)&&(identical(other.status, status) || other.status == status)&&(identical(other.paymentMethod, paymentMethod) || other.paymentMethod == paymentMethod)&&const DeepCollectionEquality().equals(other.paymentDetails, paymentDetails)&&(identical(other.basePrice, basePrice) || other.basePrice == basePrice)&&(identical(other.couponId, couponId) || other.couponId == couponId)&&const DeepCollectionEquality().equals(other.coupon, coupon)&&(identical(other.renewalAt, renewalAt) || other.renewalAt == renewalAt)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.account, account) || other.account == account)&&(identical(other.isAvailable, isAvailable) || other.isAvailable == isAvailable)&&(identical(other.finalPrice, finalPrice) || other.finalPrice == finalPrice)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt));
@ -560,6 +587,7 @@ String toString() {
return 'SnWalletSubscription(id: $id, begunAt: $begunAt, endedAt: $endedAt, identifier: $identifier, isActive: $isActive, isFreeTrial: $isFreeTrial, status: $status, paymentMethod: $paymentMethod, paymentDetails: $paymentDetails, basePrice: $basePrice, couponId: $couponId, coupon: $coupon, renewalAt: $renewalAt, accountId: $accountId, account: $account, isAvailable: $isAvailable, finalPrice: $finalPrice, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
}
}
/// @nodoc
@ -570,6 +598,7 @@ $Res call({
String id, DateTime begunAt, DateTime? endedAt, String identifier, bool isActive, bool isFreeTrial, int status, String? paymentMethod, Map<String, dynamic>? paymentDetails, double? basePrice, String? couponId, dynamic coupon, DateTime? renewalAt, String accountId, SnAccount? account, bool isAvailable, double? finalPrice, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
});
$SnAccountCopyWith<$Res>? get account;
}
@ -623,6 +652,7 @@ $SnAccountCopyWith<$Res>? get account {
}
}
/// @nodoc
@JsonSerializable()
@ -684,6 +714,7 @@ String toString() {
return 'SnWalletSubscription(id: $id, begunAt: $begunAt, endedAt: $endedAt, identifier: $identifier, isActive: $isActive, isFreeTrial: $isFreeTrial, status: $status, paymentMethod: $paymentMethod, paymentDetails: $paymentDetails, basePrice: $basePrice, couponId: $couponId, coupon: $coupon, renewalAt: $renewalAt, accountId: $accountId, account: $account, isAvailable: $isAvailable, finalPrice: $finalPrice, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
}
}
/// @nodoc
@ -694,6 +725,7 @@ $Res call({
String id, DateTime begunAt, DateTime? endedAt, String identifier, bool isActive, bool isFreeTrial, int status, String? paymentMethod, Map<String, dynamic>? paymentDetails, double? basePrice, String? couponId, dynamic coupon, DateTime? renewalAt, String accountId, SnAccount? account, bool isAvailable, double? finalPrice, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
});
@override $SnAccountCopyWith<$Res>? get account;
}
@ -748,6 +780,7 @@ $SnAccountCopyWith<$Res>? get account {
}
}
/// @nodoc
mixin _$SnWalletSubscriptionRef {
@ -761,6 +794,7 @@ $SnWalletSubscriptionRefCopyWith<SnWalletSubscriptionRef> get copyWith => _$SnWa
/// Serializes this SnWalletSubscriptionRef to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnWalletSubscriptionRef&&(identical(other.id, id) || other.id == id)&&(identical(other.isActive, isActive) || other.isActive == isActive)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.identifier, identifier) || other.identifier == identifier));
@ -775,6 +809,7 @@ String toString() {
return 'SnWalletSubscriptionRef(id: $id, isActive: $isActive, accountId: $accountId, createdAt: $createdAt, deletedAt: $deletedAt, updatedAt: $updatedAt, identifier: $identifier)';
}
}
/// @nodoc
@ -785,6 +820,9 @@ $Res call({
String id, bool isActive, String accountId, DateTime createdAt, DateTime? deletedAt, DateTime updatedAt, String identifier
});
}
/// @nodoc
class _$SnWalletSubscriptionRefCopyWithImpl<$Res>
@ -811,6 +849,7 @@ as String,
}
/// @nodoc
@JsonSerializable()
@ -851,6 +890,7 @@ String toString() {
return 'SnWalletSubscriptionRef(id: $id, isActive: $isActive, accountId: $accountId, createdAt: $createdAt, deletedAt: $deletedAt, updatedAt: $updatedAt, identifier: $identifier)';
}
}
/// @nodoc
@ -861,6 +901,9 @@ $Res call({
String id, bool isActive, String accountId, DateTime createdAt, DateTime? deletedAt, DateTime updatedAt, String identifier
});
}
/// @nodoc
class __$SnWalletSubscriptionRefCopyWithImpl<$Res>
@ -885,8 +928,10 @@ as String,
));
}
}
/// @nodoc
mixin _$SnWalletOrder {
@ -900,6 +945,7 @@ $SnWalletOrderCopyWith<SnWalletOrder> get copyWith => _$SnWalletOrderCopyWithImp
/// Serializes this SnWalletOrder to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnWalletOrder&&(identical(other.id, id) || other.id == id)&&(identical(other.status, status) || other.status == status)&&(identical(other.currency, currency) || other.currency == currency)&&const DeepCollectionEquality().equals(other.remarks, remarks)&&(identical(other.appIdentifier, appIdentifier) || other.appIdentifier == appIdentifier)&&const DeepCollectionEquality().equals(other.meta, meta)&&(identical(other.amount, amount) || other.amount == amount)&&(identical(other.expiredAt, expiredAt) || other.expiredAt == expiredAt)&&(identical(other.payeeWalletId, payeeWalletId) || other.payeeWalletId == payeeWalletId)&&(identical(other.payeeWallet, payeeWallet) || other.payeeWallet == payeeWallet)&&(identical(other.transactionId, transactionId) || other.transactionId == transactionId)&&(identical(other.transaction, transaction) || other.transaction == transaction)&&(identical(other.issuerAppId, issuerAppId) || other.issuerAppId == issuerAppId)&&const DeepCollectionEquality().equals(other.issuerApp, issuerApp)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt));
@ -914,6 +960,7 @@ String toString() {
return 'SnWalletOrder(id: $id, status: $status, currency: $currency, remarks: $remarks, appIdentifier: $appIdentifier, meta: $meta, amount: $amount, expiredAt: $expiredAt, payeeWalletId: $payeeWalletId, payeeWallet: $payeeWallet, transactionId: $transactionId, transaction: $transaction, issuerAppId: $issuerAppId, issuerApp: $issuerApp, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
}
}
/// @nodoc
@ -924,6 +971,7 @@ $Res call({
String id, int status, String currency, dynamic remarks, String appIdentifier, Map<String, dynamic> meta, int amount, DateTime expiredAt, String? payeeWalletId, SnWallet? payeeWallet, String? transactionId, SnTransaction? transaction, String? issuerAppId, dynamic issuerApp, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
});
$SnWalletCopyWith<$Res>? get payeeWallet;$SnTransactionCopyWith<$Res>? get transaction;
}
@ -986,6 +1034,7 @@ $SnTransactionCopyWith<$Res>? get transaction {
}
}
/// @nodoc
@JsonSerializable()
@ -1042,6 +1091,7 @@ String toString() {
return 'SnWalletOrder(id: $id, status: $status, currency: $currency, remarks: $remarks, appIdentifier: $appIdentifier, meta: $meta, amount: $amount, expiredAt: $expiredAt, payeeWalletId: $payeeWalletId, payeeWallet: $payeeWallet, transactionId: $transactionId, transaction: $transaction, issuerAppId: $issuerAppId, issuerApp: $issuerApp, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
}
}
/// @nodoc
@ -1052,6 +1102,7 @@ $Res call({
String id, int status, String currency, dynamic remarks, String appIdentifier, Map<String, dynamic> meta, int amount, DateTime expiredAt, String? payeeWalletId, SnWallet? payeeWallet, String? transactionId, SnTransaction? transaction, String? issuerAppId, dynamic issuerApp, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
});
@override $SnWalletCopyWith<$Res>? get payeeWallet;@override $SnTransactionCopyWith<$Res>? get transaction;
}

View File

@ -22,11 +22,14 @@ mixin _$CallState {
@pragma('vm:prefer-inline')
$CallStateCopyWith<CallState> get copyWith => _$CallStateCopyWithImpl<CallState>(this as CallState, _$identity);
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is CallState&&(identical(other.isConnected, isConnected) || other.isConnected == isConnected)&&(identical(other.isMicrophoneEnabled, isMicrophoneEnabled) || other.isMicrophoneEnabled == isMicrophoneEnabled)&&(identical(other.isCameraEnabled, isCameraEnabled) || other.isCameraEnabled == isCameraEnabled)&&(identical(other.isScreenSharing, isScreenSharing) || other.isScreenSharing == isScreenSharing)&&(identical(other.duration, duration) || other.duration == duration)&&(identical(other.error, error) || other.error == error));
}
@override
int get hashCode => Object.hash(runtimeType,isConnected,isMicrophoneEnabled,isCameraEnabled,isScreenSharing,duration,error);
@ -35,6 +38,7 @@ String toString() {
return 'CallState(isConnected: $isConnected, isMicrophoneEnabled: $isMicrophoneEnabled, isCameraEnabled: $isCameraEnabled, isScreenSharing: $isScreenSharing, duration: $duration, error: $error)';
}
}
/// @nodoc
@ -45,6 +49,9 @@ $Res call({
bool isConnected, bool isMicrophoneEnabled, bool isCameraEnabled, bool isScreenSharing, Duration duration, String? error
});
}
/// @nodoc
class _$CallStateCopyWithImpl<$Res>
@ -70,8 +77,10 @@ as String?,
}
/// @nodoc
class _CallState implements CallState {
const _CallState({required this.isConnected, required this.isMicrophoneEnabled, required this.isCameraEnabled, required this.isScreenSharing, this.duration = const Duration(seconds: 0), this.error});
@ -89,11 +98,14 @@ class _CallState implements CallState {
@pragma('vm:prefer-inline')
_$CallStateCopyWith<_CallState> get copyWith => __$CallStateCopyWithImpl<_CallState>(this, _$identity);
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _CallState&&(identical(other.isConnected, isConnected) || other.isConnected == isConnected)&&(identical(other.isMicrophoneEnabled, isMicrophoneEnabled) || other.isMicrophoneEnabled == isMicrophoneEnabled)&&(identical(other.isCameraEnabled, isCameraEnabled) || other.isCameraEnabled == isCameraEnabled)&&(identical(other.isScreenSharing, isScreenSharing) || other.isScreenSharing == isScreenSharing)&&(identical(other.duration, duration) || other.duration == duration)&&(identical(other.error, error) || other.error == error));
}
@override
int get hashCode => Object.hash(runtimeType,isConnected,isMicrophoneEnabled,isCameraEnabled,isScreenSharing,duration,error);
@ -102,6 +114,7 @@ String toString() {
return 'CallState(isConnected: $isConnected, isMicrophoneEnabled: $isMicrophoneEnabled, isCameraEnabled: $isCameraEnabled, isScreenSharing: $isScreenSharing, duration: $duration, error: $error)';
}
}
/// @nodoc
@ -112,6 +125,9 @@ $Res call({
bool isConnected, bool isMicrophoneEnabled, bool isCameraEnabled, bool isScreenSharing, Duration duration, String? error
});
}
/// @nodoc
class __$CallStateCopyWithImpl<$Res>
@ -135,6 +151,7 @@ as String?,
));
}
}
/// @nodoc
@ -147,11 +164,14 @@ mixin _$CallParticipantLive {
@pragma('vm:prefer-inline')
$CallParticipantLiveCopyWith<CallParticipantLive> get copyWith => _$CallParticipantLiveCopyWithImpl<CallParticipantLive>(this as CallParticipantLive, _$identity);
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is CallParticipantLive&&(identical(other.participant, participant) || other.participant == participant)&&(identical(other.remoteParticipant, remoteParticipant) || other.remoteParticipant == remoteParticipant));
}
@override
int get hashCode => Object.hash(runtimeType,participant,remoteParticipant);
@ -160,6 +180,7 @@ String toString() {
return 'CallParticipantLive(participant: $participant, remoteParticipant: $remoteParticipant)';
}
}
/// @nodoc
@ -170,6 +191,7 @@ $Res call({
CallParticipant participant, Participant remoteParticipant
});
$CallParticipantCopyWith<$Res> get participant;
}
@ -202,8 +224,10 @@ $CallParticipantCopyWith<$Res> get participant {
}
}
/// @nodoc
class _CallParticipantLive extends CallParticipantLive {
const _CallParticipantLive({required this.participant, required this.remoteParticipant}): super._();
@ -217,11 +241,14 @@ class _CallParticipantLive extends CallParticipantLive {
@pragma('vm:prefer-inline')
_$CallParticipantLiveCopyWith<_CallParticipantLive> get copyWith => __$CallParticipantLiveCopyWithImpl<_CallParticipantLive>(this, _$identity);
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _CallParticipantLive&&(identical(other.participant, participant) || other.participant == participant)&&(identical(other.remoteParticipant, remoteParticipant) || other.remoteParticipant == remoteParticipant));
}
@override
int get hashCode => Object.hash(runtimeType,participant,remoteParticipant);
@ -230,6 +257,7 @@ String toString() {
return 'CallParticipantLive(participant: $participant, remoteParticipant: $remoteParticipant)';
}
}
/// @nodoc
@ -240,6 +268,7 @@ $Res call({
CallParticipant participant, Participant remoteParticipant
});
@override $CallParticipantCopyWith<$Res> get participant;
}

View File

@ -23,11 +23,14 @@ mixin _$AppSettings {
@pragma('vm:prefer-inline')
$AppSettingsCopyWith<AppSettings> get copyWith => _$AppSettingsCopyWithImpl<AppSettings>(this as AppSettings, _$identity);
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is AppSettings&&(identical(other.autoTranslate, autoTranslate) || other.autoTranslate == autoTranslate)&&(identical(other.soundEffects, soundEffects) || other.soundEffects == soundEffects)&&(identical(other.aprilFoolFeatures, aprilFoolFeatures) || other.aprilFoolFeatures == aprilFoolFeatures)&&(identical(other.enterToSend, enterToSend) || other.enterToSend == enterToSend)&&(identical(other.appBarTransparent, appBarTransparent) || other.appBarTransparent == appBarTransparent)&&(identical(other.customFonts, customFonts) || other.customFonts == customFonts)&&(identical(other.appColorScheme, appColorScheme) || other.appColorScheme == appColorScheme)&&(identical(other.windowSize, windowSize) || other.windowSize == windowSize));
}
@override
int get hashCode => Object.hash(runtimeType,autoTranslate,soundEffects,aprilFoolFeatures,enterToSend,appBarTransparent,customFonts,appColorScheme,windowSize);
@ -36,6 +39,7 @@ String toString() {
return 'AppSettings(autoTranslate: $autoTranslate, soundEffects: $soundEffects, aprilFoolFeatures: $aprilFoolFeatures, enterToSend: $enterToSend, appBarTransparent: $appBarTransparent, customFonts: $customFonts, appColorScheme: $appColorScheme, windowSize: $windowSize)';
}
}
/// @nodoc
@ -46,6 +50,9 @@ $Res call({
bool autoTranslate, bool soundEffects, bool aprilFoolFeatures, bool enterToSend, bool appBarTransparent, String? customFonts, int? appColorScheme, Size? windowSize
});
}
/// @nodoc
class _$AppSettingsCopyWithImpl<$Res>
@ -73,8 +80,10 @@ as Size?,
}
/// @nodoc
class _AppSettings implements AppSettings {
const _AppSettings({required this.autoTranslate, required this.soundEffects, required this.aprilFoolFeatures, required this.enterToSend, required this.appBarTransparent, required this.customFonts, required this.appColorScheme, required this.windowSize});
@ -95,11 +104,14 @@ class _AppSettings implements AppSettings {
@pragma('vm:prefer-inline')
_$AppSettingsCopyWith<_AppSettings> get copyWith => __$AppSettingsCopyWithImpl<_AppSettings>(this, _$identity);
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _AppSettings&&(identical(other.autoTranslate, autoTranslate) || other.autoTranslate == autoTranslate)&&(identical(other.soundEffects, soundEffects) || other.soundEffects == soundEffects)&&(identical(other.aprilFoolFeatures, aprilFoolFeatures) || other.aprilFoolFeatures == aprilFoolFeatures)&&(identical(other.enterToSend, enterToSend) || other.enterToSend == enterToSend)&&(identical(other.appBarTransparent, appBarTransparent) || other.appBarTransparent == appBarTransparent)&&(identical(other.customFonts, customFonts) || other.customFonts == customFonts)&&(identical(other.appColorScheme, appColorScheme) || other.appColorScheme == appColorScheme)&&(identical(other.windowSize, windowSize) || other.windowSize == windowSize));
}
@override
int get hashCode => Object.hash(runtimeType,autoTranslate,soundEffects,aprilFoolFeatures,enterToSend,appBarTransparent,customFonts,appColorScheme,windowSize);
@ -108,6 +120,7 @@ String toString() {
return 'AppSettings(autoTranslate: $autoTranslate, soundEffects: $soundEffects, aprilFoolFeatures: $aprilFoolFeatures, enterToSend: $enterToSend, appBarTransparent: $appBarTransparent, customFonts: $customFonts, appColorScheme: $appColorScheme, windowSize: $windowSize)';
}
}
/// @nodoc
@ -118,6 +131,9 @@ $Res call({
bool autoTranslate, bool soundEffects, bool aprilFoolFeatures, bool enterToSend, bool appBarTransparent, String? customFonts, int? appColorScheme, Size? windowSize
});
}
/// @nodoc
class __$AppSettingsCopyWithImpl<$Res>
@ -143,6 +159,7 @@ as Size?,
));
}
}
// dart format on

View File

@ -32,7 +32,6 @@ class UserInfoNotifier extends StateNotifier<AsyncValue<SnAccount?>> {
state = const AsyncValue.data(null);
final prefs = _ref.read(sharedPreferencesProvider);
await prefs.remove(kTokenPairStoreKey);
_ref.invalidate(userInfoProvider);
_ref.invalidate(tokenProvider);
}
}

View File

@ -15,6 +15,9 @@ T _$identity<T>(T value) => value;
/// @nodoc
mixin _$WebSocketState implements DiagnosticableTreeMixin {
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
properties
@ -27,6 +30,7 @@ bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is WebSocketState);
}
@override
int get hashCode => runtimeType.hashCode;
@ -35,6 +39,7 @@ String toString({ DiagnosticLevel minLevel = DiagnosticLevel.info }) {
return 'WebSocketState()';
}
}
/// @nodoc
@ -42,12 +47,18 @@ class $WebSocketStateCopyWith<$Res> {
$WebSocketStateCopyWith(WebSocketState _, $Res Function(WebSocketState) __);
}
/// @nodoc
class _Connected with DiagnosticableTreeMixin implements WebSocketState {
const _Connected();
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
properties
@ -60,6 +71,7 @@ bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _Connected);
}
@override
int get hashCode => runtimeType.hashCode;
@ -68,14 +80,23 @@ String toString({ DiagnosticLevel minLevel = DiagnosticLevel.info }) {
return 'WebSocketState.connected()';
}
}
/// @nodoc
class _Connecting with DiagnosticableTreeMixin implements WebSocketState {
const _Connecting();
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
properties
@ -88,6 +109,7 @@ bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _Connecting);
}
@override
int get hashCode => runtimeType.hashCode;
@ -96,14 +118,23 @@ String toString({ DiagnosticLevel minLevel = DiagnosticLevel.info }) {
return 'WebSocketState.connecting()';
}
}
/// @nodoc
class _Disconnected with DiagnosticableTreeMixin implements WebSocketState {
const _Disconnected();
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
properties
@ -116,6 +147,7 @@ bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _Disconnected);
}
@override
int get hashCode => runtimeType.hashCode;
@ -124,10 +156,15 @@ String toString({ DiagnosticLevel minLevel = DiagnosticLevel.info }) {
return 'WebSocketState.disconnected()';
}
}
/// @nodoc
class _Error with DiagnosticableTreeMixin implements WebSocketState {
const _Error(this.message);
@ -140,6 +177,7 @@ class _Error with DiagnosticableTreeMixin implements WebSocketState {
@pragma('vm:prefer-inline')
_$ErrorCopyWith<_Error> get copyWith => __$ErrorCopyWithImpl<_Error>(this, _$identity);
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
properties
@ -152,6 +190,7 @@ bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _Error&&(identical(other.message, message) || other.message == message));
}
@override
int get hashCode => Object.hash(runtimeType,message);
@ -160,6 +199,7 @@ String toString({ DiagnosticLevel minLevel = DiagnosticLevel.info }) {
return 'WebSocketState.error(message: $message)';
}
}
/// @nodoc
@ -170,6 +210,9 @@ $Res call({
String message
});
}
/// @nodoc
class __$ErrorCopyWithImpl<$Res>
@ -188,8 +231,10 @@ as String,
));
}
}
/// @nodoc
mixin _$WebSocketPacket implements DiagnosticableTreeMixin {
@ -224,6 +269,7 @@ String toString({ DiagnosticLevel minLevel = DiagnosticLevel.info }) {
return 'WebSocketPacket(type: $type, data: $data, errorMessage: $errorMessage)';
}
}
/// @nodoc
@ -234,6 +280,9 @@ $Res call({
String type, Map<String, dynamic>? data, String? errorMessage
});
}
/// @nodoc
class _$WebSocketPacketCopyWithImpl<$Res>
@ -256,6 +305,7 @@ as String?,
}
/// @nodoc
@JsonSerializable()
@ -306,6 +356,7 @@ String toString({ DiagnosticLevel minLevel = DiagnosticLevel.info }) {
return 'WebSocketPacket(type: $type, data: $data, errorMessage: $errorMessage)';
}
}
/// @nodoc
@ -316,6 +367,9 @@ $Res call({
String type, Map<String, dynamic>? data, String? errorMessage
});
}
/// @nodoc
class __$WebSocketPacketCopyWithImpl<$Res>
@ -336,6 +390,7 @@ as String?,
));
}
}
// dart format on

View File

@ -31,6 +31,7 @@ import 'package:island/screens/settings.dart';
import 'package:island/screens/realm/realms.dart';
import 'package:island/screens/realm/detail.dart';
import 'package:island/screens/account/event_calendar.dart';
import 'package:island/screens/discovery/realms.dart';
// Shell route keys for nested navigation
final rootNavigatorKey = GlobalKey<NavigatorState>();
@ -52,7 +53,10 @@ final routerProvider = Provider<GoRouter>((ref) {
// Standalone routes without bottom navigation
GoRoute(
path: '/posts/compose',
builder: (context, state) => const PostComposeScreen(),
builder:
(context, state) => PostComposeScreen(
initialState: state.extra as PostComposeInitialState?,
),
),
GoRoute(
path: '/posts/:id/edit',
@ -75,44 +79,45 @@ final routerProvider = Provider<GoRouter>((ref) {
return EventCalanderScreen(name: name);
},
),
GoRoute(
path: '/creators',
builder: (context, state) => const CreatorHubScreen(),
ShellRoute(
builder:
(context, state, child) => CreatorHubShellScreen(child: child),
routes: [
GoRoute(
path: ':name/posts',
path: '/creators',
builder: (context, state) => const CreatorHubScreen(),
),
GoRoute(
path: '/creators/:name/posts',
builder: (context, state) {
final name = state.pathParameters['name']!;
return CreatorPostListScreen(pubName: name);
},
),
GoRoute(
path: ':name/stickers',
path: '/creators/:name/stickers',
builder: (context, state) {
final name = state.pathParameters['name']!;
return StickersScreen(pubName: name);
},
),
GoRoute(
path: ':name/stickers/new',
path: '/creators/:name/stickers/new',
builder: (context, state) {
final name = state.pathParameters['name']!;
return NewStickerPacksScreen(pubName: name);
},
),
GoRoute(
path: ':name/stickers/:packId/edit',
path: '/creators/:name/stickers/:packId/edit',
builder: (context, state) {
final name = state.pathParameters['name']!;
final packId = state.pathParameters['packId']!;
return EditStickerPacksScreen(
pubName: name,
packId: packId,
);
return EditStickerPacksScreen(pubName: name, packId: packId);
},
),
GoRoute(
path: ':name/stickers/:packId',
path: '/creators/:name/stickers/:packId',
builder: (context, state) {
final name = state.pathParameters['name']!;
final packId = state.pathParameters['packId']!;
@ -120,14 +125,14 @@ final routerProvider = Provider<GoRouter>((ref) {
},
),
GoRoute(
path: ':name/stickers/:packId/new',
path: '/creators/:name/stickers/:packId/new',
builder: (context, state) {
final packId = state.pathParameters['packId']!;
return NewStickersScreen(packId: packId);
},
),
GoRoute(
path: ':name/stickers/:packId/:id/edit',
path: '/creators/:name/stickers/:packId/:id/edit',
builder: (context, state) {
final packId = state.pathParameters['packId']!;
final id = state.pathParameters['id']!;
@ -135,11 +140,11 @@ final routerProvider = Provider<GoRouter>((ref) {
},
),
GoRoute(
path: 'new',
path: '/creators/new',
builder: (context, state) => const NewPublisherScreen(),
),
GoRoute(
path: ':name/edit',
path: '/creators/:name/edit',
builder: (context, state) {
final name = state.pathParameters['name']!;
return EditPublisherScreen(name: name);
@ -172,52 +177,64 @@ final routerProvider = Provider<GoRouter>((ref) {
},
routes: [
// Explore tab
GoRoute(
path: '/',
builder: (context, state) => const ExploreScreen(),
ShellRoute(
builder:
(context, state, child) => ExploreShellScreen(child: child),
routes: [
GoRoute(
path: 'posts/:id',
path: '/',
builder: (context, state) => const ExploreScreen(),
),
GoRoute(
path: '/posts/:id',
builder: (context, state) {
final id = state.pathParameters['id']!;
return PostDetailScreen(id: id);
},
),
GoRoute(
path: 'publishers/:name',
path: '/publishers/:name',
builder: (context, state) {
final name = state.pathParameters['name']!;
return PublisherProfileScreen(name: name);
},
),
GoRoute(
path: '/discovery/realms',
builder: (context, state) => const DiscoveryRealmsScreen(),
),
],
),
// Chat tab
GoRoute(
path: '/chat',
builder: (context, state) => const ChatListScreen(),
ShellRoute(
builder:
(context, state, child) => ChatShellScreen(child: child),
routes: [
GoRoute(
path: ':id',
path: '/chat',
builder: (context, state) => const ChatListScreen(),
),
GoRoute(
path: '/chat/new',
builder: (context, state) => const NewChatScreen(),
),
GoRoute(
path: '/chat/:id',
builder: (context, state) {
final id = state.pathParameters['id']!;
return ChatRoomScreen(id: id);
},
),
GoRoute(
path: 'new',
builder: (context, state) => const NewChatScreen(),
),
GoRoute(
path: ':id/edit',
path: '/chat/:id/edit',
builder: (context, state) {
final id = state.pathParameters['id']!;
return EditChatScreen(id: id);
},
),
GoRoute(
path: ':id/detail',
path: '/chat/:id/detail',
builder: (context, state) {
final id = state.pathParameters['id']!;
return ChatDetailScreen(id: id);
@ -227,9 +244,9 @@ final routerProvider = Provider<GoRouter>((ref) {
),
// Realms tab
GoRoute(
path: '/realms',
builder: (context, state) => const RealmListScreen(),
GoRoute(
path: '/realms',
builder: (context, state) => const RealmListScreen(),
routes: [
GoRoute(
path: 'new',
@ -253,39 +270,43 @@ final routerProvider = Provider<GoRouter>((ref) {
),
// Account tab
GoRoute(
path: '/account',
builder: (context, state) => const AccountScreen(),
ShellRoute(
builder:
(context, state, child) => AccountShellScreen(child: child),
routes: [
GoRoute(
path: 'notifications',
path: '/account',
builder: (context, state) => const AccountScreen(),
),
GoRoute(
path: '/account/notifications',
builder: (context, state) => const NotificationScreen(),
),
GoRoute(
path: 'wallet',
path: '/account/wallet',
builder: (context, state) => const WalletScreen(),
),
GoRoute(
path: 'relationships',
path: '/account/relationships',
builder: (context, state) => const RelationshipScreen(),
),
GoRoute(
path: ':name',
path: '/account/:name',
builder: (context, state) {
final name = state.pathParameters['name']!;
return AccountProfileScreen(name: name);
},
),
GoRoute(
path: 'me/update',
path: '/account/me/update',
builder: (context, state) => const UpdateProfileScreen(),
),
GoRoute(
path: 'me/leveling',
path: '/account/me/leveling',
builder: (context, state) => const LevelingScreen(),
),
GoRoute(
path: 'settings',
path: '/account/settings',
builder: (context, state) => const AccountSettingsScreen(),
),
],

View File

@ -143,7 +143,7 @@ class AccountScreen extends HookConsumerWidget {
progress: user.value!.profile.levelingProgress,
),
onTap: () {
context.push('/account/leveling');
context.push('/account/me/leveling');
},
).padding(horizontal: 12),
Row(
@ -200,7 +200,7 @@ class AccountScreen extends HookConsumerWidget {
],
),
onTap: () {
context.push('/notification');
context.push('/account/notifications');
},
),
ListTile(
@ -210,7 +210,7 @@ class AccountScreen extends HookConsumerWidget {
contentPadding: EdgeInsets.symmetric(horizontal: 24),
title: Text('wallet').tr(),
onTap: () {
context.push('/wallet');
context.push('/account/wallet');
},
),
ListTile(

View File

@ -53,17 +53,21 @@ Future<List<SnAccountBadge>> accountBadges(Ref ref, String uname) async {
@riverpod
Future<Color?> accountAppbarForcegroundColor(Ref ref, String uname) async {
final account = await ref.watch(accountProvider(uname).future);
if (account.profile.background == null) return null;
final palette = await PaletteGenerator.fromImageProvider(
CloudImageWidget.provider(
fileId: account.profile.background!.id,
serverUrl: ref.watch(serverUrlProvider),
),
);
final dominantColor = palette.dominantColor?.color;
if (dominantColor == null) return null;
return dominantColor.computeLuminance() > 0.5 ? Colors.black : Colors.white;
try {
final account = await ref.watch(accountProvider(uname).future);
if (account.profile.background == null) return null;
final palette = await PaletteGenerator.fromImageProvider(
CloudImageWidget.provider(
fileId: account.profile.background!.id,
serverUrl: ref.watch(serverUrlProvider),
),
);
final dominantColor = palette.dominantColor?.color;
if (dominantColor == null) return null;
return dominantColor.computeLuminance() > 0.5 ? Colors.black : Colors.white;
} catch (_) {
return null;
}
}
@riverpod

View File

@ -215,6 +215,7 @@ class RelationshipScreen extends HookConsumerWidget {
Future<void> addFriend() async {
final result = await showModalBottomSheet(
context: context,
useRootNavigator: true,
builder: (context) => AccountPickerSheet(),
);
if (result == null) return;

View File

@ -186,7 +186,7 @@ class ChatShellScreen extends HookConsumerWidget {
child: Row(
children: [
Flexible(flex: 2, child: ChatListScreen(isAside: true)),
VerticalDivider(width: 1),
const VerticalDivider(width: 1),
Flexible(flex: 4, child: child),
],
),
@ -227,7 +227,8 @@ class ChatListScreen extends HookConsumerWidget {
Future<void> createDirectMessage() async {
final result = await showModalBottomSheet(
context: context,
builder: (context) => AccountPickerSheet(),
useRootNavigator: true,
builder: (context) => const AccountPickerSheet(),
);
if (result == null) return;
final client = ref.read(apiClientProvider);
@ -242,7 +243,7 @@ class ChatListScreen extends HookConsumerWidget {
return AppScaffold(
extendBody: false, // Prevent conflicts with tabs navigation
appBar: AppBar(
title: Text('chat').tr(),
title: const Text('chat').tr(),
bottom: TabBar(
controller: tabController,
tabs: [
@ -296,7 +297,7 @@ class ChatListScreen extends HookConsumerWidget {
showModalBottomSheet(
isScrollControlled: true,
context: context,
builder: (context) => _ChatInvitesSheet(),
builder: (context) => const _ChatInvitesSheet(),
);
},
),
@ -307,13 +308,14 @@ class ChatListScreen extends HookConsumerWidget {
onPressed: () {
showModalBottomSheet(
context: context,
useRootNavigator: true,
builder:
(context) => Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
ListTile(
title: Text('createChatRoom').tr(),
title: const Text('createChatRoom').tr(),
leading: const Icon(Symbols.add),
onTap: () {
Navigator.pop(context);
@ -325,7 +327,7 @@ class ChatListScreen extends HookConsumerWidget {
},
),
ListTile(
title: Text('createDirectMessage').tr(),
title: const Text('createDirectMessage').tr(),
leading: const Icon(Symbols.person),
onTap: () {
Navigator.pop(context);
@ -432,17 +434,31 @@ class ChatListScreen extends HookConsumerWidget {
@riverpod
Future<SnChatRoom?> chatroom(Ref ref, String? identifier) async {
if (identifier == null) return null;
final client = ref.watch(apiClientProvider);
final resp = await client.get('/chat/$identifier');
return SnChatRoom.fromJson(resp.data);
try {
final client = ref.watch(apiClientProvider);
final resp = await client.get('/chat/$identifier');
return SnChatRoom.fromJson(resp.data);
} catch (err) {
if (err is DioException && err.response?.statusCode == 404) {
return null; // Chat room not found
}
rethrow; // Rethrow other errors
}
}
@riverpod
Future<SnChatMember?> chatroomIdentity(Ref ref, String? identifier) async {
if (identifier == null) return null;
final client = ref.watch(apiClientProvider);
final resp = await client.get('/chat/$identifier/members/me');
return SnChatMember.fromJson(resp.data);
try {
final client = ref.watch(apiClientProvider);
final resp = await client.get('/chat/$identifier/members/me');
return SnChatMember.fromJson(resp.data);
} catch (err) {
if (err is DioException && err.response?.statusCode == 404) {
return null; // Chat member not found
}
rethrow; // Rethrow other errors
}
}
class NewChatScreen extends StatelessWidget {
@ -450,7 +466,7 @@ class NewChatScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return EditChatScreen();
return const EditChatScreen();
}
}
@ -468,6 +484,8 @@ class EditChatScreen extends HookConsumerWidget {
final descriptionController = useTextEditingController();
final picture = useState<SnCloudFile?>(null);
final background = useState<SnCloudFile?>(null);
final isPublic = useState(true);
final isCommunity = useState(false);
final chat = ref.watch(chatroomProvider(id));
@ -480,12 +498,14 @@ class EditChatScreen extends HookConsumerWidget {
descriptionController.text = chat.value!.description ?? '';
picture.value = chat.value!.picture;
background.value = chat.value!.background;
isPublic.value = chat.value!.isPublic;
isCommunity.value = chat.value!.isCommunity;
currentRealm.value = joinedRealms.value?.firstWhereOrNull(
(realm) => realm.id == chat.value!.realmId,
);
}
return;
}, [chat]);
}, [chat, joinedRealms]);
void setPicture(String position) async {
showLoadingModal(context);
@ -503,9 +523,9 @@ class EditChatScreen extends HookConsumerWidget {
image: result,
allowedAspectRatios: [
if (position == 'background')
CropAspectRatio(height: 7, width: 16)
const CropAspectRatio(height: 7, width: 16)
else
CropAspectRatio(height: 1, width: 1),
const CropAspectRatio(height: 1, width: 1),
],
);
if (result == null) {
@ -562,6 +582,8 @@ class EditChatScreen extends HookConsumerWidget {
'background_id': background.value?.id,
'picture_id': picture.value?.id,
'realm_id': currentRealm.value?.id,
'is_public': isPublic.value,
'is_community': isCommunity.value,
},
options: Options(method: id == null ? 'POST' : 'PATCH'),
);
@ -654,6 +676,19 @@ class EditChatScreen extends HookConsumerWidget {
(_) => FocusManager.instance.primaryFocus?.unfocus(),
),
const SizedBox(height: 16),
CheckboxListTile(
title: const Text('isPublic').tr(),
subtitle: const Text('isPublicHint').tr(),
value: isPublic.value,
onChanged: (value) => isPublic.value = value ?? false,
),
CheckboxListTile(
title: const Text('isCommunity').tr(),
subtitle: const Text('isCommunityHint').tr(),
value: isCommunity.value,
onChanged: (value) => isCommunity.value = value ?? false,
),
const SizedBox(height: 16),
Align(
alignment: Alignment.centerRight,
child: TextButton.icon(
@ -754,7 +789,7 @@ class _ChatInvitesSheet extends HookConsumerWidget {
),
if (invite.chatRoom!.type == 1)
Badge(
label: Text('directMessage').tr(),
label: const Text('directMessage').tr(),
backgroundColor:
Theme.of(context).colorScheme.primary,
textColor:

View File

@ -25,7 +25,7 @@ final chatroomsJoinedProvider =
@Deprecated('Will be removed in 3.0. Use Ref instead')
// ignore: unused_element
typedef ChatroomsJoinedRef = AutoDisposeFutureProviderRef<List<SnChatRoom>>;
String _$chatroomHash() => r'dce3c0fc407f178bb7c306a08b9fa545795a9205';
String _$chatroomHash() => r'8dac7aaac50932e6dd213039102d43c1cf5f1d4e';
/// Copied from Dart SDK
class _SystemHash {
@ -164,7 +164,7 @@ class _ChatroomProviderElement
String? get identifier => (origin as ChatroomProvider).identifier;
}
String _$chatroomIdentityHash() => r'4c349ea4265df7b0498cf26c82dbaabe3d868727';
String _$chatroomIdentityHash() => r'ad6ad09b6fc4cf7c4abe146ea97f8e364a3d4fd0';
/// See also [chatroomIdentity].
@ProviderFor(chatroomIdentity)

View File

@ -295,6 +295,68 @@ class ChatRoomScreen extends HookConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) {
final chatRoom = ref.watch(chatroomProvider(id));
final chatIdentity = ref.watch(chatroomIdentityProvider(id));
if (chatIdentity.isLoading || chatRoom.isLoading) {
return AppScaffold(
appBar: AppBar(leading: const PageBackButton()),
body: CircularProgressIndicator().center(),
);
} else if (chatIdentity.value == null) {
// Identity was not found, user was not joined
return AppScaffold(
appBar: AppBar(leading: const PageBackButton()),
body: Center(
child:
ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 280),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
chatRoom.value?.isCommunity == true
? Symbols.person_add
: Symbols.person_remove,
size: 36,
fill: 1,
).padding(bottom: 4),
Text('chatNotJoined').tr(),
if (chatRoom.value?.isCommunity != true)
Text(
'chatUnableJoin',
textAlign: TextAlign.center,
).tr().bold()
else
FilledButton.tonalIcon(
onPressed: () async {
try {
showLoadingModal(context);
final apiClient = ref.read(apiClientProvider);
if (chatRoom.value == null) {
hideLoadingModal(context);
return;
}
await apiClient.post(
'/chat/${chatRoom.value!.id}/members/me',
);
ref.invalidate(chatroomIdentityProvider(id));
} catch (err) {
showErrorAlert(err);
} finally {
if (context.mounted) hideLoadingModal(context);
}
},
label: Text('chatJoin').tr(),
icon: const Icon(Icons.add),
).padding(top: 8),
],
),
).center(),
),
);
}
final messages = ref.watch(messagesNotifierProvider(id));
final messagesNotifier = ref.read(messagesNotifierProvider(id).notifier);
final ws = ref.watch(websocketProvider);
@ -429,6 +491,28 @@ class ChatRoomScreen extends HookConsumerWidget {
return () => subscription.cancel();
}, [ws, chatRoom]);
useEffect(() {
final wsState = ref.read(websocketStateProvider.notifier);
wsState.sendMessage(
jsonEncode(
WebSocketPacket(
type: 'messages.subscribe',
data: {'chat_room_id': id},
),
),
);
return () {
wsState.sendMessage(
jsonEncode(
WebSocketPacket(
type: 'messages.unsubscribe',
data: {'chat_room_id': id},
),
),
);
};
}, [id]);
Future<void> pickPhotoMedia() async {
final result = await ref
.watch(imagePickerProvider)
@ -603,7 +687,7 @@ class ChatRoomScreen extends HookConsumerWidget {
IconButton(
icon: const Icon(Icons.more_vert),
onPressed: () {
context.push('/chat/id/detail');
context.push('/chat/$id/detail');
},
),
const Gap(8),

View File

@ -584,8 +584,8 @@ class _ChatMemberListSheet extends HookConsumerWidget {
Future<void> invitePerson() async {
final result = await showModalBottomSheet(
isScrollControlled: true,
context: context,
useRootNavigator: true,
builder: (context) => const AccountPickerSheet(),
);
if (result == null) return;

View File

@ -22,11 +22,14 @@ mixin _$ChatRoomMemberState {
@pragma('vm:prefer-inline')
$ChatRoomMemberStateCopyWith<ChatRoomMemberState> get copyWith => _$ChatRoomMemberStateCopyWithImpl<ChatRoomMemberState>(this as ChatRoomMemberState, _$identity);
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is ChatRoomMemberState&&const DeepCollectionEquality().equals(other.members, members)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.total, total) || other.total == total)&&(identical(other.error, error) || other.error == error));
}
@override
int get hashCode => Object.hash(runtimeType,const DeepCollectionEquality().hash(members),isLoading,total,error);
@ -35,6 +38,7 @@ String toString() {
return 'ChatRoomMemberState(members: $members, isLoading: $isLoading, total: $total, error: $error)';
}
}
/// @nodoc
@ -45,6 +49,9 @@ $Res call({
List<SnChatMember> members, bool isLoading, int total, String? error
});
}
/// @nodoc
class _$ChatRoomMemberStateCopyWithImpl<$Res>
@ -68,8 +75,10 @@ as String?,
}
/// @nodoc
class _ChatRoomMemberState implements ChatRoomMemberState {
const _ChatRoomMemberState({required final List<SnChatMember> members, required this.isLoading, required this.total, this.error}): _members = members;
@ -91,11 +100,14 @@ class _ChatRoomMemberState implements ChatRoomMemberState {
@pragma('vm:prefer-inline')
_$ChatRoomMemberStateCopyWith<_ChatRoomMemberState> get copyWith => __$ChatRoomMemberStateCopyWithImpl<_ChatRoomMemberState>(this, _$identity);
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _ChatRoomMemberState&&const DeepCollectionEquality().equals(other._members, _members)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.total, total) || other.total == total)&&(identical(other.error, error) || other.error == error));
}
@override
int get hashCode => Object.hash(runtimeType,const DeepCollectionEquality().hash(_members),isLoading,total,error);
@ -104,6 +116,7 @@ String toString() {
return 'ChatRoomMemberState(members: $members, isLoading: $isLoading, total: $total, error: $error)';
}
}
/// @nodoc
@ -114,6 +127,9 @@ $Res call({
List<SnChatMember> members, bool isLoading, int total, String? error
});
}
/// @nodoc
class __$ChatRoomMemberStateCopyWithImpl<$Res>
@ -135,6 +151,7 @@ as String?,
));
}
}
// dart format on

View File

@ -22,11 +22,14 @@ mixin _$StickerWithPackQuery {
@pragma('vm:prefer-inline')
$StickerWithPackQueryCopyWith<StickerWithPackQuery> get copyWith => _$StickerWithPackQueryCopyWithImpl<StickerWithPackQuery>(this as StickerWithPackQuery, _$identity);
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is StickerWithPackQuery&&(identical(other.packId, packId) || other.packId == packId)&&(identical(other.id, id) || other.id == id));
}
@override
int get hashCode => Object.hash(runtimeType,packId,id);
@ -35,6 +38,7 @@ String toString() {
return 'StickerWithPackQuery(packId: $packId, id: $id)';
}
}
/// @nodoc
@ -45,6 +49,9 @@ $Res call({
String packId, String id
});
}
/// @nodoc
class _$StickerWithPackQueryCopyWithImpl<$Res>
@ -66,8 +73,10 @@ as String,
}
/// @nodoc
class _StickerWithPackQuery implements StickerWithPackQuery {
const _StickerWithPackQuery({required this.packId, required this.id});
@ -81,11 +90,14 @@ class _StickerWithPackQuery implements StickerWithPackQuery {
@pragma('vm:prefer-inline')
_$StickerWithPackQueryCopyWith<_StickerWithPackQuery> get copyWith => __$StickerWithPackQueryCopyWithImpl<_StickerWithPackQuery>(this, _$identity);
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _StickerWithPackQuery&&(identical(other.packId, packId) || other.packId == packId)&&(identical(other.id, id) || other.id == id));
}
@override
int get hashCode => Object.hash(runtimeType,packId,id);
@ -94,6 +106,7 @@ String toString() {
return 'StickerWithPackQuery(packId: $packId, id: $id)';
}
}
/// @nodoc
@ -104,6 +117,9 @@ $Res call({
String packId, String id
});
}
/// @nodoc
class __$StickerWithPackQueryCopyWithImpl<$Res>
@ -123,6 +139,7 @@ as String,
));
}
}
// dart format on

View File

@ -0,0 +1,64 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:gap/gap.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:island/widgets/app_scaffold.dart';
import 'package:island/widgets/realm/realm_list.dart';
import 'dart:async';
class DiscoveryRealmsScreen extends HookConsumerWidget {
const DiscoveryRealmsScreen({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
Timer? debounceTimer;
final searchController = useTextEditingController();
final currentQuery = useState<String?>(null);
return AppScaffold(
appBar: AppBar(title: Text('discoverRealms'.tr())),
body: Stack(
children: [
CustomScrollView(
slivers: [
SliverGap(80),
SliverRealmList(
query: currentQuery.value,
key: ValueKey(currentQuery.value),
),
SliverGap(MediaQuery.of(context).padding.bottom + 16),
],
),
Positioned(
top: 0,
left: 0,
right: 0,
child: Padding(
padding: const EdgeInsets.all(16),
child: SearchBar(
elevation: WidgetStateProperty.all(4),
controller: searchController,
hintText: 'search'.tr(),
leading: const Icon(Icons.search),
padding: WidgetStateProperty.all(
const EdgeInsets.symmetric(horizontal: 24),
),
onChanged: (value) {
if (debounceTimer?.isActive ?? false) {
debounceTimer?.cancel();
}
debounceTimer = Timer(const Duration(milliseconds: 300), () {
if (currentQuery.value != value) {
currentQuery.value = value;
}
});
},
),
),
),
],
),
);
}
}

View File

@ -1,22 +1,25 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:gap/gap.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:island/models/activity.dart';
import 'package:island/models/realm.dart';
import 'package:island/pods/userinfo.dart';
import 'package:island/services/responsive.dart';
import 'package:island/widgets/app_scaffold.dart';
import 'package:island/models/post.dart';
import 'package:island/widgets/check_in.dart';
import 'package:island/widgets/post/post_item.dart';
import 'package:island/widgets/tour/tour.dart';
import 'package:island/screens/tabs.dart';
import 'package:material_symbols_icons/symbols.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:riverpod_paging_utils/riverpod_paging_utils.dart';
import 'package:island/pods/network.dart';
import 'package:island/widgets/realm/realm_card.dart';
import 'package:island/widgets/publisher/publisher_card.dart';
import 'package:styled_widget/styled_widget.dart';
part 'explore.g.dart';
@ -83,65 +86,64 @@ class ExploreScreen extends HookConsumerWidget {
activityListNotifierProvider(currentFilter.value).notifier,
);
return TourTriggerWidget(
child: AppScaffold(
extendBody: false, // Prevent conflicts with tabs navigation
appBar: AppBar(
toolbarHeight: 0,
bottom: TabBar(
controller: tabController,
tabs: [
Tab(
child: Text(
'explore'.tr(),
textAlign: TextAlign.center,
style: TextStyle(
color: Theme.of(context).appBarTheme.foregroundColor!,
),
),
),
Tab(
child: Text(
'exploreFilterSubscriptions'.tr(),
textAlign: TextAlign.center,
style: TextStyle(
color: Theme.of(context).appBarTheme.foregroundColor!,
),
),
),
Tab(
child: Text(
'exploreFilterFriends'.tr(),
textAlign: TextAlign.center,
style: TextStyle(
color: Theme.of(context).appBarTheme.foregroundColor!,
),
),
),
],
),
),
floatingActionButton: FloatingActionButton(
heroTag: Key("explore-page-fab"),
onPressed: () {
context.push('/posts/compose').then((value) {
if (value != null) {
activitiesNotifier.forceRefresh();
}
});
},
child: const Icon(Symbols.edit),
),
floatingActionButtonLocation: TabbedFabLocation(context),
body: TabBarView(
return AppScaffold(
extendBody: false, // Prevent conflicts with tabs navigation
appBar: AppBar(
toolbarHeight: 0,
bottom: TabBar(
controller: tabController,
children: [
_buildActivityList(ref, null),
_buildActivityList(ref, 'subscriptions'),
_buildActivityList(ref, 'friends'),
tabs: [
Tab(
child: Text(
'explore'.tr(),
textAlign: TextAlign.center,
style: TextStyle(
color: Theme.of(context).appBarTheme.foregroundColor!,
),
),
),
Tab(
child: Text(
'exploreFilterSubscriptions'.tr(),
textAlign: TextAlign.center,
style: TextStyle(
color: Theme.of(context).appBarTheme.foregroundColor!,
),
),
),
Tab(
child: Text(
'exploreFilterFriends'.tr(),
textAlign: TextAlign.center,
style: TextStyle(
color: Theme.of(context).appBarTheme.foregroundColor!,
),
),
),
],
),
),
floatingActionButton: FloatingActionButton(
heroTag: Key("explore-page-fab"),
onPressed: () {
context.push('/posts/compose').then((value) {
if (value != null) {
activitiesNotifier.forceRefresh();
}
});
},
child: const Icon(Symbols.edit),
),
floatingActionButtonLocation: TabbedFabLocation(context),
body: TabBarView(
controller: tabController,
physics: const NeverScrollableScrollPhysics(),
children: [
_buildActivityList(ref, null),
_buildActivityList(ref, 'subscriptions'),
_buildActivityList(ref, 'friends'),
],
),
);
}
@ -171,6 +173,64 @@ class ExploreScreen extends HookConsumerWidget {
}
}
class _DiscoveryActivityItem extends StatelessWidget {
final Map<String, dynamic> data;
const _DiscoveryActivityItem({required this.data});
@override
Widget build(BuildContext context) {
final items = data['items'] as List;
final type = items.firstOrNull?['type'] ?? 'unknown';
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
const Icon(Symbols.explore, size: 19),
const Gap(8),
Text(
(switch (type) {
'realm' => 'discoverRealms',
'publisher' => 'discoverPublishers',
_ => 'unknown',
}).tr(),
style: Theme.of(context).textTheme.titleMedium,
).padding(top: 1),
],
).padding(horizontal: 20, top: 8, bottom: 4),
SizedBox(
height: 180,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: items.length,
padding: const EdgeInsets.symmetric(horizontal: 8),
itemBuilder: (context, index) {
final item = items[index];
switch (type) {
case 'realm':
return RealmCard(
realm: SnRealm.fromJson(item['data']),
maxWidth: 280,
);
case 'publisher':
return PublisherCard(
publisher: SnPublisher.fromJson(item['data']),
maxWidth: 280,
);
default:
return Placeholder();
}
},
),
).padding(bottom: 4),
],
);
}
}
class _ActivityListView extends HookConsumerWidget {
final CursorPagingData<SnActivity> data;
final int widgetCount;
@ -214,10 +274,14 @@ class _ActivityListView extends HookConsumerWidget {
itemWidget = PostItem(
backgroundColor:
isWideScreen(context) ? Colors.transparent : null,
item: SnPost.fromJson(item.data),
item: SnPost.fromJson(item.data!),
padding:
isReply
? EdgeInsets.only(left: 16, right: 16, bottom: 16)
? const EdgeInsets.only(
left: 16,
right: 16,
bottom: 16,
)
: null,
onRefresh: (_) {
activitiesNotifier.forceRefresh();
@ -245,6 +309,9 @@ class _ActivityListView extends HookConsumerWidget {
);
}
break;
case 'discovery':
itemWidget = _DiscoveryActivityItem(data: item.data!);
break;
default:
itemWidget = const Placeholder();
}
@ -274,6 +341,7 @@ class ActivityListNotifier extends _$ActivityListNotifier
if (cursor != null) 'cursor': cursor,
'take': take,
if (filter != null) 'filter': filter,
if (kDebugMode) 'debugInclude': 'realms,publishers',
};
final response = await client.get(

View File

@ -7,7 +7,7 @@ part of 'explore.dart';
// **************************************************************************
String _$activityListNotifierHash() =>
r'14ec2f211c86e1e64a9a34b142d0e8f78ff6361a';
r'57e9dcec944a9f88f8508b69fc91342592f5b349';
/// Copied from Dart SDK
class _SystemHash {

View File

@ -4,19 +4,18 @@ import 'dart:math' as math;
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:flutter/services.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:island/models/user.dart';
import 'package:island/pods/network.dart';
import 'package:island/pods/websocket.dart';
import 'package:island/widgets/alert.dart';
import 'package:island/route.dart';
import 'package:island/widgets/app_scaffold.dart';
import 'package:island/widgets/content/markdown.dart';
import 'package:relative_time/relative_time.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:url_launcher/url_launcher.dart';
import 'package:url_launcher/url_launcher_string.dart';
part 'notification.g.dart';
@ -180,36 +179,17 @@ class NotificationScreen extends HookConsumerWidget {
),
),
onTap: () {
if (notification.meta['link'] is String) {
final href = notification.meta['link'];
final uri = Uri.tryParse(href);
if (uri == null) {
showSnackBar(
'brokenLink'.tr(args: []),
action: SnackBarAction(
label: 'copyToClipboard'.tr(),
onPressed: () {
Clipboard.setData(ClipboardData(text: href));
clearSnackBar(context);
},
),
if (notification.meta['action_uri'] != null) {
var uri = notification.meta['action_uri'] as String;
if (uri.startsWith('/')) {
// In-app routes
rootNavigatorKey.currentContext?.push(
notification.meta['action_uri'],
);
return;
} else {
// External URLs
launchUrlString(uri);
}
if (uri.scheme == 'solian') {
context.push(
['', uri.host, ...uri.pathSegments].join('/'),
);
return;
}
showConfirmAlert(
'openLinkConfirmDescription'.tr(args: [href]),
'openLinkConfirm'.tr(),
).then((value) {
if (value) {
launchUrl(uri, mode: LaunchMode.externalApplication);
}
});
}
},
);

View File

@ -103,15 +103,32 @@ class PostComposeScreen extends HookConsumerWidget {
originalPost: originalPost,
forwardedPost: effectiveForwardedPost,
repliedPost: effectiveRepliedPost,
postType: 0, // Regular post type
),
[originalPost, effectiveForwardedPost, effectiveRepliedPost],
);
// Add a listener to the entire state to trigger rebuilds
final stateNotifier = useMemoized(
() => Listenable.merge([
state.titleController,
state.descriptionController,
state.contentController,
state.visibility,
state.attachments,
state.attachmentProgress,
state.currentPublisher,
state.submitting,
]),
[state],
);
useListenable(stateNotifier);
// Start auto-save when component mounts
useEffect(() {
if (originalPost == null) {
// Only auto-save for new posts, not edits
state.startAutoSave(ref, postType: 0);
state.startAutoSave(ref);
}
return () => state.stopAutoSave();
}, [state]);
@ -150,13 +167,18 @@ class PostComposeScreen extends HookConsumerWidget {
final drafts = ref.read(composeStorageNotifierProvider);
if (drafts.isNotEmpty) {
final mostRecentDraft = drafts.values.reduce(
(a, b) => (a.updatedAt ?? DateTime(0)).isAfter(b.updatedAt ?? DateTime(0)) ? a : b,
(a, b) =>
(a.updatedAt ?? DateTime(0)).isAfter(b.updatedAt ?? DateTime(0))
? a
: b,
);
// Only load if the draft has meaningful content
if (mostRecentDraft.content?.isNotEmpty == true || mostRecentDraft.title?.isNotEmpty == true) {
if (mostRecentDraft.content?.isNotEmpty == true ||
mostRecentDraft.title?.isNotEmpty == true) {
state.titleController.text = mostRecentDraft.title ?? '';
state.descriptionController.text = mostRecentDraft.description ?? '';
state.descriptionController.text =
mostRecentDraft.description ?? '';
state.contentController.text = mostRecentDraft.content ?? '';
state.visibility.value = mostRecentDraft.visibility;
}
@ -184,6 +206,8 @@ class PostComposeScreen extends HookConsumerWidget {
titleController: state.titleController,
descriptionController: state.descriptionController,
visibility: state.visibility,
tagsController: state.tagsController,
categoriesController: state.categoriesController,
onVisibilityChanged: () {
// Trigger rebuild if needed
},
@ -203,22 +227,18 @@ class PostComposeScreen extends HookConsumerWidget {
),
itemCount: state.attachments.value.length,
itemBuilder: (context, idx) {
return ValueListenableBuilder<Map<int, double>>(
valueListenable: state.attachmentProgress,
builder: (context, progressMap, _) {
return AttachmentPreview(
item: state.attachments.value[idx],
progress: progressMap[idx],
onRequestUpload:
() => ComposeLogic.uploadAttachment(ref, state, idx),
onDelete: () => ComposeLogic.deleteAttachment(ref, state, idx),
onMove: (delta) {
state.attachments.value = ComposeLogic.moveAttachment(
state.attachments.value,
idx,
delta,
);
},
final progressMap = state.attachmentProgress.value;
return AttachmentPreview(
item: state.attachments.value[idx],
progress: progressMap[idx],
onRequestUpload:
() => ComposeLogic.uploadAttachment(ref, state, idx),
onDelete: () => ComposeLogic.deleteAttachment(ref, state, idx),
onMove: (delta) {
state.attachments.value = ComposeLogic.moveAttachment(
state.attachments.value,
idx,
delta,
);
},
);
@ -232,26 +252,24 @@ class PostComposeScreen extends HookConsumerWidget {
for (var idx = 0; idx < state.attachments.value.length; idx++)
Container(
margin: const EdgeInsets.only(bottom: 8),
child: ValueListenableBuilder<Map<int, double>>(
valueListenable: state.attachmentProgress,
builder: (context, progressMap, _) {
return AttachmentPreview(
item: state.attachments.value[idx],
progress: progressMap[idx],
onRequestUpload:
() => ComposeLogic.uploadAttachment(ref, state, idx),
onDelete:
() => ComposeLogic.deleteAttachment(ref, state, idx),
onMove: (delta) {
state.attachments.value = ComposeLogic.moveAttachment(
state.attachments.value,
idx,
delta,
);
},
);
},
),
child: () {
final progressMap = state.attachmentProgress.value;
return AttachmentPreview(
item: state.attachments.value[idx],
progress: progressMap[idx],
onRequestUpload:
() => ComposeLogic.uploadAttachment(ref, state, idx),
onDelete:
() => ComposeLogic.deleteAttachment(ref, state, idx),
onMove: (delta) {
state.attachments.value = ComposeLogic.moveAttachment(
state.attachments.value,
idx,
delta,
);
},
);
}(),
),
],
);
@ -287,7 +305,8 @@ class PostComposeScreen extends HookConsumerWidget {
state.titleController.text = draft.title ?? '';
state.descriptionController.text =
draft.description ?? '';
state.contentController.text = draft.content ?? '';
state.contentController.text =
draft.content ?? '';
state.visibility.value = draft.visibility;
}
},
@ -306,39 +325,31 @@ class PostComposeScreen extends HookConsumerWidget {
onPressed: showSettingsSheet,
tooltip: 'postSettings'.tr(),
),
ValueListenableBuilder<bool>(
valueListenable: state.submitting,
builder: (context, submitting, _) {
return IconButton(
onPressed:
submitting
? null
: () => ComposeLogic.performAction(
ref,
state,
context,
originalPost: originalPost,
repliedPost: repliedPost,
forwardedPost: forwardedPost,
postType: 0, // Regular post type
),
icon:
submitting
? SizedBox(
width: 28,
height: 28,
child: const CircularProgressIndicator(
color: Colors.white,
strokeWidth: 2.5,
),
).center()
: Icon(
originalPost != null
? Symbols.edit
: Symbols.upload,
),
);
},
IconButton(
onPressed:
state.submitting.value
? null
: () => ComposeLogic.performAction(
ref,
state,
context,
originalPost: originalPost,
repliedPost: repliedPost,
forwardedPost: forwardedPost,
),
icon:
state.submitting.value
? SizedBox(
width: 28,
height: 28,
child: const CircularProgressIndicator(
color: Colors.white,
strokeWidth: 2.5,
),
).center()
: Icon(
originalPost != null ? Symbols.edit : Symbols.upload,
),
),
const Gap(8),
],
@ -399,7 +410,6 @@ class PostComposeScreen extends HookConsumerWidget {
originalPost: originalPost,
repliedPost: repliedPost,
forwardedPost: forwardedPost,
postType: 0, // Regular post type
),
child: TextField(
controller: state.contentController,
@ -420,22 +430,17 @@ class PostComposeScreen extends HookConsumerWidget {
const Gap(8),
// Attachments preview
ValueListenableBuilder<List<UniversalFile>>(
valueListenable: state.attachments,
builder: (context, attachments, _) {
if (attachments.isEmpty) {
return const SizedBox.shrink();
}
return LayoutBuilder(
builder: (context, constraints) {
final isWide = isWideScreen(context);
return isWide
? buildWideAttachmentGrid()
: buildNarrowAttachmentList();
},
);
},
),
if (state.attachments.value.isNotEmpty)
LayoutBuilder(
builder: (context, constraints) {
final isWide = isWideScreen(context);
return isWide
? buildWideAttachmentGrid()
: buildNarrowAttachmentList();
},
)
else
const SizedBox.shrink(),
],
),
),

View File

@ -26,6 +26,7 @@ $PostComposeInitialStateCopyWith<PostComposeInitialState> get copyWith => _$Post
/// Serializes this PostComposeInitialState to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is PostComposeInitialState&&(identical(other.title, title) || other.title == title)&&(identical(other.description, description) || other.description == description)&&(identical(other.content, content) || other.content == content)&&const DeepCollectionEquality().equals(other.attachments, attachments)&&(identical(other.visibility, visibility) || other.visibility == visibility));
@ -40,6 +41,7 @@ String toString() {
return 'PostComposeInitialState(title: $title, description: $description, content: $content, attachments: $attachments, visibility: $visibility)';
}
}
/// @nodoc
@ -50,6 +52,9 @@ $Res call({
String? title, String? description, String? content, List<UniversalFile> attachments, int? visibility
});
}
/// @nodoc
class _$PostComposeInitialStateCopyWithImpl<$Res>
@ -74,6 +79,7 @@ as int?,
}
/// @nodoc
@JsonSerializable()
@ -118,6 +124,7 @@ String toString() {
return 'PostComposeInitialState(title: $title, description: $description, content: $content, attachments: $attachments, visibility: $visibility)';
}
}
/// @nodoc
@ -128,6 +135,9 @@ $Res call({
String? title, String? description, String? content, List<UniversalFile> attachments, int? visibility
});
}
/// @nodoc
class __$PostComposeInitialStateCopyWithImpl<$Res>
@ -150,6 +160,7 @@ as int?,
));
}
}
// dart format on

View File

@ -60,7 +60,10 @@ class ArticleComposeScreen extends HookConsumerWidget {
final publishers = ref.watch(publishersManagedProvider);
final state = useMemoized(
() => ComposeLogic.createState(originalPost: originalPost),
() => ComposeLogic.createState(
originalPost: originalPost,
postType: 1, // Article type
),
[originalPost],
);
@ -70,7 +73,7 @@ class ArticleComposeScreen extends HookConsumerWidget {
if (originalPost == null) {
// Only auto-save for new articles, not edits
autoSaveTimer = Timer.periodic(const Duration(seconds: 3), (_) {
ComposeLogic.saveDraftWithoutUpload(ref, state, postType: 1);
ComposeLogic.saveDraftWithoutUpload(ref, state);
});
}
return () {
@ -78,7 +81,7 @@ class ArticleComposeScreen extends HookConsumerWidget {
state.stopAutoSave();
// Save final draft before disposing
if (originalPost == null) {
ComposeLogic.saveDraftWithoutUpload(ref, state, postType: 1);
ComposeLogic.saveDraftWithoutUpload(ref, state);
}
ComposeLogic.dispose(state);
autoSaveTimer?.cancel();
@ -140,6 +143,8 @@ class ArticleComposeScreen extends HookConsumerWidget {
titleController: state.titleController,
descriptionController: state.descriptionController,
visibility: state.visibility,
tagsController: state.tagsController,
categoriesController: state.categoriesController,
onVisibilityChanged: () {
// Trigger rebuild if needed
},
@ -360,7 +365,7 @@ class ArticleComposeScreen extends HookConsumerWidget {
return PopScope(
onPopInvoked: (_) {
if (originalPost == null) {
ComposeLogic.saveDraftWithoutUpload(ref, state, postType: 1);
ComposeLogic.saveDraftWithoutUpload(ref, state);
}
},
child: AppScaffold(
@ -408,7 +413,7 @@ class ArticleComposeScreen extends HookConsumerWidget {
),
IconButton(
icon: const Icon(Symbols.save),
onPressed: () => ComposeLogic.saveDraft(ref, state, postType: 1),
onPressed: () => ComposeLogic.saveDraft(ref, state),
tooltip: 'saveDraft'.tr(),
),
IconButton(
@ -435,7 +440,6 @@ class ArticleComposeScreen extends HookConsumerWidget {
state,
context,
originalPost: originalPost,
postType: 1, // Article type
),
icon:
submitting
@ -528,18 +532,17 @@ class ArticleComposeScreen extends HookConsumerWidget {
if (isPaste && isModifierPressed) {
ComposeLogic.handlePaste(state);
} else if (isSave && isModifierPressed) {
ComposeLogic.saveDraft(ref, state, postType: 1);
ComposeLogic.saveDraft(ref, state);
ComposeLogic.saveDraft(ref, state);
} else if (isSubmit && isModifierPressed && !state.submitting.value) {
ComposeLogic.performAction(
ref,
state,
context,
originalPost: originalPost,
postType: 1, // Article type
);
}
}
// Helper method to save article draft
}

View File

@ -54,25 +54,26 @@ Future<SnSubscriptionStatus> publisherSubscriptionStatus(
@riverpod
Future<Color?> publisherAppbarForcegroundColor(Ref ref, String pubName) async {
final publisher = await ref.watch(publisherProvider(pubName).future);
if (publisher.background == null) return null;
final palette = await PaletteGenerator.fromImageProvider(
CloudImageWidget.provider(
fileId: publisher.background!.id,
serverUrl: ref.watch(serverUrlProvider),
),
);
final dominantColor = palette.dominantColor?.color;
if (dominantColor == null) return null;
return dominantColor.computeLuminance() > 0.5 ? Colors.black : Colors.white;
try {
final publisher = await ref.watch(publisherProvider(pubName).future);
if (publisher.background == null) return null;
final palette = await PaletteGenerator.fromImageProvider(
CloudImageWidget.provider(
fileId: publisher.background!.id,
serverUrl: ref.watch(serverUrlProvider),
),
);
final dominantColor = palette.dominantColor?.color;
if (dominantColor == null) return null;
return dominantColor.computeLuminance() > 0.5 ? Colors.black : Colors.white;
} catch (_) {
return null;
}
}
class PublisherProfileScreen extends HookConsumerWidget {
final String name;
const PublisherProfileScreen({
super.key,
required this.name,
});
const PublisherProfileScreen({super.key, required this.name});
@override
Widget build(BuildContext context, WidgetRef ref) {

View File

@ -1,12 +1,17 @@
import 'package:dio/dio.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:island/screens/chat/chat.dart';
import 'package:flutter/material.dart';
import 'package:island/models/chat.dart';
import 'package:island/services/color.dart';
import 'package:palette_generator/palette_generator.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:gap/gap.dart';
import 'package:go_router/go_router.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:island/models/realm.dart';
import 'package:island/pods/network.dart';
import 'package:island/pods/config.dart';
import 'package:island/screens/realm/realms.dart';
import 'package:island/widgets/account/account_picker.dart';
import 'package:island/widgets/alert.dart';
@ -19,11 +24,40 @@ import 'package:styled_widget/styled_widget.dart';
part 'detail.g.dart';
@riverpod
Future<Color?> realmAppbarForegroundColor(Ref ref, String realmSlug) async {
final realm = await ref.watch(realmProvider(realmSlug).future);
if (realm?.background == null) return null;
final palette = await PaletteGenerator.fromImageProvider(
CloudImageWidget.provider(
fileId: realm!.background!.id,
serverUrl: ref.watch(serverUrlProvider),
),
);
final dominantColor = palette.dominantColor?.color;
if (dominantColor == null) return null;
return dominantColor.computeLuminance() > 0.5 ? Colors.black : Colors.white;
}
@riverpod
Future<SnRealmMember?> realmIdentity(Ref ref, String realmSlug) async {
try {
final apiClient = ref.watch(apiClientProvider);
final response = await apiClient.get('/realms/$realmSlug/members/me');
return SnRealmMember.fromJson(response.data);
} catch (err) {
if (err is DioException && err.response?.statusCode == 404) {
return null; // No identity found, user is not a member
}
rethrow;
}
}
@riverpod
Future<List<SnChatRoom>> realmChatRooms(Ref ref, String realmSlug) async {
final apiClient = ref.watch(apiClientProvider);
final response = await apiClient.get('/realms/$realmSlug/members/me');
return SnRealmMember.fromJson(response.data);
final response = await apiClient.get('/realms/$realmSlug/chat');
return (response.data as List).map((e) => SnChatRoom.fromJson(e)).toList();
}
class RealmDetailScreen extends HookConsumerWidget {
@ -34,9 +68,10 @@ class RealmDetailScreen extends HookConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final realmState = ref.watch(realmProvider(slug));
final appbarColor = ref.watch(realmAppbarForegroundColorProvider(slug));
const iconShadow = Shadow(
color: Colors.black54,
final iconShadow = Shadow(
color: appbarColor.value?.invert ?? Colors.black54,
blurRadius: 5.0,
offset: Offset(1.0, 1.0),
);
@ -51,7 +86,11 @@ class RealmDetailScreen extends HookConsumerWidget {
SliverAppBar(
expandedHeight: 180,
pinned: true,
leading: PageBackButton(shadows: [iconShadow]),
foregroundColor: appbarColor.value,
leading: PageBackButton(
color: appbarColor.value,
shadows: [iconShadow],
),
flexibleSpace: FlexibleSpaceBar(
background:
realm!.background?.id != null
@ -63,14 +102,16 @@ class RealmDetailScreen extends HookConsumerWidget {
title: Text(
realm.name,
style: TextStyle(
color: Theme.of(context).appBarTheme.foregroundColor,
color:
appbarColor.value ??
Theme.of(context).appBarTheme.foregroundColor,
shadows: [iconShadow],
),
),
),
actions: [
IconButton(
icon: const Icon(Icons.people, shadows: [iconShadow]),
icon: Icon(Icons.people, shadows: [iconShadow]),
onPressed: () {
showModalBottomSheet(
isScrollControlled: true,
@ -86,18 +127,97 @@ class RealmDetailScreen extends HookConsumerWidget {
],
),
SliverToBoxAdapter(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
realm.description,
style: const TextStyle(fontSize: 16),
),
],
),
),
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,
),
],
),
if (identity == null && realm.isCommunity)
FilledButton.tonalIcon(
onPressed: () async {
try {
final apiClient = ref.read(
apiClientProvider,
);
await apiClient.post(
'/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:
(error, _) => SliverToBoxAdapter(
child: Center(child: Text('Error: $error')),
),
data: (rooms) {
if (rooms.isEmpty) {
return const SliverToBoxAdapter(
child: SizedBox.shrink(),
);
}
return SliverList(
delegate: SliverChildBuilderDelegate((
context,
index,
) {
return ChatRoomListTile(
room: rooms[index],
onTap: () {
context.push('/chat/${rooms[index].id}');
},
);
}, childCount: rooms.length),
);
},
);
},
),
],
),
@ -114,8 +234,8 @@ class _RealmActionMenu extends HookConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final realmIdentityAsync = ref.watch(realmIdentityProvider(realmSlug));
final isModerator = realmIdentityAsync.when(
final realmIdentity = ref.watch(realmIdentityProvider(realmSlug));
final isModerator = realmIdentity.when(
data: (identity) => (identity?.role ?? 0) >= 50,
loading: () => false,
error: (_, _) => false,
@ -141,7 +261,7 @@ class _RealmActionMenu extends HookConsumerWidget {
],
),
),
realmIdentityAsync.when(
realmIdentity.when(
data:
(identity) =>
(identity?.role ?? 0) >= 100

View File

@ -6,7 +6,8 @@ part of 'detail.dart';
// RiverpodGenerator
// **************************************************************************
String _$realmIdentityHash() => r'eac6e829b5b46bcfadbf201ab6f918d78c894b9f';
String _$realmAppbarForegroundColorHash() =>
r'14b5563d861996ea182d0d2db7aa5c2bb3bbaf48';
/// Copied from Dart SDK
class _SystemHash {
@ -29,6 +30,133 @@ class _SystemHash {
}
}
/// See also [realmAppbarForegroundColor].
@ProviderFor(realmAppbarForegroundColor)
const realmAppbarForegroundColorProvider = RealmAppbarForegroundColorFamily();
/// See also [realmAppbarForegroundColor].
class RealmAppbarForegroundColorFamily extends Family<AsyncValue<Color?>> {
/// See also [realmAppbarForegroundColor].
const RealmAppbarForegroundColorFamily();
/// See also [realmAppbarForegroundColor].
RealmAppbarForegroundColorProvider call(String realmSlug) {
return RealmAppbarForegroundColorProvider(realmSlug);
}
@override
RealmAppbarForegroundColorProvider getProviderOverride(
covariant RealmAppbarForegroundColorProvider provider,
) {
return call(provider.realmSlug);
}
static const Iterable<ProviderOrFamily>? _dependencies = null;
@override
Iterable<ProviderOrFamily>? get dependencies => _dependencies;
static const Iterable<ProviderOrFamily>? _allTransitiveDependencies = null;
@override
Iterable<ProviderOrFamily>? get allTransitiveDependencies =>
_allTransitiveDependencies;
@override
String? get name => r'realmAppbarForegroundColorProvider';
}
/// See also [realmAppbarForegroundColor].
class RealmAppbarForegroundColorProvider
extends AutoDisposeFutureProvider<Color?> {
/// See also [realmAppbarForegroundColor].
RealmAppbarForegroundColorProvider(String realmSlug)
: this._internal(
(ref) => realmAppbarForegroundColor(
ref as RealmAppbarForegroundColorRef,
realmSlug,
),
from: realmAppbarForegroundColorProvider,
name: r'realmAppbarForegroundColorProvider',
debugGetCreateSourceHash:
const bool.fromEnvironment('dart.vm.product')
? null
: _$realmAppbarForegroundColorHash,
dependencies: RealmAppbarForegroundColorFamily._dependencies,
allTransitiveDependencies:
RealmAppbarForegroundColorFamily._allTransitiveDependencies,
realmSlug: realmSlug,
);
RealmAppbarForegroundColorProvider._internal(
super._createNotifier, {
required super.name,
required super.dependencies,
required super.allTransitiveDependencies,
required super.debugGetCreateSourceHash,
required super.from,
required this.realmSlug,
}) : super.internal();
final String realmSlug;
@override
Override overrideWith(
FutureOr<Color?> Function(RealmAppbarForegroundColorRef provider) create,
) {
return ProviderOverride(
origin: this,
override: RealmAppbarForegroundColorProvider._internal(
(ref) => create(ref as RealmAppbarForegroundColorRef),
from: from,
name: null,
dependencies: null,
allTransitiveDependencies: null,
debugGetCreateSourceHash: null,
realmSlug: realmSlug,
),
);
}
@override
AutoDisposeFutureProviderElement<Color?> createElement() {
return _RealmAppbarForegroundColorProviderElement(this);
}
@override
bool operator ==(Object other) {
return other is RealmAppbarForegroundColorProvider &&
other.realmSlug == realmSlug;
}
@override
int get hashCode {
var hash = _SystemHash.combine(0, runtimeType.hashCode);
hash = _SystemHash.combine(hash, realmSlug.hashCode);
return _SystemHash.finish(hash);
}
}
@Deprecated('Will be removed in 3.0. Use Ref instead')
// ignore: unused_element
mixin RealmAppbarForegroundColorRef on AutoDisposeFutureProviderRef<Color?> {
/// The parameter `realmSlug` of this provider.
String get realmSlug;
}
class _RealmAppbarForegroundColorProviderElement
extends AutoDisposeFutureProviderElement<Color?>
with RealmAppbarForegroundColorRef {
_RealmAppbarForegroundColorProviderElement(super.provider);
@override
String get realmSlug =>
(origin as RealmAppbarForegroundColorProvider).realmSlug;
}
String _$realmIdentityHash() => r'308d43eef8a6145c762d27bdf7e12e27149524db';
/// See also [realmIdentity].
@ProviderFor(realmIdentity)
const realmIdentityProvider = RealmIdentityFamily();
@ -148,6 +276,128 @@ class _RealmIdentityProviderElement
String get realmSlug => (origin as RealmIdentityProvider).realmSlug;
}
String _$realmChatRoomsHash() => r'8207c1e6f0922323967f208efeed027e943039cc';
/// See also [realmChatRooms].
@ProviderFor(realmChatRooms)
const realmChatRoomsProvider = RealmChatRoomsFamily();
/// See also [realmChatRooms].
class RealmChatRoomsFamily extends Family<AsyncValue<List<SnChatRoom>>> {
/// See also [realmChatRooms].
const RealmChatRoomsFamily();
/// See also [realmChatRooms].
RealmChatRoomsProvider call(String realmSlug) {
return RealmChatRoomsProvider(realmSlug);
}
@override
RealmChatRoomsProvider getProviderOverride(
covariant RealmChatRoomsProvider provider,
) {
return call(provider.realmSlug);
}
static const Iterable<ProviderOrFamily>? _dependencies = null;
@override
Iterable<ProviderOrFamily>? get dependencies => _dependencies;
static const Iterable<ProviderOrFamily>? _allTransitiveDependencies = null;
@override
Iterable<ProviderOrFamily>? get allTransitiveDependencies =>
_allTransitiveDependencies;
@override
String? get name => r'realmChatRoomsProvider';
}
/// See also [realmChatRooms].
class RealmChatRoomsProvider
extends AutoDisposeFutureProvider<List<SnChatRoom>> {
/// See also [realmChatRooms].
RealmChatRoomsProvider(String realmSlug)
: this._internal(
(ref) => realmChatRooms(ref as RealmChatRoomsRef, realmSlug),
from: realmChatRoomsProvider,
name: r'realmChatRoomsProvider',
debugGetCreateSourceHash:
const bool.fromEnvironment('dart.vm.product')
? null
: _$realmChatRoomsHash,
dependencies: RealmChatRoomsFamily._dependencies,
allTransitiveDependencies:
RealmChatRoomsFamily._allTransitiveDependencies,
realmSlug: realmSlug,
);
RealmChatRoomsProvider._internal(
super._createNotifier, {
required super.name,
required super.dependencies,
required super.allTransitiveDependencies,
required super.debugGetCreateSourceHash,
required super.from,
required this.realmSlug,
}) : super.internal();
final String realmSlug;
@override
Override overrideWith(
FutureOr<List<SnChatRoom>> Function(RealmChatRoomsRef provider) create,
) {
return ProviderOverride(
origin: this,
override: RealmChatRoomsProvider._internal(
(ref) => create(ref as RealmChatRoomsRef),
from: from,
name: null,
dependencies: null,
allTransitiveDependencies: null,
debugGetCreateSourceHash: null,
realmSlug: realmSlug,
),
);
}
@override
AutoDisposeFutureProviderElement<List<SnChatRoom>> createElement() {
return _RealmChatRoomsProviderElement(this);
}
@override
bool operator ==(Object other) {
return other is RealmChatRoomsProvider && other.realmSlug == realmSlug;
}
@override
int get hashCode {
var hash = _SystemHash.combine(0, runtimeType.hashCode);
hash = _SystemHash.combine(hash, realmSlug.hashCode);
return _SystemHash.finish(hash);
}
}
@Deprecated('Will be removed in 3.0. Use Ref instead')
// ignore: unused_element
mixin RealmChatRoomsRef on AutoDisposeFutureProviderRef<List<SnChatRoom>> {
/// The parameter `realmSlug` of this provider.
String get realmSlug;
}
class _RealmChatRoomsProviderElement
extends AutoDisposeFutureProviderElement<List<SnChatRoom>>
with RealmChatRoomsRef {
_RealmChatRoomsProviderElement(super.provider);
@override
String get realmSlug => (origin as RealmChatRoomsProvider).realmSlug;
}
String _$realmMemberListNotifierHash() =>
r'b2e3eefc62a597f45df9470b2058fdda62f8853f';

View File

@ -46,6 +46,10 @@ class RealmListScreen extends HookConsumerWidget {
appBar: AppBar(
title: const Text('realms').tr(),
actions: [
IconButton(
icon: const Icon(Symbols.travel_explore),
onPressed: () => context.push('/discovery/realms'),
),
IconButton(
icon: Badge(
label: Text(
@ -66,7 +70,7 @@ class RealmListScreen extends HookConsumerWidget {
showModalBottomSheet(
context: context,
isScrollControlled: true,
builder: (_) => _RealmInviteSheet(),
builder: (_) => const _RealmInviteSheet(),
);
},
),
@ -74,7 +78,7 @@ class RealmListScreen extends HookConsumerWidget {
],
),
floatingActionButton: FloatingActionButton(
heroTag: Key("realms-page-fab"),
heroTag: const Key("realms-page-fab"),
child: const Icon(Symbols.add),
onPressed: () {
context.push('/realms/new').then((value) {
@ -106,7 +110,7 @@ class RealmListScreen extends HookConsumerWidget {
onTap: () {
context.push('/realms/${value[item].slug}');
},
contentPadding: EdgeInsets.only(
contentPadding: const EdgeInsets.only(
left: 16,
right: 14,
top: 8,
@ -158,6 +162,8 @@ class EditRealmScreen extends HookConsumerWidget {
final picture = useState<SnCloudFile?>(null);
final background = useState<SnCloudFile?>(null);
final isPublic = useState(true);
final isCommunity = useState(false);
final slugController = useTextEditingController();
final nameController = useTextEditingController();
@ -174,6 +180,8 @@ class EditRealmScreen extends HookConsumerWidget {
slugController.text = realm.value!.slug;
nameController.text = realm.value!.name;
descriptionController.text = realm.value!.description;
isPublic.value = realm.value!.isPublic;
isCommunity.value = realm.value!.isCommunity;
}
return null;
}, [realm]);
@ -194,9 +202,9 @@ class EditRealmScreen extends HookConsumerWidget {
image: result,
allowedAspectRatios: [
if (position == 'background')
CropAspectRatio(height: 7, width: 16)
const CropAspectRatio(height: 7, width: 16)
else
CropAspectRatio(height: 1, width: 1),
const CropAspectRatio(height: 1, width: 1),
],
);
if (result == null) {
@ -252,6 +260,8 @@ class EditRealmScreen extends HookConsumerWidget {
'description': descriptionController.text,
'background_id': background.value?.id,
'picture_id': picture.value?.id,
'is_public': isPublic.value,
'is_community': isCommunity.value,
},
options: Options(method: slug == null ? 'POST' : 'PATCH'),
);
@ -284,9 +294,9 @@ class EditRealmScreen extends HookConsumerWidget {
child:
background.value != null
? CloudFileWidget(
item: background.value!,
fit: BoxFit.cover,
)
item: background.value!,
fit: BoxFit.cover,
)
: const SizedBox.shrink(),
),
onTap: () {
@ -314,7 +324,6 @@ class EditRealmScreen extends HookConsumerWidget {
key: formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
spacing: 16,
children: [
TextFormField(
controller: slugController,
@ -325,12 +334,14 @@ class EditRealmScreen extends HookConsumerWidget {
onTapOutside:
(_) => FocusManager.instance.primaryFocus?.unfocus(),
),
const SizedBox(height: 16),
TextFormField(
controller: nameController,
decoration: InputDecoration(labelText: 'name'.tr()),
onTapOutside:
(_) => FocusManager.instance.primaryFocus?.unfocus(),
),
const SizedBox(height: 16),
TextFormField(
controller: descriptionController,
decoration: InputDecoration(labelText: 'description'.tr()),
@ -339,6 +350,20 @@ class EditRealmScreen extends HookConsumerWidget {
onTapOutside:
(_) => FocusManager.instance.primaryFocus?.unfocus(),
),
const SizedBox(height: 16),
CheckboxListTile(
title: const Text('isPublic').tr(),
subtitle: const Text('isPublicHint').tr(),
value: isPublic.value,
onChanged: (value) => isPublic.value = value ?? false,
),
CheckboxListTile(
title: const Text('isCommunity').tr(),
subtitle: const Text('isCommunityHint').tr(),
value: isCommunity.value,
onChanged: (value) => isCommunity.value = value ?? false,
),
const SizedBox(height: 16),
Align(
alignment: Alignment.centerRight,
child: TextButton.icon(
@ -410,47 +435,47 @@ class _RealmInviteSheet extends HookConsumerWidget {
(items) =>
items.isEmpty
? Center(
child:
Text(
'invitesEmpty',
textAlign: TextAlign.center,
).tr(),
)
child:
Text(
'invitesEmpty',
textAlign: TextAlign.center,
).tr(),
)
: ListView.builder(
shrinkWrap: true,
itemCount: items.length,
itemBuilder: (context, index) {
final invite = items[index];
return ListTile(
leading: ProfilePictureWidget(
fileId: invite.realm!.picture?.id,
fallbackIcon: Symbols.group,
),
title: Text(invite.realm!.name),
subtitle:
Text(
invite.role >= 100
? 'permissionOwner'
: invite.role >= 50
? 'permissionModerator'
: 'permissionMember',
).tr(),
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
IconButton(
icon: const Icon(Symbols.check),
onPressed: () => acceptInvite(invite),
),
IconButton(
icon: const Icon(Symbols.close),
onPressed: () => declineInvite(invite),
),
],
),
);
},
),
shrinkWrap: true,
itemCount: items.length,
itemBuilder: (context, index) {
final invite = items[index];
return ListTile(
leading: ProfilePictureWidget(
fileId: invite.realm!.picture?.id,
fallbackIcon: Symbols.group,
),
title: Text(invite.realm!.name),
subtitle:
Text(
invite.role >= 100
? 'permissionOwner'
: invite.role >= 50
? 'permissionModerator'
: 'permissionMember',
).tr(),
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
IconButton(
icon: const Icon(Symbols.check),
onPressed: () => acceptInvite(invite),
),
IconButton(
icon: const Icon(Symbols.close),
onPressed: () => declineInvite(invite),
),
],
),
);
},
),
loading: () => const Center(child: CircularProgressIndicator()),
error:
(error, _) => ResponseErrorWidget(
@ -460,4 +485,4 @@ class _RealmInviteSheet extends HookConsumerWidget {
),
);
}
}
}

View File

@ -185,7 +185,6 @@ Completer<SnCloudFile?> _processUpload(
onProgress: (double progress, Duration estimate) {
onProgress?.call(progress, estimate);
},
measureUploadSpeed: true,
)
.catchError(completer.completeError);

View File

@ -32,7 +32,9 @@ StreamSubscription<WebSocketPacket> setupNotificationListener(
var uri = notification.meta['action_uri'] as String;
if (uri.startsWith('/')) {
// In-app routes
rootNavigatorKey.currentContext?.push(notification.meta['action_uri']);
rootNavigatorKey.currentContext?.push(
notification.meta['action_uri'],
);
} else {
// External URLs
launchUrlString(uri);
@ -46,8 +48,14 @@ StreamSubscription<WebSocketPacket> setupNotificationListener(
padding: EdgeInsets.only(
left: 16,
right: 16,
// ignore: use_build_context_synchronously
top: MediaQuery.of(context).padding.top + 24,
top:
(!kIsWeb &&
(Platform.isMacOS ||
Platform.isWindows ||
Platform.isLinux))
? 24
// ignore: use_build_context_synchronously
: MediaQuery.of(context).padding.top + 8,
bottom: 16,
),
);

View File

@ -22,11 +22,14 @@ mixin _$Tour {
@pragma('vm:prefer-inline')
$TourCopyWith<Tour> get copyWith => _$TourCopyWithImpl<Tour>(this as Tour, _$identity);
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is Tour&&(identical(other.id, id) || other.id == id)&&(identical(other.isStartup, isStartup) || other.isStartup == isStartup));
}
@override
int get hashCode => Object.hash(runtimeType,id,isStartup);
@ -35,6 +38,7 @@ String toString() {
return 'Tour(id: $id, isStartup: $isStartup)';
}
}
/// @nodoc
@ -45,6 +49,9 @@ $Res call({
String id, bool isStartup
});
}
/// @nodoc
class _$TourCopyWithImpl<$Res>
@ -66,8 +73,10 @@ as bool,
}
/// @nodoc
class _Tour extends Tour {
const _Tour({required this.id, required this.isStartup}): super._();
@ -81,11 +90,14 @@ class _Tour extends Tour {
@pragma('vm:prefer-inline')
_$TourCopyWith<_Tour> get copyWith => __$TourCopyWithImpl<_Tour>(this, _$identity);
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _Tour&&(identical(other.id, id) || other.id == id)&&(identical(other.isStartup, isStartup) || other.isStartup == isStartup));
}
@override
int get hashCode => Object.hash(runtimeType,id,isStartup);
@ -94,6 +106,7 @@ String toString() {
return 'Tour(id: $id, isStartup: $isStartup)';
}
}
/// @nodoc
@ -104,6 +117,9 @@ $Res call({
String id, bool isStartup
});
}
/// @nodoc
class __$TourCopyWithImpl<$Res>
@ -123,6 +139,7 @@ as bool,
));
}
}
// dart format on

View File

@ -4,6 +4,7 @@ import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:island/services/notify.dart';
import 'package:island/services/sharing_intent.dart';
import 'package:island/widgets/tour/tour.dart';
class AppWrapper extends HookConsumerWidget {
final Widget child;
@ -24,6 +25,6 @@ class AppWrapper extends HookConsumerWidget {
};
}, const []);
return child;
return TourTriggerWidget(child: child);
}
}

View File

@ -233,16 +233,27 @@ class MessageItem extends HookConsumerWidget {
if (remoteMessage.meta['embeds'] != null)
...((remoteMessage.meta['embeds'] as List<dynamic>)
.where((embed) => embed['Type'] == 'link')
.map((embed) => SnEmbedLink.fromJson(embed as Map<String, dynamic>))
.map((link) => LayoutBuilder(
builder: (context, constraints) {
return EmbedLinkWidget(
link: link,
maxWidth: math.min(constraints.maxWidth, 480),
margin: const EdgeInsets.symmetric(vertical: 4),
);
},
))
.map(
(embed) => SnEmbedLink.fromJson(
embed as Map<String, dynamic>,
),
)
.map(
(link) => LayoutBuilder(
builder: (context, constraints) {
return EmbedLinkWidget(
link: link,
maxWidth: math.min(
constraints.maxWidth,
480,
),
margin: const EdgeInsets.symmetric(
vertical: 4,
),
);
},
),
)
.toList()),
if (progress != null && progress!.isNotEmpty)
Column(
@ -482,7 +493,11 @@ class _MessageItemContent extends StatelessWidget {
);
case 'text':
default:
return MarkdownTextContent(content: item.content!, isSelectable: true);
return MarkdownTextContent(
content: item.content!,
isSelectable: true,
linesMargin: EdgeInsets.zero,
);
}
}

View File

@ -186,13 +186,7 @@ class CloudFileZoomIn extends HookConsumerWidget {
Future<void> saveToGallery() async {
try {
// Show loading indicator
final scaffold = ScaffoldMessenger.of(context);
scaffold.showSnackBar(
const SnackBar(
content: Text('Saving image to gallery...'),
duration: Duration(seconds: 1),
),
);
showSnackBar('Saving image to gallery...');
// Get the image URL
final client = ref.watch(apiClientProvider);
@ -209,12 +203,7 @@ class CloudFileZoomIn extends HookConsumerWidget {
await Gal.putImage(filePath, album: 'Solar Network');
// Show success message
scaffold.showSnackBar(
const SnackBar(
content: Text('Image saved to gallery'),
duration: Duration(seconds: 2),
),
);
showSnackBar('Image saved to gallery');
} catch (e) {
showErrorAlert(e);
}

View File

@ -4,12 +4,107 @@ import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:gap/gap.dart';
import 'package:island/widgets/content/sheet.dart';
import 'package:material_symbols_icons/symbols.dart';
import 'package:textfield_tags/textfield_tags.dart';
/// A reusable widget for tag input fields with chip display
class ChipTagInputField extends StatelessWidget {
final InputFieldValues inputFieldValues;
final String labelText;
final String hintText;
const ChipTagInputField({
super.key,
required this.inputFieldValues,
required this.labelText,
required this.hintText,
});
@override
Widget build(BuildContext context) {
return TextField(
controller: inputFieldValues.textEditingController,
focusNode: inputFieldValues.focusNode,
decoration: InputDecoration(
label: Text(labelText).tr(),
border: OutlineInputBorder(borderRadius: BorderRadius.circular(12)),
contentPadding: const EdgeInsets.all(16),
hintText: inputFieldValues.tags.isNotEmpty ? '' : hintText.tr(),
errorText: inputFieldValues.error,
prefixIconConstraints: BoxConstraints(
maxWidth: MediaQuery.of(context).size.width * 0.8,
),
prefixIcon:
inputFieldValues.tags.isNotEmpty
? SingleChildScrollView(
controller: inputFieldValues.tagScrollController,
scrollDirection: Axis.vertical,
child: Padding(
padding: const EdgeInsets.only(top: 8, bottom: 8, left: 8),
child: Wrap(
runSpacing: 4.0,
spacing: 4.0,
children:
inputFieldValues.tags.map<Widget>((dynamic tag) {
return Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.all(
Radius.circular(20.0),
),
color: Theme.of(context).colorScheme.primary,
),
margin: const EdgeInsets.only(left: 5),
padding: const EdgeInsets.symmetric(
horizontal: 10.0,
vertical: 5.0,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
InkWell(
child: Text(
'#$tag',
style: TextStyle(
color:
Theme.of(
context,
).colorScheme.onPrimary,
),
),
),
const Gap(4),
InkWell(
child: const Icon(
Icons.cancel,
size: 14.0,
color: Color.fromARGB(255, 233, 233, 233),
),
onTap: () {
inputFieldValues.onTagRemoved(tag);
},
),
],
),
);
}).toList(),
),
),
)
: null,
),
onChanged: inputFieldValues.onTagChanged,
onSubmitted: inputFieldValues.onTagSubmitted,
);
}
}
class ComposeSettingsSheet extends HookWidget {
final TextEditingController titleController;
final TextEditingController descriptionController;
final ValueNotifier<int> visibility;
final VoidCallback? onVisibilityChanged;
final StringTagController tagsController;
final StringTagController categoriesController;
const ComposeSettingsSheet({
super.key,
@ -17,6 +112,8 @@ class ComposeSettingsSheet extends HookWidget {
required this.descriptionController,
required this.visibility,
this.onVisibilityChanged,
required this.tagsController,
required this.categoriesController,
});
@override
@ -117,6 +214,7 @@ class ComposeSettingsSheet extends HookWidget {
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
spacing: 16,
children: [
// Title field
TextField(
@ -133,7 +231,6 @@ class ComposeSettingsSheet extends HookWidget {
onTapOutside:
(_) => FocusManager.instance.primaryFocus?.unfocus(),
),
const Gap(16),
// Description field
TextField(
@ -151,7 +248,45 @@ class ComposeSettingsSheet extends HookWidget {
onTapOutside:
(_) => FocusManager.instance.primaryFocus?.unfocus(),
),
const Gap(16),
// Tags field
TextFieldTags(
textfieldTagsController: tagsController,
textSeparators: const [' ', ','],
letterCase: LetterCase.normal,
validator: (String tag) {
if (tag.isEmpty) {
return 'No, cannot be empty';
}
return null;
},
inputFieldBuilder: (context, inputFieldValues) {
return ChipTagInputField(
inputFieldValues: inputFieldValues,
labelText: 'tags',
hintText: 'tagsHint',
);
},
),
// Categories field
TextFieldTags(
textfieldTagsController: categoriesController,
textSeparators: const [' ', ','],
letterCase: LetterCase.small,
validator: (String tag) {
if (tag.isEmpty) return 'No, cannot be empty';
if (tag.contains(' ')) return 'Tags should be URL-safe';
return null;
},
inputFieldBuilder: (context, inputFieldValues) {
return ChipTagInputField(
inputFieldValues: inputFieldValues,
labelText: 'categories',
hintText: 'categoriesHint',
);
},
),
// Visibility setting
Container(

View File

@ -16,34 +16,42 @@ import 'package:pasteboard/pasteboard.dart';
import 'dart:async';
import 'dart:developer';
import 'package:textfield_tags/textfield_tags.dart';
class ComposeState {
final ValueNotifier<List<UniversalFile>> attachments;
final TextEditingController titleController;
final TextEditingController descriptionController;
final TextEditingController contentController;
final ValueNotifier<int> visibility;
final ValueNotifier<bool> submitting;
final ValueNotifier<List<UniversalFile>> attachments;
final ValueNotifier<Map<int, double>> attachmentProgress;
final ValueNotifier<SnPublisher?> currentPublisher;
final ValueNotifier<bool> submitting;
StringTagController tagsController;
StringTagController categoriesController;
final String draftId;
int postType;
Timer? _autoSaveTimer;
ComposeState({
required this.attachments,
required this.titleController,
required this.descriptionController,
required this.contentController,
required this.visibility,
required this.submitting,
required this.attachments,
required this.attachmentProgress,
required this.currentPublisher,
required this.submitting,
required this.tagsController,
required this.categoriesController,
required this.draftId,
this.postType = 0,
});
void startAutoSave(WidgetRef ref, {int postType = 0}) {
void startAutoSave(WidgetRef ref) {
_autoSaveTimer?.cancel();
_autoSaveTimer = Timer.periodic(const Duration(seconds: 3), (_) {
ComposeLogic.saveDraftWithoutUpload(ref, this, postType: postType);
ComposeLogic.saveDraftWithoutUpload(ref, this);
});
}
@ -59,9 +67,15 @@ class ComposeLogic {
SnPost? forwardedPost,
SnPost? repliedPost,
String? draftId,
int postType = 0,
}) {
final id = draftId ?? DateTime.now().millisecondsSinceEpoch.toString();
final tagsController = StringTagController();
final categoriesController = StringTagController();
originalPost?.tags.forEach((x) => tagsController.addTag(x.slug));
originalPost?.categories.forEach(
(x) => categoriesController.addTag(x.slug),
);
return ComposeState(
attachments: ValueNotifier<List<UniversalFile>>(
originalPost?.attachments
@ -86,17 +100,32 @@ class ComposeLogic {
contentController: TextEditingController(
text:
originalPost?.content ??
(forwardedPost != null ? '> ${forwardedPost.content}\n\n' : null),
(forwardedPost != null
? '''> ${forwardedPost.content}
'''
: null),
),
visibility: ValueNotifier<int>(originalPost?.visibility ?? 0),
submitting: ValueNotifier<bool>(false),
attachmentProgress: ValueNotifier<Map<int, double>>({}),
currentPublisher: ValueNotifier<SnPublisher?>(null),
tagsController: tagsController,
categoriesController: categoriesController,
draftId: id,
postType: postType,
);
}
static ComposeState createStateFromDraft(SnPost draft) {
static ComposeState createStateFromDraft(SnPost draft, {int postType = 0}) {
final tagsController = StringTagController();
final categoriesController = StringTagController();
for (var x in draft.tags) {
tagsController.addTag(x.slug);
}
for (var x in draft.categories) {
categoriesController.addTag(x.slug);
}
return ComposeState(
attachments: ValueNotifier<List<UniversalFile>>(
draft.attachments.map((e) => UniversalFile.fromAttachment(e)).toList(),
@ -108,15 +137,14 @@ class ComposeLogic {
submitting: ValueNotifier<bool>(false),
attachmentProgress: ValueNotifier<Map<int, double>>({}),
currentPublisher: ValueNotifier<SnPublisher?>(null),
tagsController: tagsController,
categoriesController: categoriesController,
draftId: draft.id,
postType: postType,
);
}
static Future<void> saveDraft(
WidgetRef ref,
ComposeState state, {
int postType = 0,
}) async {
static Future<void> saveDraft(WidgetRef ref, ComposeState state) async {
final hasContent =
state.titleController.text.trim().isNotEmpty ||
state.descriptionController.text.trim().isNotEmpty ||
@ -148,7 +176,7 @@ class ComposeLogic {
baseUrl: baseUrl,
filename:
attachment.data.name ??
(postType == 1 ? 'Article media' : 'Post media'),
(state.postType == 1 ? 'Article media' : 'Post media'),
mimetype:
attachment.data.mimeType ??
ComposeLogic.getMimeTypeFromFileType(attachment.type),
@ -175,7 +203,7 @@ class ComposeLogic {
publishedAt: DateTime.now(),
visibility: state.visibility.value,
content: state.contentController.text,
type: postType,
type: state.postType,
meta: null,
viewsUnique: 0,
viewsTotal: 0,
@ -225,9 +253,8 @@ class ComposeLogic {
static Future<void> saveDraftWithoutUpload(
WidgetRef ref,
ComposeState state, {
int postType = 0,
}) async {
ComposeState state,
) async {
final hasContent =
state.titleController.text.trim().isNotEmpty ||
state.descriptionController.text.trim().isNotEmpty ||
@ -252,7 +279,7 @@ class ComposeLogic {
publishedAt: DateTime.now(),
visibility: state.visibility.value,
content: state.contentController.text,
type: postType,
type: state.postType,
meta: null,
viewsUnique: 0,
viewsTotal: 0,
@ -306,54 +333,7 @@ class ComposeLogic {
BuildContext context,
) async {
try {
final draft = SnPost(
id: state.draftId,
title: state.titleController.text,
description: state.descriptionController.text,
language: null,
editedAt: null,
publishedAt: DateTime.now(),
visibility: state.visibility.value,
content: state.contentController.text,
type: 0,
meta: null,
viewsUnique: 0,
viewsTotal: 0,
upvotes: 0,
downvotes: 0,
repliesCount: 0,
threadedPostId: null,
threadedPost: null,
repliedPostId: null,
repliedPost: null,
forwardedPostId: null,
forwardedPost: null,
attachments: [], // TODO: Handle attachments
publisher: SnPublisher(
id: '',
type: 0,
name: '',
nick: '',
picture: null,
background: null,
account: null,
accountId: null,
createdAt: DateTime.now(),
updatedAt: DateTime.now(),
deletedAt: null,
realmId: null,
verification: null,
),
reactions: [],
tags: [],
categories: [],
collections: [],
createdAt: DateTime.now(),
updatedAt: DateTime.now(),
deletedAt: null,
);
await ref.read(composeStorageNotifierProvider.notifier).saveDraft(draft);
await saveDraft(ref, state);
if (context.mounted) {
showSnackBar('draftSaved'.tr());
@ -508,7 +488,6 @@ class ComposeLogic {
SnPost? originalPost,
SnPost? repliedPost,
SnPost? forwardedPost,
int? postType, // 0 for regular post, 1 for article
}) async {
if (state.submitting.value) return;
@ -554,9 +533,11 @@ class ComposeLogic {
.where((e) => e.isOnCloud)
.map((e) => e.data.id)
.toList(),
if (postType != null) 'type': postType,
'type': state.postType,
if (repliedPost != null) 'replied_post_id': repliedPost.id,
if (forwardedPost != null) 'forwarded_post_id': forwardedPost.id,
'tags': state.tagsController.getTags,
'categories': state.categoriesController.getTags,
};
// Send request
@ -570,7 +551,7 @@ class ComposeLogic {
);
// Delete draft after successful submission
if (postType == 1) {
if (state.postType == 1) {
// Delete article draft
await ref
.read(composeStorageNotifierProvider.notifier)
@ -613,7 +594,6 @@ class ComposeLogic {
SnPost? originalPost,
SnPost? repliedPost,
SnPost? forwardedPost,
int? postType,
}) {
if (event is! RawKeyDownEvent) return;
@ -634,7 +614,6 @@ class ComposeLogic {
originalPost: originalPost,
repliedPost: repliedPost,
forwardedPost: forwardedPost,
postType: postType,
);
}
}
@ -649,5 +628,7 @@ class ComposeLogic {
state.submitting.dispose();
state.attachmentProgress.dispose();
state.currentPublisher.dispose();
state.tagsController.dispose();
state.categoriesController.dispose();
}
}

View File

@ -4,6 +4,7 @@ import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:gap/gap.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:island/services/compose_storage_db.dart';
import 'package:island/widgets/content/sheet.dart';
import 'package:material_symbols_icons/symbols.dart';
class DraftManagerSheet extends HookConsumerWidget {
@ -43,9 +44,9 @@ class DraftManagerSheet extends HookConsumerWidget {
],
);
return Scaffold(
appBar: AppBar(title: Text('drafts'.tr())),
body:
return SheetScaffold(
titleText: 'drafts'.tr(),
child:
isLoading.value
? const Center(child: CircularProgressIndicator())
: Column(

View File

@ -71,7 +71,7 @@ class PostItem extends HookConsumerWidget {
title: 'edit'.tr(),
image: MenuImage.icon(Symbols.edit),
callback: () {
context.push('/posts/item.id/edit').then((value) {
context.push('/posts/${item.id}/edit').then((value) {
if (value != null) {
onRefresh?.call();
}
@ -242,6 +242,57 @@ class PostItem extends HookConsumerWidget {
? EdgeInsets.only(bottom: 8)
: null,
),
// Render tags and categories if they exist
if (item.tags.isNotEmpty ||
item.categories.isNotEmpty)
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (item.tags.isNotEmpty)
Wrap(
children: [
for (final tag in item.tags)
InkWell(
child: Row(
spacing: 4,
children: [
const Icon(
Symbols.label,
size: 13,
),
Text(
tag.name ?? '#${tag.slug}',
).fontSize(13),
],
),
onTap: () {},
),
],
),
if (item.categories.isNotEmpty)
Wrap(
children: [
for (final category in item.categories)
InkWell(
child: Row(
spacing: 4,
children: [
const Icon(
Symbols.category,
size: 13,
),
Text(
category.name ??
'#${category.slug}',
).fontSize(13),
],
),
onTap: () {},
),
],
),
],
),
// Show truncation hint if post is truncated
if (item.isTruncated && !isFullPost)
_PostTruncateHint().padding(
@ -283,7 +334,7 @@ class PostItem extends HookConsumerWidget {
),
onTap: () {
if (isOpenable) {
context.push('/posts/item.id');
context.push('/posts/${item.id}');
}
},
),

View File

@ -45,7 +45,7 @@ class PostItemCreator extends HookConsumerWidget {
title: 'edit'.tr(),
image: MenuImage.icon(Symbols.edit),
callback: () {
context.push('/posts/item.id/edit').then((value) {
context.push('/posts/${item.id}/edit').then((value) {
if (value != null) {
onRefresh?.call();
}
@ -80,7 +80,7 @@ class PostItemCreator extends HookConsumerWidget {
image: MenuImage.icon(Symbols.link),
callback: () {
// Copy post link to clipboard
context.push('/posts/item.id');
context.push('/posts/${item.id}');
},
),
],

View File

@ -0,0 +1,100 @@
import 'package:flutter/material.dart';
import 'package:gap/gap.dart';
import 'package:go_router/go_router.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:island/models/post.dart';
import 'package:island/widgets/content/cloud_files.dart';
class PublisherCard extends ConsumerWidget {
final SnPublisher publisher;
final double? maxWidth;
const PublisherCard({super.key, required this.publisher, this.maxWidth});
@override
Widget build(BuildContext context, WidgetRef ref) {
Widget imageWidget;
if (publisher.picture != null) {
imageWidget = CloudImageWidget(
file: publisher.background,
fit: BoxFit.cover,
);
} else {
imageWidget = ColoredBox(
color: Theme.of(context).colorScheme.secondaryContainer,
);
}
Widget card = Card(
clipBehavior: Clip.antiAlias,
child: InkWell(
onTap: () {
context.push('/publishers/${publisher.name}');
},
child: AspectRatio(
aspectRatio: 16 / 7,
child: Stack(
fit: StackFit.expand,
children: [
imageWidget,
Positioned(
bottom: 0,
left: 0,
right: 0,
child: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.bottomCenter,
end: Alignment.topCenter,
colors: [
Colors.black.withOpacity(0.7),
Colors.transparent,
],
),
),
padding: const EdgeInsets.all(8),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
decoration: BoxDecoration(
shape: BoxShape.circle,
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.5),
blurRadius: 4,
offset: const Offset(0, 2),
),
],
),
child: ProfilePictureWidget(
file: publisher.picture,
radius: 12,
),
),
const Gap(2),
Text(
publisher.nick,
style: Theme.of(context).textTheme.titleSmall?.copyWith(
color: Colors.white,
fontWeight: FontWeight.bold,
),
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
],
),
),
),
],
),
),
),
);
return ConstrainedBox(
constraints: BoxConstraints(maxWidth: maxWidth ?? double.infinity),
child: card,
);
}
}

View File

@ -0,0 +1,103 @@
import 'package:flutter/material.dart';
import 'package:gap/gap.dart';
import 'package:go_router/go_router.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:island/models/realm.dart';
import 'package:island/widgets/content/cloud_files.dart';
import 'package:material_symbols_icons/symbols.dart';
class RealmCard extends ConsumerWidget {
final SnRealm realm;
final double? maxWidth;
const RealmCard({super.key, required this.realm, this.maxWidth});
@override
Widget build(BuildContext context, WidgetRef ref) {
Widget imageWidget;
if (realm.picture != null) {
imageWidget =
imageWidget = CloudImageWidget(
file: realm.background,
fit: BoxFit.cover,
);
} else {
imageWidget = ColoredBox(
color: Theme.of(context).colorScheme.secondaryContainer,
);
}
Widget card = Card(
clipBehavior: Clip.antiAlias,
child: InkWell(
onTap: () {
context.push('/realms/${realm.slug}');
},
child: AspectRatio(
aspectRatio: 16 / 7,
child: Stack(
fit: StackFit.expand,
children: [
imageWidget,
Positioned(
bottom: 0,
left: 0,
right: 0,
child: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.bottomCenter,
end: Alignment.topCenter,
colors: [
Colors.black.withOpacity(0.7),
Colors.transparent,
],
),
),
padding: const EdgeInsets.all(8),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
decoration: BoxDecoration(
shape: BoxShape.circle,
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.5),
blurRadius: 4,
offset: const Offset(0, 2),
),
],
),
child: ProfilePictureWidget(
file: realm.picture,
fallbackIcon: Symbols.group,
radius: 12,
),
),
const Gap(2),
Text(
realm.name,
style: Theme.of(context).textTheme.titleSmall?.copyWith(
color: Colors.white,
fontWeight: FontWeight.bold,
),
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
],
),
),
),
],
),
),
),
);
return ConstrainedBox(
constraints: BoxConstraints(maxWidth: maxWidth ?? double.infinity),
child: card,
);
}
}

View File

@ -0,0 +1,88 @@
import 'package:flutter/material.dart';
import 'package:gap/gap.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:island/models/realm.dart';
import 'package:island/pods/network.dart';
import 'package:island/widgets/realm/realm_card.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:riverpod_paging_utils/riverpod_paging_utils.dart';
part 'realm_list.g.dart';
@riverpod
class RealmListNotifier extends _$RealmListNotifier
with CursorPagingNotifierMixin<SnRealm> {
static const int _pageSize = 20;
@override
Future<CursorPagingData<SnRealm>> build(String? query) {
return fetch(cursor: null, query: query);
}
@override
Future<CursorPagingData<SnRealm>> fetch({
required String? cursor,
String? query,
}) async {
final client = ref.read(apiClientProvider);
final offset = cursor == null ? 0 : int.parse(cursor);
final queryParams = {
'offset': offset,
'take': _pageSize,
if (query != null && query.isNotEmpty) 'query': query,
};
final response = await client.get(
'/discovery/realms',
queryParameters: queryParams,
);
final total = int.parse(response.headers.value('X-Total') ?? '0');
final List<dynamic> data = response.data;
final realms = data.map((json) => SnRealm.fromJson(json)).toList();
final hasMore = offset + realms.length < total;
final nextCursor = hasMore ? (offset + realms.length).toString() : null;
return CursorPagingData(
items: realms,
hasMore: hasMore,
nextCursor: nextCursor,
);
}
}
class SliverRealmList extends HookConsumerWidget {
const SliverRealmList({super.key, this.query});
final String? query;
@override
Widget build(BuildContext context, WidgetRef ref) {
return PagingHelperSliverView(
provider: realmListNotifierProvider(query),
futureRefreshable: realmListNotifierProvider(query).future,
notifierRefreshable: realmListNotifierProvider(query).notifier,
contentBuilder:
(data, widgetCount, endItemView) => SliverList.separated(
itemCount: widgetCount,
itemBuilder: (context, index) {
if (index == widgetCount - 1) {
return endItemView;
}
final realm = data.items[index];
return Padding(
padding: const EdgeInsets.symmetric(
horizontal: 16,
vertical: 8,
),
child: RealmCard(realm: realm),
);
},
separatorBuilder: (_, _) => const Gap(8),
),
);
}
}

View File

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

View File

@ -0,0 +1,20 @@
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:island/models/realm.dart';
import 'package:island/widgets/content/cloud_files.dart';
class RealmTile extends HookConsumerWidget {
final SnRealm realm;
const RealmTile({super.key, required this.realm});
@override
Widget build(BuildContext context, WidgetRef ref) {
return ListTile(
leading: ProfilePictureWidget(file: realm.picture),
title: Text(realm.name),
subtitle: Text(realm.description),
onTap: () => context.push('/realms/${realm.slug}'),
);
}
}

View File

@ -13,6 +13,7 @@ import 'package:island/pods/network.dart';
import 'package:island/pods/config.dart';
import 'package:island/pods/userinfo.dart';
import 'package:island/services/file.dart';
import 'package:mime/mime.dart';
import 'dart:io';
import 'package:path/path.dart' as path;
@ -149,9 +150,9 @@ class _ShareSheetState extends ConsumerState<ShareSheet> {
case ShareContentType.file:
if (widget.content.files != null) {
// Convert XFiles to UniversalFiles
for (final xFile in widget.content.files!) {
final file = File(xFile.path);
final mimeType = xFile.mimeType;
for (final file in widget.content.files!) {
var mimeType = file.mimeType;
mimeType ??= lookupMimeType(file.path);
UniversalFileType fileType;
if (mimeType?.startsWith('image/') == true) {

View File

@ -49,6 +49,8 @@ PODS:
- OrderedSet (~> 6.0.3)
- flutter_platform_alert (0.0.1):
- FlutterMacOS
- flutter_secure_storage_macos (6.1.3):
- FlutterMacOS
- flutter_timezone (0.1.0):
- FlutterMacOS
- flutter_udid (0.0.1):
@ -171,6 +173,7 @@ DEPENDENCIES:
- firebase_messaging (from `Flutter/ephemeral/.symlinks/plugins/firebase_messaging/macos`)
- flutter_inappwebview_macos (from `Flutter/ephemeral/.symlinks/plugins/flutter_inappwebview_macos/macos`)
- flutter_platform_alert (from `Flutter/ephemeral/.symlinks/plugins/flutter_platform_alert/macos`)
- flutter_secure_storage_macos (from `Flutter/ephemeral/.symlinks/plugins/flutter_secure_storage_macos/macos`)
- flutter_timezone (from `Flutter/ephemeral/.symlinks/plugins/flutter_timezone/macos`)
- flutter_udid (from `Flutter/ephemeral/.symlinks/plugins/flutter_udid/macos`)
- flutter_webrtc (from `Flutter/ephemeral/.symlinks/plugins/flutter_webrtc/macos`)
@ -232,6 +235,8 @@ EXTERNAL SOURCES:
:path: Flutter/ephemeral/.symlinks/plugins/flutter_inappwebview_macos/macos
flutter_platform_alert:
:path: Flutter/ephemeral/.symlinks/plugins/flutter_platform_alert/macos
flutter_secure_storage_macos:
:path: Flutter/ephemeral/.symlinks/plugins/flutter_secure_storage_macos/macos
flutter_timezone:
:path: Flutter/ephemeral/.symlinks/plugins/flutter_timezone/macos
flutter_udid:
@ -295,6 +300,7 @@ SPEC CHECKSUMS:
FirebaseMessaging: 195bbdb73e6ca1dbc76cd46e73f3552c084ef6e4
flutter_inappwebview_macos: c2d68649f9f8f1831bfcd98d73fd6256366d9d1d
flutter_platform_alert: 8fa7a7c21f95b26d08b4a3891936ca27e375f284
flutter_secure_storage_macos: 7f45e30f838cf2659862a4e4e3ee1c347c2b3b54
flutter_timezone: d59eea86178cbd7943cd2431cc2eaa9850f935d8
flutter_udid: d26e455e8c06174e6aff476e147defc6cae38495
flutter_webrtc: a7eeb54859e672228c28f4b48b1fb61561976ea3

View File

@ -1041,10 +1041,10 @@ packages:
dependency: "direct main"
description:
name: go_router
sha256: f02fd7d2a4dc512fec615529824fdd217fecb3a3d3de68360293a551f21634b3
sha256: ac294be30ba841830cfa146e5a3b22bb09f8dc5a0fdd9ca9332b04b0bde99ebf
url: "https://pub.dev"
source: hosted
version: "14.8.1"
version: "15.2.4"
google_fonts:
dependency: "direct main"
description:
@ -1470,7 +1470,7 @@ packages:
source: hosted
version: "1.16.0"
mime:
dependency: transitive
dependency: "direct main"
description:
name: mime
sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6"
@ -1785,10 +1785,10 @@ packages:
dependency: transitive
description:
name: record_linux
sha256: "29e7735b05c1944bb6c9b72a36c08d4a1b24117e712d6a9523c003bde12bf484"
sha256: "0626678a092c75ce6af1e32fe7fd1dea709b92d308bc8e3b6d6348e2430beb95"
url: "https://pub.dev"
source: hosted
version: "1.1.0"
version: "1.1.1"
record_macos:
dependency: transitive
description:
@ -2106,14 +2106,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.10.1"
speed_test_dart:
dependency: transitive
description:
name: speed_test_dart
sha256: "4131faa68d5c9259766626450a10e552bc11ff6e651bb6377cc56476443e1cfa"
url: "https://pub.dev"
source: hosted
version: "1.0.5+0"
sprintf:
dependency: transitive
description:
@ -2258,22 +2250,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.4.1"
sync:
dependency: transitive
description:
name: sync
sha256: f2ebb89eac969abb02b498562a35c4da63d6843396c4fe81948cd06a76845fce
url: "https://pub.dev"
source: hosted
version: "0.3.0"
synchronized:
dependency: transitive
description:
name: synchronized
sha256: "0669c70faae6270521ee4f05bffd2919892d42d1276e6c495be80174b6bc0ef6"
sha256: c254ade258ec8282947a0acbbc90b9575b4f19673533ee46f2f6e9b3aeefd7c0
url: "https://pub.dev"
source: hosted
version: "3.3.1"
version: "3.4.0"
table_calendar:
dependency: "direct main"
description:
@ -2314,6 +2298,15 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.6.8"
textfield_tags:
dependency: "direct main"
description:
path: "."
ref: "fixes/allow-controller-re-registration"
resolved-ref: "7574e79649e34df1c3cc0c49b2f0cc2b92de6a7b"
url: "https://github.com/lionelmennig/textfield_tags.git"
source: git
version: "3.0.1"
timezone:
dependency: "direct main"
description:
@ -2351,7 +2344,7 @@ packages:
description:
path: "."
ref: HEAD
resolved-ref: "55e0eecfb7a7af67be4a7b6e8e73d128d4460436"
resolved-ref: e33aa4f363104d083e681103b102037e212e32ab
url: "https://github.com/LittleSheep2Code/tus_client.git"
source: git
version: "2.5.0"

View File

@ -16,7 +16,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
# In Windows, build-name is used as the major, minor, and patch parts
# of the product and file versions while build-number is used as the build suffix.
version: 3.0.0+107
version: 3.0.0+109
environment:
sdk: ^3.7.2
@ -37,7 +37,7 @@ dependencies:
flutter_hooks: ^0.21.2
hooks_riverpod: ^2.6.1
bitsdojo_window: ^0.1.6
go_router: ^14.6.2
go_router: ^15.2.4
styled_widget: ^0.4.1
shared_preferences: ^2.5.3
flutter_riverpod: ^2.6.1
@ -122,6 +122,11 @@ dependencies:
share_plus: ^11.0.0
receive_sharing_intent: ^1.8.1
top_snackbar_flutter: ^3.3.0
textfield_tags:
git:
url: https://github.com/lionelmennig/textfield_tags.git
ref: fixes/allow-controller-re-registration
mime: ^2.0.0
dev_dependencies:
flutter_test: