Compare commits
No commits in common. "5939a1dc5b9700331f676a6950b6f6fdfbc6257a" and "047cb9dc0de0dc6b235c41d2656dc39a52245796" have entirely different histories.
5939a1dc5b
...
047cb9dc0d
@ -89,14 +89,31 @@
|
|||||||
"authFactorInAppNotifyDescription": "A one-time code sent via in-app notification.",
|
"authFactorInAppNotifyDescription": "A one-time code sent via in-app notification.",
|
||||||
"authFactorPin": "Pin Code",
|
"authFactorPin": "Pin Code",
|
||||||
"authFactorPinDescription": "It consists of 6 digits. It cannot be used to log in. When performing some dangerous operations, the system will ask you to enter this PIN for confirmation.",
|
"authFactorPinDescription": "It consists of 6 digits. It cannot be used to log in. When performing some dangerous operations, the system will ask you to enter this PIN for confirmation.",
|
||||||
|
"realms": "Realms",
|
||||||
|
"createRealm": "Create a Realm",
|
||||||
|
"createRealmHint": "Meet friends with same interests, build communities, and more.",
|
||||||
|
"editRealm": "Edit Realm",
|
||||||
|
"deleteRealm": "Delete Realm",
|
||||||
|
"deleteRealmHint": "Are you sure to delete this realm? This will also deleted all the channels, publishers, and posts under this realm.",
|
||||||
"explore": "Explore",
|
"explore": "Explore",
|
||||||
"exploreFilterSubscriptions": "Subscriptions",
|
"exploreFilterSubscriptions": "Subscriptions",
|
||||||
"exploreFilterFriends": "Friends",
|
"exploreFilterFriends": "Friends",
|
||||||
"discover": "Discover",
|
"discoverCommunities": "Discover Communities",
|
||||||
"account": "Account",
|
"account": "Account",
|
||||||
"name": "Name",
|
"name": "Name",
|
||||||
"slug": "Slug",
|
"slug": "Slug",
|
||||||
"slugHint": "The slug will be used in the URL to access this resource, it should be unique and URL safe.",
|
"slugHint": "The slug will be used in the URL to access this resource, it should be unique and URL safe.",
|
||||||
|
"createChatRoom": "Create a Room",
|
||||||
|
"editChatRoom": "Edit Room",
|
||||||
|
"deleteChatRoom": "Delete Room",
|
||||||
|
"deleteChatRoomHint": "Are you sure to delete this room? This action cannot be undone.",
|
||||||
|
"chat": "Chat",
|
||||||
|
"chatTabAll": "All",
|
||||||
|
"chatTabDirect": "Direct Messages",
|
||||||
|
"chatTabGroup": "Group Chats",
|
||||||
|
"chatMessageHint": "Message in {}",
|
||||||
|
"chatDirectMessageHint": "Message to {}",
|
||||||
|
"directMessage": "Direct Message",
|
||||||
"loading": "Loading...",
|
"loading": "Loading...",
|
||||||
"descriptionNone": "No description yet.",
|
"descriptionNone": "No description yet.",
|
||||||
"invites": "Invites",
|
"invites": "Invites",
|
||||||
@ -231,6 +248,7 @@
|
|||||||
"uploadingProgress": "Uploading {} of {}",
|
"uploadingProgress": "Uploading {} of {}",
|
||||||
"uploadAll": "Upload All",
|
"uploadAll": "Upload All",
|
||||||
"stickerCopyPlaceholder": "Copy Placeholder",
|
"stickerCopyPlaceholder": "Copy Placeholder",
|
||||||
|
"realmSelection": "Select a Realm",
|
||||||
"individual": "Individual",
|
"individual": "Individual",
|
||||||
"firstPostBadgeName": "First Post",
|
"firstPostBadgeName": "First Post",
|
||||||
"firstPostBadgeDescription": "Created your first post on Solar Network",
|
"firstPostBadgeDescription": "Created your first post on Solar Network",
|
||||||
@ -286,6 +304,10 @@
|
|||||||
"levelingProgressExperience": "{} EXP",
|
"levelingProgressExperience": "{} EXP",
|
||||||
"levelingProgressLevel": "Level {}",
|
"levelingProgressLevel": "Level {}",
|
||||||
"fileUploadingProgress": "Uploading file #{}: {}%",
|
"fileUploadingProgress": "Uploading file #{}: {}%",
|
||||||
|
"removeChatMember": "Remove Chat Room Member",
|
||||||
|
"removeChatMemberHint": "Are you sure to remove this member from the room?",
|
||||||
|
"removeRealmMember": "Remove Realm Member",
|
||||||
|
"removeRealmMemberHint": "Are you sure to remove this member from the realm?",
|
||||||
"memberRole": "Member Role",
|
"memberRole": "Member Role",
|
||||||
"memberRoleHint": "Greater number has higher permission.",
|
"memberRoleHint": "Greater number has higher permission.",
|
||||||
"memberRoleEdit": "Edit role for @{}",
|
"memberRoleEdit": "Edit role for @{}",
|
||||||
@ -293,6 +315,10 @@
|
|||||||
"openLinkConfirmDescription": "You're going to leave the Solar Network and open the link ({}) in your browser. It is not related to Solar Network. Beware of phishing and scams.",
|
"openLinkConfirmDescription": "You're going to leave the Solar Network and open the link ({}) in your browser. It is not related to Solar Network. Beware of phishing and scams.",
|
||||||
"brokenLink": "Unable open link {}... It might be broken or missing uri parts...",
|
"brokenLink": "Unable open link {}... It might be broken or missing uri parts...",
|
||||||
"copyToClipboard": "Copy to clipboard",
|
"copyToClipboard": "Copy to clipboard",
|
||||||
|
"leaveChatRoom": "Leave Chat Room",
|
||||||
|
"leaveChatRoomHint": "Are you sure to leave this chat room?",
|
||||||
|
"leaveRealm": "Leave Realm",
|
||||||
|
"leaveRealmHint": "Are you sure to leave this realm?",
|
||||||
"walletNotFound": "Wallet not found",
|
"walletNotFound": "Wallet not found",
|
||||||
"walletCreateHint": "You don't have a wallet yet. Create one to start using the Solar Network eWallet.",
|
"walletCreateHint": "You don't have a wallet yet. Create one to start using the Solar Network eWallet.",
|
||||||
"walletCreate": "Create a Wallet",
|
"walletCreate": "Create a Wallet",
|
||||||
@ -304,6 +330,12 @@
|
|||||||
"settingsBackgroundImageClear": "Clear Background Image",
|
"settingsBackgroundImageClear": "Clear Background Image",
|
||||||
"settingsBackgroundGenerateColor": "Generate color scheme from Bacground Image",
|
"settingsBackgroundGenerateColor": "Generate color scheme from Bacground Image",
|
||||||
"messageNone": "No content to display",
|
"messageNone": "No content to display",
|
||||||
|
"unreadMessages": {
|
||||||
|
"one": "{} unread message",
|
||||||
|
"other": "{} unread messages"
|
||||||
|
},
|
||||||
|
"chatBreakNone": "None",
|
||||||
|
"settingsRealmCompactView": "Compact Realm View",
|
||||||
"settingsMixedFeed": "Mixed Feed",
|
"settingsMixedFeed": "Mixed Feed",
|
||||||
"settingsAutoTranslate": "Auto Translate",
|
"settingsAutoTranslate": "Auto Translate",
|
||||||
"settingsHideBottomNav": "Hide Bottom Navigation",
|
"settingsHideBottomNav": "Hide Bottom Navigation",
|
||||||
@ -346,6 +378,7 @@
|
|||||||
"postVisibilityUnlisted": "Unlisted",
|
"postVisibilityUnlisted": "Unlisted",
|
||||||
"postVisibilityPrivate": "Private",
|
"postVisibilityPrivate": "Private",
|
||||||
"postTruncated": "Content truncated, tap to view full post",
|
"postTruncated": "Content truncated, tap to view full post",
|
||||||
|
"copyMessage": "Copy Message",
|
||||||
"authFactor": "Authentication Factor",
|
"authFactor": "Authentication Factor",
|
||||||
"authFactorDelete": "Delete the Factor",
|
"authFactorDelete": "Delete the Factor",
|
||||||
"authFactorDeleteHint": "Are you sure you want to delete this authentication factor? This action cannot be undone.",
|
"authFactorDeleteHint": "Are you sure you want to delete this authentication factor? This action cannot be undone.",
|
||||||
@ -378,6 +411,10 @@
|
|||||||
"authDeviceLabelHint": "Enter a name for this device",
|
"authDeviceLabelHint": "Enter a name for this device",
|
||||||
"authDeviceSwipeEditHint": "Swipe left to edit label",
|
"authDeviceSwipeEditHint": "Swipe left to edit label",
|
||||||
"authDeviceSwipeLogoutHint": "Swipe right to logout device",
|
"authDeviceSwipeLogoutHint": "Swipe right to logout device",
|
||||||
|
"typingHint": {
|
||||||
|
"one": "{} is typing...",
|
||||||
|
"other": "{} are typing..."
|
||||||
|
},
|
||||||
"settingsAppearance": "Appearance",
|
"settingsAppearance": "Appearance",
|
||||||
"settingsServer": "Server",
|
"settingsServer": "Server",
|
||||||
"settingsBehavior": "Behavior",
|
"settingsBehavior": "Behavior",
|
||||||
@ -439,6 +476,21 @@
|
|||||||
"contactMethodSetPrimary": "Set as Primary",
|
"contactMethodSetPrimary": "Set as Primary",
|
||||||
"contactMethodSetPrimaryHint": "Set this contact method as your primary contact method for account recovery and notifications",
|
"contactMethodSetPrimaryHint": "Set this contact method as your primary contact method for account recovery and notifications",
|
||||||
"contactMethodDeleteHint": "Are you sure to delete this contact method? This action cannot be undone.",
|
"contactMethodDeleteHint": "Are you sure to delete this contact method? This action cannot be undone.",
|
||||||
|
"chatNotifyLevel": "Notify Level",
|
||||||
|
"chatNotifyLevelDescription": "Decide how many notifications you will receive.",
|
||||||
|
"chatNotifyLevelAll": "All",
|
||||||
|
"chatNotifyLevelMention": "Mentions",
|
||||||
|
"chatNotifyLevelNone": "None",
|
||||||
|
"chatNotifyLevelUpdated": "The notify level has been updated to {}.",
|
||||||
|
"chatBreak": "Take a Break",
|
||||||
|
"chatBreakDescription": "Set a time, before that time, your notification level will be metions only, to take a break of the current topic they're talking about.",
|
||||||
|
"chatBreakClear": "Clear the break time",
|
||||||
|
"chatBreakHour": "{} break",
|
||||||
|
"chatBreakDay": "{} day break",
|
||||||
|
"chatBreakSet": "Break set for {}",
|
||||||
|
"chatBreakCleared": "Chat break has been cleared.",
|
||||||
|
"chatBreakCustom": "Custom duration",
|
||||||
|
"chatBreakEnterMinutes": "Enter minutes",
|
||||||
"firstName": "First Name",
|
"firstName": "First Name",
|
||||||
"middleName": "Middle Name",
|
"middleName": "Middle Name",
|
||||||
"lastName": "Last Name",
|
"lastName": "Last Name",
|
||||||
@ -520,17 +572,29 @@
|
|||||||
"quickActions": "Quick Actions",
|
"quickActions": "Quick Actions",
|
||||||
"post": "Post",
|
"post": "Post",
|
||||||
"copy": "Copy",
|
"copy": "Copy",
|
||||||
|
"sendToChat": "Send to Chat",
|
||||||
"failedToShareToPost": "Failed to share to post: {}",
|
"failedToShareToPost": "Failed to share to post: {}",
|
||||||
"shareToChatComingSoon": "Share to chat functionality coming soon",
|
"shareToChatComingSoon": "Share to chat functionality coming soon",
|
||||||
|
"failedToShareToChat": "Failed to share to chat: {}",
|
||||||
|
"shareToSpecificChatComingSoon": "Share to {} coming soon",
|
||||||
|
"directChat": "Direct Chat",
|
||||||
"systemShareComingSoon": "System share functionality coming soon",
|
"systemShareComingSoon": "System share functionality coming soon",
|
||||||
"failedToShareToSystem": "Failed to share to system: {}",
|
"failedToShareToSystem": "Failed to share to system: {}",
|
||||||
"failedToCopy": "Failed to copy: {}",
|
"failedToCopy": "Failed to copy: {}",
|
||||||
|
"noChatRoomsAvailable": "No chat rooms available",
|
||||||
|
"failedToLoadChats": "Failed to load chats",
|
||||||
"contentToShare": "Content to share:",
|
"contentToShare": "Content to share:",
|
||||||
|
"unknownChat": "Unknown Chat",
|
||||||
|
"addAdditionalMessage": "Add additional message...",
|
||||||
"uploadingFiles": "Uploading files...",
|
"uploadingFiles": "Uploading files...",
|
||||||
|
"sharedSuccessfully": "Shared successfully!",
|
||||||
"shareSuccess": "Shared successfully!",
|
"shareSuccess": "Shared successfully!",
|
||||||
|
"shareToSpecificChatSuccess": "Shared to {} successfully!",
|
||||||
"wouldYouLikeToGoToChat": "Would you like to go to the chat?",
|
"wouldYouLikeToGoToChat": "Would you like to go to the chat?",
|
||||||
"no": "No",
|
"no": "No",
|
||||||
"yes": "Yes",
|
"yes": "Yes",
|
||||||
|
"navigateToChat": "Navigate to Chat",
|
||||||
|
"wouldYouLikeToNavigateToChat": "Would you like to navigate to the chat?",
|
||||||
"abuseReport": "Report",
|
"abuseReport": "Report",
|
||||||
"abuseReportTitle": "Report Content",
|
"abuseReportTitle": "Report Content",
|
||||||
"abuseReportDescription": "Help us keep the community safe by reporting inappropriate content or behavior.",
|
"abuseReportDescription": "Help us keep the community safe by reporting inappropriate content or behavior.",
|
||||||
|
@ -29,12 +29,6 @@ import 'package:image_picker_platform_interface/image_picker_platform_interface.
|
|||||||
import 'package:flutter_native_splash/flutter_native_splash.dart';
|
import 'package:flutter_native_splash/flutter_native_splash.dart';
|
||||||
import 'package:url_launcher/url_launcher_string.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 {
|
void main() async {
|
||||||
final widgetsBinding = WidgetsFlutterBinding.ensureInitialized();
|
final widgetsBinding = WidgetsFlutterBinding.ensureInitialized();
|
||||||
if (!kIsWeb && (Platform.isAndroid || Platform.isIOS)) {
|
if (!kIsWeb && (Platform.isAndroid || Platform.isIOS)) {
|
||||||
@ -49,7 +43,6 @@ void main() async {
|
|||||||
await Firebase.initializeApp(
|
await Firebase.initializeApp(
|
||||||
options: DefaultFirebaseOptions.currentPlatform,
|
options: DefaultFirebaseOptions.currentPlatform,
|
||||||
);
|
);
|
||||||
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
|
|
||||||
log("[SplashScreen] Firebase is ready!");
|
log("[SplashScreen] Firebase is ready!");
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
showErrorAlert(err);
|
showErrorAlert(err);
|
||||||
@ -158,30 +151,17 @@ class IslandApp extends HookConsumerWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() {
|
useEffect(() {
|
||||||
// When the app is opened from a terminated state.
|
Future(() async {
|
||||||
FirebaseMessaging.instance.getInitialMessage().then((message) {
|
RemoteMessage? initialMessage =
|
||||||
if (message != null) {
|
await FirebaseMessaging.instance.getInitialMessage();
|
||||||
handleMessage(message);
|
if (initialMessage != null) {
|
||||||
|
handleMessage(initialMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FirebaseMessaging.onMessageOpenedApp.listen(handleMessage);
|
||||||
});
|
});
|
||||||
|
|
||||||
// When the app is in the background and opened.
|
return null;
|
||||||
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(() {
|
useEffect(() {
|
||||||
@ -205,7 +185,7 @@ class IslandApp extends HookConsumerWidget {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
final router = ref.watch(routerProvider);
|
final router = ref.watch(routerProvider);
|
||||||
|
|
||||||
return MaterialApp.router(
|
return MaterialApp.router(
|
||||||
theme: theme?.light,
|
theme: theme?.light,
|
||||||
darkTheme: theme?.dark,
|
darkTheme: theme?.dark,
|
||||||
@ -224,8 +204,9 @@ class IslandApp extends HookConsumerWidget {
|
|||||||
initialEntries: [
|
initialEntries: [
|
||||||
OverlayEntry(
|
OverlayEntry(
|
||||||
builder:
|
builder:
|
||||||
(_) =>
|
(_) => WindowScaffold(
|
||||||
WindowScaffold(child: child ?? const SizedBox.shrink()),
|
child: child ?? const SizedBox.shrink(),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
@ -14,7 +14,6 @@ sealed class SnChatRoom with _$SnChatRoom {
|
|||||||
required String? description,
|
required String? description,
|
||||||
required int type,
|
required int type,
|
||||||
required bool isPublic,
|
required bool isPublic,
|
||||||
required bool isCommunity,
|
|
||||||
required SnCloudFile? picture,
|
required SnCloudFile? picture,
|
||||||
required SnCloudFile? background,
|
required SnCloudFile? background,
|
||||||
required String? realmId,
|
required String? realmId,
|
||||||
|
@ -16,7 +16,7 @@ T _$identity<T>(T value) => value;
|
|||||||
/// @nodoc
|
/// @nodoc
|
||||||
mixin _$SnChatRoom {
|
mixin _$SnChatRoom {
|
||||||
|
|
||||||
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;
|
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;
|
||||||
/// Create a copy of SnChatRoom
|
/// Create a copy of SnChatRoom
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@ -29,16 +29,16 @@ $SnChatRoomCopyWith<SnChatRoom> get copyWith => _$SnChatRoomCopyWithImpl<SnChatR
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
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.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));
|
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));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType,id,name,description,type,isPublic,isCommunity,picture,background,realmId,realm,createdAt,updatedAt,deletedAt,const DeepCollectionEquality().hash(members));
|
int get hashCode => Object.hash(runtimeType,id,name,description,type,isPublic,picture,background,realmId,realm,createdAt,updatedAt,deletedAt,const DeepCollectionEquality().hash(members));
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
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)';
|
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)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -49,7 +49,7 @@ abstract mixin class $SnChatRoomCopyWith<$Res> {
|
|||||||
factory $SnChatRoomCopyWith(SnChatRoom value, $Res Function(SnChatRoom) _then) = _$SnChatRoomCopyWithImpl;
|
factory $SnChatRoomCopyWith(SnChatRoom value, $Res Function(SnChatRoom) _then) = _$SnChatRoomCopyWithImpl;
|
||||||
@useResult
|
@useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
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
|
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
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@ -66,14 +66,13 @@ class _$SnChatRoomCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of SnChatRoom
|
/// Create a copy of SnChatRoom
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? 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,}) {
|
@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,}) {
|
||||||
return _then(_self.copyWith(
|
return _then(_self.copyWith(
|
||||||
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||||
as String,name: freezed == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
|
as String,name: freezed == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,description: freezed == description ? _self.description : description // ignore: cast_nullable_to_non_nullable
|
as String?,description: freezed == description ? _self.description : description // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable
|
as String?,type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable
|
||||||
as int,isPublic: null == isPublic ? _self.isPublic : isPublic // 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 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?,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
|
as SnCloudFile?,realmId: freezed == realmId ? _self.realmId : realmId // ignore: cast_nullable_to_non_nullable
|
||||||
@ -129,7 +128,7 @@ $SnRealmCopyWith<$Res>? get realm {
|
|||||||
@JsonSerializable()
|
@JsonSerializable()
|
||||||
|
|
||||||
class _SnChatRoom implements SnChatRoom {
|
class _SnChatRoom implements SnChatRoom {
|
||||||
const _SnChatRoom({required this.id, required this.name, required this.description, required this.type, required this.isPublic, required this.isCommunity, 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, 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;
|
||||||
factory _SnChatRoom.fromJson(Map<String, dynamic> json) => _$SnChatRoomFromJson(json);
|
factory _SnChatRoom.fromJson(Map<String, dynamic> json) => _$SnChatRoomFromJson(json);
|
||||||
|
|
||||||
@override final String id;
|
@override final String id;
|
||||||
@ -137,7 +136,6 @@ class _SnChatRoom implements SnChatRoom {
|
|||||||
@override final String? description;
|
@override final String? description;
|
||||||
@override final int type;
|
@override final int type;
|
||||||
@override final bool isPublic;
|
@override final bool isPublic;
|
||||||
@override final bool isCommunity;
|
|
||||||
@override final SnCloudFile? picture;
|
@override final SnCloudFile? picture;
|
||||||
@override final SnCloudFile? background;
|
@override final SnCloudFile? background;
|
||||||
@override final String? realmId;
|
@override final String? realmId;
|
||||||
@ -168,16 +166,16 @@ Map<String, dynamic> toJson() {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
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.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));
|
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));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType,id,name,description,type,isPublic,isCommunity,picture,background,realmId,realm,createdAt,updatedAt,deletedAt,const DeepCollectionEquality().hash(_members));
|
int get hashCode => Object.hash(runtimeType,id,name,description,type,isPublic,picture,background,realmId,realm,createdAt,updatedAt,deletedAt,const DeepCollectionEquality().hash(_members));
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
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)';
|
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)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -188,7 +186,7 @@ abstract mixin class _$SnChatRoomCopyWith<$Res> implements $SnChatRoomCopyWith<$
|
|||||||
factory _$SnChatRoomCopyWith(_SnChatRoom value, $Res Function(_SnChatRoom) _then) = __$SnChatRoomCopyWithImpl;
|
factory _$SnChatRoomCopyWith(_SnChatRoom value, $Res Function(_SnChatRoom) _then) = __$SnChatRoomCopyWithImpl;
|
||||||
@override @useResult
|
@override @useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
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
|
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
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@ -205,14 +203,13 @@ class __$SnChatRoomCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of SnChatRoom
|
/// Create a copy of SnChatRoom
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? 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,}) {
|
@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,}) {
|
||||||
return _then(_SnChatRoom(
|
return _then(_SnChatRoom(
|
||||||
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||||
as String,name: freezed == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
|
as String,name: freezed == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,description: freezed == description ? _self.description : description // ignore: cast_nullable_to_non_nullable
|
as String?,description: freezed == description ? _self.description : description // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable
|
as String?,type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable
|
||||||
as int,isPublic: null == isPublic ? _self.isPublic : isPublic // 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 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?,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
|
as SnCloudFile?,realmId: freezed == realmId ? _self.realmId : realmId // ignore: cast_nullable_to_non_nullable
|
||||||
|
@ -12,7 +12,6 @@ _SnChatRoom _$SnChatRoomFromJson(Map<String, dynamic> json) => _SnChatRoom(
|
|||||||
description: json['description'] as String?,
|
description: json['description'] as String?,
|
||||||
type: (json['type'] as num).toInt(),
|
type: (json['type'] as num).toInt(),
|
||||||
isPublic: json['is_public'] as bool,
|
isPublic: json['is_public'] as bool,
|
||||||
isCommunity: json['is_community'] as bool,
|
|
||||||
picture:
|
picture:
|
||||||
json['picture'] == null
|
json['picture'] == null
|
||||||
? null
|
? null
|
||||||
@ -45,7 +44,6 @@ Map<String, dynamic> _$SnChatRoomToJson(_SnChatRoom instance) =>
|
|||||||
'description': instance.description,
|
'description': instance.description,
|
||||||
'type': instance.type,
|
'type': instance.type,
|
||||||
'is_public': instance.isPublic,
|
'is_public': instance.isPublic,
|
||||||
'is_community': instance.isCommunity,
|
|
||||||
'picture': instance.picture?.toJson(),
|
'picture': instance.picture?.toJson(),
|
||||||
'background': instance.background?.toJson(),
|
'background': instance.background?.toJson(),
|
||||||
'realm_id': instance.realmId,
|
'realm_id': instance.realmId,
|
||||||
|
@ -11,7 +11,7 @@ sealed class SnRealm with _$SnRealm {
|
|||||||
required String id,
|
required String id,
|
||||||
required String slug,
|
required String slug,
|
||||||
required String name,
|
required String name,
|
||||||
@Default('') String description,
|
required String description,
|
||||||
required String? verifiedAs,
|
required String? verifiedAs,
|
||||||
required DateTime? verifiedAt,
|
required DateTime? verifiedAt,
|
||||||
required bool isCommunity,
|
required bool isCommunity,
|
||||||
|
@ -117,13 +117,13 @@ $SnCloudFileCopyWith<$Res>? get background {
|
|||||||
@JsonSerializable()
|
@JsonSerializable()
|
||||||
|
|
||||||
class _SnRealm implements SnRealm {
|
class _SnRealm implements SnRealm {
|
||||||
const _SnRealm({required this.id, required this.slug, required 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});
|
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});
|
||||||
factory _SnRealm.fromJson(Map<String, dynamic> json) => _$SnRealmFromJson(json);
|
factory _SnRealm.fromJson(Map<String, dynamic> json) => _$SnRealmFromJson(json);
|
||||||
|
|
||||||
@override final String id;
|
@override final String id;
|
||||||
@override final String slug;
|
@override final String slug;
|
||||||
@override final String name;
|
@override final String name;
|
||||||
@override@JsonKey() final String description;
|
@override final String description;
|
||||||
@override final String? verifiedAs;
|
@override final String? verifiedAs;
|
||||||
@override final DateTime? verifiedAt;
|
@override final DateTime? verifiedAt;
|
||||||
@override final bool isCommunity;
|
@override final bool isCommunity;
|
||||||
|
@ -10,7 +10,7 @@ _SnRealm _$SnRealmFromJson(Map<String, dynamic> json) => _SnRealm(
|
|||||||
id: json['id'] as String,
|
id: json['id'] as String,
|
||||||
slug: json['slug'] as String,
|
slug: json['slug'] as String,
|
||||||
name: json['name'] as String,
|
name: json['name'] as String,
|
||||||
description: json['description'] as String? ?? '',
|
description: json['description'] as String,
|
||||||
verifiedAs: json['verified_as'] as String?,
|
verifiedAs: json['verified_as'] as String?,
|
||||||
verifiedAt:
|
verifiedAt:
|
||||||
json['verified_at'] == null
|
json['verified_at'] == null
|
||||||
|
@ -31,7 +31,6 @@ import 'package:island/screens/settings.dart';
|
|||||||
import 'package:island/screens/realm/realms.dart';
|
import 'package:island/screens/realm/realms.dart';
|
||||||
import 'package:island/screens/realm/detail.dart';
|
import 'package:island/screens/realm/detail.dart';
|
||||||
import 'package:island/screens/account/event_calendar.dart';
|
import 'package:island/screens/account/event_calendar.dart';
|
||||||
import 'package:island/screens/discovery/realms.dart';
|
|
||||||
|
|
||||||
// Shell route keys for nested navigation
|
// Shell route keys for nested navigation
|
||||||
final rootNavigatorKey = GlobalKey<NavigatorState>();
|
final rootNavigatorKey = GlobalKey<NavigatorState>();
|
||||||
@ -106,7 +105,10 @@ final routerProvider = Provider<GoRouter>((ref) {
|
|||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
final name = state.pathParameters['name']!;
|
final name = state.pathParameters['name']!;
|
||||||
final packId = state.pathParameters['packId']!;
|
final packId = state.pathParameters['packId']!;
|
||||||
return EditStickerPacksScreen(pubName: name, packId: packId);
|
return EditStickerPacksScreen(
|
||||||
|
pubName: name,
|
||||||
|
packId: packId,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
GoRoute(
|
GoRoute(
|
||||||
@ -188,10 +190,6 @@ final routerProvider = Provider<GoRouter>((ref) {
|
|||||||
return PublisherProfileScreen(name: name);
|
return PublisherProfileScreen(name: name);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
GoRoute(
|
|
||||||
path: 'discovery/realms',
|
|
||||||
builder: (context, state) => const DiscoveryRealmsScreen(),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
||||||
@ -200,10 +198,6 @@ final routerProvider = Provider<GoRouter>((ref) {
|
|||||||
path: '/chat',
|
path: '/chat',
|
||||||
builder: (context, state) => const ChatListScreen(),
|
builder: (context, state) => const ChatListScreen(),
|
||||||
routes: [
|
routes: [
|
||||||
GoRoute(
|
|
||||||
path: 'new',
|
|
||||||
builder: (context, state) => const NewChatScreen(),
|
|
||||||
),
|
|
||||||
GoRoute(
|
GoRoute(
|
||||||
path: ':id',
|
path: ':id',
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
@ -211,6 +205,10 @@ final routerProvider = Provider<GoRouter>((ref) {
|
|||||||
return ChatRoomScreen(id: id);
|
return ChatRoomScreen(id: id);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
GoRoute(
|
||||||
|
path: 'new',
|
||||||
|
builder: (context, state) => const NewChatScreen(),
|
||||||
|
),
|
||||||
GoRoute(
|
GoRoute(
|
||||||
path: ':id/edit',
|
path: ':id/edit',
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
@ -229,9 +227,9 @@ final routerProvider = Provider<GoRouter>((ref) {
|
|||||||
),
|
),
|
||||||
|
|
||||||
// Realms tab
|
// Realms tab
|
||||||
GoRoute(
|
GoRoute(
|
||||||
path: '/realms',
|
path: '/realms',
|
||||||
builder: (context, state) => const RealmListScreen(),
|
builder: (context, state) => const RealmListScreen(),
|
||||||
routes: [
|
routes: [
|
||||||
GoRoute(
|
GoRoute(
|
||||||
path: 'new',
|
path: 'new',
|
||||||
|
@ -200,7 +200,7 @@ class AccountScreen extends HookConsumerWidget {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
context.push('/account/notifications');
|
context.push('/notification');
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
|
@ -215,7 +215,6 @@ class RelationshipScreen extends HookConsumerWidget {
|
|||||||
Future<void> addFriend() async {
|
Future<void> addFriend() async {
|
||||||
final result = await showModalBottomSheet(
|
final result = await showModalBottomSheet(
|
||||||
context: context,
|
context: context,
|
||||||
useRootNavigator: true,
|
|
||||||
builder: (context) => AccountPickerSheet(),
|
builder: (context) => AccountPickerSheet(),
|
||||||
);
|
);
|
||||||
if (result == null) return;
|
if (result == null) return;
|
||||||
|
@ -186,7 +186,7 @@ class ChatShellScreen extends HookConsumerWidget {
|
|||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
Flexible(flex: 2, child: ChatListScreen(isAside: true)),
|
Flexible(flex: 2, child: ChatListScreen(isAside: true)),
|
||||||
const VerticalDivider(width: 1),
|
VerticalDivider(width: 1),
|
||||||
Flexible(flex: 4, child: child),
|
Flexible(flex: 4, child: child),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@ -227,8 +227,7 @@ class ChatListScreen extends HookConsumerWidget {
|
|||||||
Future<void> createDirectMessage() async {
|
Future<void> createDirectMessage() async {
|
||||||
final result = await showModalBottomSheet(
|
final result = await showModalBottomSheet(
|
||||||
context: context,
|
context: context,
|
||||||
useRootNavigator: true,
|
builder: (context) => AccountPickerSheet(),
|
||||||
builder: (context) => const AccountPickerSheet(),
|
|
||||||
);
|
);
|
||||||
if (result == null) return;
|
if (result == null) return;
|
||||||
final client = ref.read(apiClientProvider);
|
final client = ref.read(apiClientProvider);
|
||||||
@ -243,7 +242,7 @@ class ChatListScreen extends HookConsumerWidget {
|
|||||||
return AppScaffold(
|
return AppScaffold(
|
||||||
extendBody: false, // Prevent conflicts with tabs navigation
|
extendBody: false, // Prevent conflicts with tabs navigation
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: const Text('chat').tr(),
|
title: Text('chat').tr(),
|
||||||
bottom: TabBar(
|
bottom: TabBar(
|
||||||
controller: tabController,
|
controller: tabController,
|
||||||
tabs: [
|
tabs: [
|
||||||
@ -297,7 +296,7 @@ class ChatListScreen extends HookConsumerWidget {
|
|||||||
showModalBottomSheet(
|
showModalBottomSheet(
|
||||||
isScrollControlled: true,
|
isScrollControlled: true,
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) => const _ChatInvitesSheet(),
|
builder: (context) => _ChatInvitesSheet(),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -308,14 +307,13 @@ class ChatListScreen extends HookConsumerWidget {
|
|||||||
onPressed: () {
|
onPressed: () {
|
||||||
showModalBottomSheet(
|
showModalBottomSheet(
|
||||||
context: context,
|
context: context,
|
||||||
useRootNavigator: true,
|
|
||||||
builder:
|
builder:
|
||||||
(context) => Column(
|
(context) => Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
children: [
|
children: [
|
||||||
ListTile(
|
ListTile(
|
||||||
title: const Text('createChatRoom').tr(),
|
title: Text('createChatRoom').tr(),
|
||||||
leading: const Icon(Symbols.add),
|
leading: const Icon(Symbols.add),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
@ -327,7 +325,7 @@ class ChatListScreen extends HookConsumerWidget {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
title: const Text('createDirectMessage').tr(),
|
title: Text('createDirectMessage').tr(),
|
||||||
leading: const Icon(Symbols.person),
|
leading: const Icon(Symbols.person),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
@ -452,7 +450,7 @@ class NewChatScreen extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return const EditChatScreen();
|
return EditChatScreen();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -470,8 +468,6 @@ class EditChatScreen extends HookConsumerWidget {
|
|||||||
final descriptionController = useTextEditingController();
|
final descriptionController = useTextEditingController();
|
||||||
final picture = useState<SnCloudFile?>(null);
|
final picture = useState<SnCloudFile?>(null);
|
||||||
final background = useState<SnCloudFile?>(null);
|
final background = useState<SnCloudFile?>(null);
|
||||||
final isPublic = useState(true);
|
|
||||||
final isCommunity = useState(false);
|
|
||||||
|
|
||||||
final chat = ref.watch(chatroomProvider(id));
|
final chat = ref.watch(chatroomProvider(id));
|
||||||
|
|
||||||
@ -484,14 +480,12 @@ class EditChatScreen extends HookConsumerWidget {
|
|||||||
descriptionController.text = chat.value!.description ?? '';
|
descriptionController.text = chat.value!.description ?? '';
|
||||||
picture.value = chat.value!.picture;
|
picture.value = chat.value!.picture;
|
||||||
background.value = chat.value!.background;
|
background.value = chat.value!.background;
|
||||||
isPublic.value = chat.value!.isPublic;
|
|
||||||
isCommunity.value = chat.value!.isCommunity;
|
|
||||||
currentRealm.value = joinedRealms.value?.firstWhereOrNull(
|
currentRealm.value = joinedRealms.value?.firstWhereOrNull(
|
||||||
(realm) => realm.id == chat.value!.realmId,
|
(realm) => realm.id == chat.value!.realmId,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}, [chat, joinedRealms]);
|
}, [chat]);
|
||||||
|
|
||||||
void setPicture(String position) async {
|
void setPicture(String position) async {
|
||||||
showLoadingModal(context);
|
showLoadingModal(context);
|
||||||
@ -509,9 +503,9 @@ class EditChatScreen extends HookConsumerWidget {
|
|||||||
image: result,
|
image: result,
|
||||||
allowedAspectRatios: [
|
allowedAspectRatios: [
|
||||||
if (position == 'background')
|
if (position == 'background')
|
||||||
const CropAspectRatio(height: 7, width: 16)
|
CropAspectRatio(height: 7, width: 16)
|
||||||
else
|
else
|
||||||
const CropAspectRatio(height: 1, width: 1),
|
CropAspectRatio(height: 1, width: 1),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
if (result == null) {
|
if (result == null) {
|
||||||
@ -568,8 +562,6 @@ class EditChatScreen extends HookConsumerWidget {
|
|||||||
'background_id': background.value?.id,
|
'background_id': background.value?.id,
|
||||||
'picture_id': picture.value?.id,
|
'picture_id': picture.value?.id,
|
||||||
'realm_id': currentRealm.value?.id,
|
'realm_id': currentRealm.value?.id,
|
||||||
'is_public': isPublic.value,
|
|
||||||
'is_community': isCommunity.value,
|
|
||||||
},
|
},
|
||||||
options: Options(method: id == null ? 'POST' : 'PATCH'),
|
options: Options(method: id == null ? 'POST' : 'PATCH'),
|
||||||
);
|
);
|
||||||
@ -662,19 +654,6 @@ class EditChatScreen extends HookConsumerWidget {
|
|||||||
(_) => FocusManager.instance.primaryFocus?.unfocus(),
|
(_) => FocusManager.instance.primaryFocus?.unfocus(),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
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(
|
Align(
|
||||||
alignment: Alignment.centerRight,
|
alignment: Alignment.centerRight,
|
||||||
child: TextButton.icon(
|
child: TextButton.icon(
|
||||||
@ -775,7 +754,7 @@ class _ChatInvitesSheet extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
if (invite.chatRoom!.type == 1)
|
if (invite.chatRoom!.type == 1)
|
||||||
Badge(
|
Badge(
|
||||||
label: const Text('directMessage').tr(),
|
label: Text('directMessage').tr(),
|
||||||
backgroundColor:
|
backgroundColor:
|
||||||
Theme.of(context).colorScheme.primary,
|
Theme.of(context).colorScheme.primary,
|
||||||
textColor:
|
textColor:
|
||||||
|
@ -295,20 +295,6 @@ class ChatRoomScreen extends HookConsumerWidget {
|
|||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final chatRoom = ref.watch(chatroomProvider(id));
|
final chatRoom = ref.watch(chatroomProvider(id));
|
||||||
final chatIdentity = ref.watch(chatroomIdentityProvider(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: Text('You are not a member of this chat room')),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
final messages = ref.watch(messagesNotifierProvider(id));
|
final messages = ref.watch(messagesNotifierProvider(id));
|
||||||
final messagesNotifier = ref.read(messagesNotifierProvider(id).notifier);
|
final messagesNotifier = ref.read(messagesNotifierProvider(id).notifier);
|
||||||
final ws = ref.watch(websocketProvider);
|
final ws = ref.watch(websocketProvider);
|
||||||
|
@ -584,8 +584,8 @@ class _ChatMemberListSheet extends HookConsumerWidget {
|
|||||||
|
|
||||||
Future<void> invitePerson() async {
|
Future<void> invitePerson() async {
|
||||||
final result = await showModalBottomSheet(
|
final result = await showModalBottomSheet(
|
||||||
|
isScrollControlled: true,
|
||||||
context: context,
|
context: context,
|
||||||
useRootNavigator: true,
|
|
||||||
builder: (context) => const AccountPickerSheet(),
|
builder: (context) => const AccountPickerSheet(),
|
||||||
);
|
);
|
||||||
if (result == null) return;
|
if (result == null) return;
|
||||||
|
@ -1,24 +0,0 @@
|
|||||||
import 'package:easy_localization/easy_localization.dart';
|
|
||||||
import 'package:flutter/material.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';
|
|
||||||
|
|
||||||
class DiscoveryRealmsScreen extends HookConsumerWidget {
|
|
||||||
const DiscoveryRealmsScreen({super.key});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
|
||||||
return AppScaffold(
|
|
||||||
appBar: AppBar(title: Text('discoverRealms'.tr())),
|
|
||||||
body: CustomScrollView(
|
|
||||||
slivers: [
|
|
||||||
SliverGap(16),
|
|
||||||
SliverRealmList(),
|
|
||||||
SliverGap(MediaQuery.of(context).padding.bottom + 16),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -5,7 +5,6 @@ import 'package:flutter_hooks/flutter_hooks.dart';
|
|||||||
import 'package:gap/gap.dart';
|
import 'package:gap/gap.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:island/models/activity.dart';
|
import 'package:island/models/activity.dart';
|
||||||
import 'package:island/models/realm.dart';
|
|
||||||
import 'package:island/pods/userinfo.dart';
|
import 'package:island/pods/userinfo.dart';
|
||||||
import 'package:island/services/responsive.dart';
|
import 'package:island/services/responsive.dart';
|
||||||
import 'package:island/widgets/app_scaffold.dart';
|
import 'package:island/widgets/app_scaffold.dart';
|
||||||
@ -18,8 +17,8 @@ import 'package:material_symbols_icons/symbols.dart';
|
|||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
import 'package:riverpod_paging_utils/riverpod_paging_utils.dart';
|
import 'package:riverpod_paging_utils/riverpod_paging_utils.dart';
|
||||||
import 'package:island/pods/network.dart';
|
import 'package:island/pods/network.dart';
|
||||||
import 'package:island/widgets/realm/realm_card.dart';
|
|
||||||
import 'package:styled_widget/styled_widget.dart';
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
|
import 'package:island/models/realm.dart';
|
||||||
|
|
||||||
part 'explore.g.dart';
|
part 'explore.g.dart';
|
||||||
|
|
||||||
@ -207,7 +206,7 @@ class _DiscoveryActivityItem extends StatelessWidget {
|
|||||||
padding: const EdgeInsets.only(right: 8),
|
padding: const EdgeInsets.only(right: 8),
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
final realm = items[index];
|
final realm = items[index];
|
||||||
return RealmCard(realm: realm);
|
return _RealmCard(realm: realm);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -216,6 +215,86 @@ class _DiscoveryActivityItem extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class _RealmCard extends ConsumerWidget {
|
||||||
|
final SnRealm realm;
|
||||||
|
|
||||||
|
const _RealmCard({required this.realm});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final client = ref.watch(apiClientProvider);
|
||||||
|
|
||||||
|
Widget imageWidget;
|
||||||
|
if (realm.picture != null) {
|
||||||
|
final imageUrl = '${client.options.baseUrl}/files/${realm.picture!.id}';
|
||||||
|
imageWidget = Image.network(
|
||||||
|
imageUrl,
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
width: double.infinity,
|
||||||
|
height: double.infinity,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
imageWidget = Container(
|
||||||
|
color: Theme.of(context).colorScheme.secondaryContainer,
|
||||||
|
child: Center(
|
||||||
|
child: Icon(
|
||||||
|
Symbols.photo_camera,
|
||||||
|
color: Theme.of(context).colorScheme.onSecondaryContainer,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Card(
|
||||||
|
clipBehavior: Clip.antiAlias,
|
||||||
|
margin: const EdgeInsets.only(left: 16, bottom: 8, top: 8),
|
||||||
|
child: InkWell(
|
||||||
|
onTap: () {
|
||||||
|
context.push('/realms/${realm.slug}');
|
||||||
|
},
|
||||||
|
child: ConstrainedBox(
|
||||||
|
constraints: const BoxConstraints(maxWidth: 280),
|
||||||
|
child: AspectRatio(
|
||||||
|
aspectRatio: 16 / 7,
|
||||||
|
child: Stack(
|
||||||
|
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: Text(
|
||||||
|
realm.name,
|
||||||
|
style: Theme.of(context).textTheme.titleSmall?.copyWith(
|
||||||
|
color: Colors.white,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
maxLines: 2,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class _ActivityListView extends HookConsumerWidget {
|
class _ActivityListView extends HookConsumerWidget {
|
||||||
final CursorPagingData<SnActivity> data;
|
final CursorPagingData<SnActivity> data;
|
||||||
final int widgetCount;
|
final int widgetCount;
|
||||||
|
@ -1,17 +1,12 @@
|
|||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:island/screens/chat/chat.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:island/models/chat.dart';
|
|
||||||
import 'package:island/services/color.dart';
|
|
||||||
import 'package:palette_generator/palette_generator.dart';
|
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
import 'package:gap/gap.dart';
|
import 'package:gap/gap.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:island/models/realm.dart';
|
import 'package:island/models/realm.dart';
|
||||||
import 'package:island/pods/network.dart';
|
import 'package:island/pods/network.dart';
|
||||||
import 'package:island/pods/config.dart';
|
|
||||||
import 'package:island/screens/realm/realms.dart';
|
import 'package:island/screens/realm/realms.dart';
|
||||||
import 'package:island/widgets/account/account_picker.dart';
|
import 'package:island/widgets/account/account_picker.dart';
|
||||||
import 'package:island/widgets/alert.dart';
|
import 'package:island/widgets/alert.dart';
|
||||||
@ -24,40 +19,11 @@ import 'package:styled_widget/styled_widget.dart';
|
|||||||
|
|
||||||
part 'detail.g.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
|
@riverpod
|
||||||
Future<SnRealmMember?> realmIdentity(Ref ref, String realmSlug) async {
|
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 apiClient = ref.watch(apiClientProvider);
|
||||||
final response = await apiClient.get('/realms/$realmSlug/chat');
|
final response = await apiClient.get('/realms/$realmSlug/members/me');
|
||||||
return (response.data as List).map((e) => SnChatRoom.fromJson(e)).toList();
|
return SnRealmMember.fromJson(response.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
class RealmDetailScreen extends HookConsumerWidget {
|
class RealmDetailScreen extends HookConsumerWidget {
|
||||||
@ -68,10 +34,9 @@ class RealmDetailScreen extends HookConsumerWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final realmState = ref.watch(realmProvider(slug));
|
final realmState = ref.watch(realmProvider(slug));
|
||||||
final appbarColor = ref.watch(realmAppbarForegroundColorProvider(slug));
|
|
||||||
|
|
||||||
final iconShadow = Shadow(
|
const iconShadow = Shadow(
|
||||||
color: appbarColor.value?.invert ?? Colors.black54,
|
color: Colors.black54,
|
||||||
blurRadius: 5.0,
|
blurRadius: 5.0,
|
||||||
offset: Offset(1.0, 1.0),
|
offset: Offset(1.0, 1.0),
|
||||||
);
|
);
|
||||||
@ -86,11 +51,7 @@ class RealmDetailScreen extends HookConsumerWidget {
|
|||||||
SliverAppBar(
|
SliverAppBar(
|
||||||
expandedHeight: 180,
|
expandedHeight: 180,
|
||||||
pinned: true,
|
pinned: true,
|
||||||
foregroundColor: appbarColor.value,
|
leading: PageBackButton(shadows: [iconShadow]),
|
||||||
leading: PageBackButton(
|
|
||||||
color: appbarColor.value,
|
|
||||||
shadows: [iconShadow],
|
|
||||||
),
|
|
||||||
flexibleSpace: FlexibleSpaceBar(
|
flexibleSpace: FlexibleSpaceBar(
|
||||||
background:
|
background:
|
||||||
realm!.background?.id != null
|
realm!.background?.id != null
|
||||||
@ -102,16 +63,14 @@ class RealmDetailScreen extends HookConsumerWidget {
|
|||||||
title: Text(
|
title: Text(
|
||||||
realm.name,
|
realm.name,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color:
|
color: Theme.of(context).appBarTheme.foregroundColor,
|
||||||
appbarColor.value ??
|
|
||||||
Theme.of(context).appBarTheme.foregroundColor,
|
|
||||||
shadows: [iconShadow],
|
shadows: [iconShadow],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: Icon(Icons.people, shadows: [iconShadow]),
|
icon: const Icon(Icons.people, shadows: [iconShadow]),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
showModalBottomSheet(
|
showModalBottomSheet(
|
||||||
isScrollControlled: true,
|
isScrollControlled: true,
|
||||||
@ -127,97 +86,18 @@ class RealmDetailScreen extends HookConsumerWidget {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
SliverToBoxAdapter(
|
SliverToBoxAdapter(
|
||||||
child: ref
|
child: Padding(
|
||||||
.watch(realmIdentityProvider(slug))
|
padding: const EdgeInsets.all(16.0),
|
||||||
.when(
|
child: Column(
|
||||||
loading: () => const SizedBox.shrink(),
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
error: (_, _) => const SizedBox.shrink(),
|
children: [
|
||||||
data:
|
Text(
|
||||||
(identity) => Column(
|
realm.description,
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
style: const TextStyle(fontSize: 16),
|
||||||
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.isPublic)
|
|
||||||
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('joinRealmSuccess'.tr());
|
|
||||||
} catch (err) {
|
|
||||||
showErrorAlert(err);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
icon: const Icon(Symbols.add),
|
|
||||||
label: const Text('joinRealm').tr(),
|
|
||||||
).padding(horizontal: 16, vertical: 8)
|
|
||||||
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),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@ -234,8 +114,8 @@ class _RealmActionMenu extends HookConsumerWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final realmIdentity = ref.watch(realmIdentityProvider(realmSlug));
|
final realmIdentityAsync = ref.watch(realmIdentityProvider(realmSlug));
|
||||||
final isModerator = realmIdentity.when(
|
final isModerator = realmIdentityAsync.when(
|
||||||
data: (identity) => (identity?.role ?? 0) >= 50,
|
data: (identity) => (identity?.role ?? 0) >= 50,
|
||||||
loading: () => false,
|
loading: () => false,
|
||||||
error: (_, _) => false,
|
error: (_, _) => false,
|
||||||
@ -261,7 +141,7 @@ class _RealmActionMenu extends HookConsumerWidget {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
realmIdentity.when(
|
realmIdentityAsync.when(
|
||||||
data:
|
data:
|
||||||
(identity) =>
|
(identity) =>
|
||||||
(identity?.role ?? 0) >= 100
|
(identity?.role ?? 0) >= 100
|
||||||
|
@ -6,8 +6,7 @@ part of 'detail.dart';
|
|||||||
// RiverpodGenerator
|
// RiverpodGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
String _$realmAppbarForegroundColorHash() =>
|
String _$realmIdentityHash() => r'eac6e829b5b46bcfadbf201ab6f918d78c894b9f';
|
||||||
r'14b5563d861996ea182d0d2db7aa5c2bb3bbaf48';
|
|
||||||
|
|
||||||
/// Copied from Dart SDK
|
/// Copied from Dart SDK
|
||||||
class _SystemHash {
|
class _SystemHash {
|
||||||
@ -30,133 +29,6 @@ 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].
|
/// See also [realmIdentity].
|
||||||
@ProviderFor(realmIdentity)
|
@ProviderFor(realmIdentity)
|
||||||
const realmIdentityProvider = RealmIdentityFamily();
|
const realmIdentityProvider = RealmIdentityFamily();
|
||||||
@ -276,128 +148,6 @@ class _RealmIdentityProviderElement
|
|||||||
String get realmSlug => (origin as RealmIdentityProvider).realmSlug;
|
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() =>
|
String _$realmMemberListNotifierHash() =>
|
||||||
r'b2e3eefc62a597f45df9470b2058fdda62f8853f';
|
r'b2e3eefc62a597f45df9470b2058fdda62f8853f';
|
||||||
|
|
||||||
|
@ -46,10 +46,6 @@ class RealmListScreen extends HookConsumerWidget {
|
|||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: const Text('realms').tr(),
|
title: const Text('realms').tr(),
|
||||||
actions: [
|
actions: [
|
||||||
IconButton(
|
|
||||||
icon: const Icon(Symbols.travel_explore),
|
|
||||||
onPressed: () => context.push('/discovery/realms'),
|
|
||||||
),
|
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: Badge(
|
icon: Badge(
|
||||||
label: Text(
|
label: Text(
|
||||||
@ -70,7 +66,7 @@ class RealmListScreen extends HookConsumerWidget {
|
|||||||
showModalBottomSheet(
|
showModalBottomSheet(
|
||||||
context: context,
|
context: context,
|
||||||
isScrollControlled: true,
|
isScrollControlled: true,
|
||||||
builder: (_) => const _RealmInviteSheet(),
|
builder: (_) => _RealmInviteSheet(),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -78,7 +74,7 @@ class RealmListScreen extends HookConsumerWidget {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
floatingActionButton: FloatingActionButton(
|
floatingActionButton: FloatingActionButton(
|
||||||
heroTag: const Key("realms-page-fab"),
|
heroTag: Key("realms-page-fab"),
|
||||||
child: const Icon(Symbols.add),
|
child: const Icon(Symbols.add),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
context.push('/realms/new').then((value) {
|
context.push('/realms/new').then((value) {
|
||||||
@ -110,7 +106,7 @@ class RealmListScreen extends HookConsumerWidget {
|
|||||||
onTap: () {
|
onTap: () {
|
||||||
context.push('/realms/${value[item].slug}');
|
context.push('/realms/${value[item].slug}');
|
||||||
},
|
},
|
||||||
contentPadding: const EdgeInsets.only(
|
contentPadding: EdgeInsets.only(
|
||||||
left: 16,
|
left: 16,
|
||||||
right: 14,
|
right: 14,
|
||||||
top: 8,
|
top: 8,
|
||||||
@ -162,8 +158,6 @@ class EditRealmScreen extends HookConsumerWidget {
|
|||||||
|
|
||||||
final picture = useState<SnCloudFile?>(null);
|
final picture = useState<SnCloudFile?>(null);
|
||||||
final background = useState<SnCloudFile?>(null);
|
final background = useState<SnCloudFile?>(null);
|
||||||
final isPublic = useState(true);
|
|
||||||
final isCommunity = useState(false);
|
|
||||||
|
|
||||||
final slugController = useTextEditingController();
|
final slugController = useTextEditingController();
|
||||||
final nameController = useTextEditingController();
|
final nameController = useTextEditingController();
|
||||||
@ -180,8 +174,6 @@ class EditRealmScreen extends HookConsumerWidget {
|
|||||||
slugController.text = realm.value!.slug;
|
slugController.text = realm.value!.slug;
|
||||||
nameController.text = realm.value!.name;
|
nameController.text = realm.value!.name;
|
||||||
descriptionController.text = realm.value!.description;
|
descriptionController.text = realm.value!.description;
|
||||||
isPublic.value = realm.value!.isPublic;
|
|
||||||
isCommunity.value = realm.value!.isCommunity;
|
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}, [realm]);
|
}, [realm]);
|
||||||
@ -202,9 +194,9 @@ class EditRealmScreen extends HookConsumerWidget {
|
|||||||
image: result,
|
image: result,
|
||||||
allowedAspectRatios: [
|
allowedAspectRatios: [
|
||||||
if (position == 'background')
|
if (position == 'background')
|
||||||
const CropAspectRatio(height: 7, width: 16)
|
CropAspectRatio(height: 7, width: 16)
|
||||||
else
|
else
|
||||||
const CropAspectRatio(height: 1, width: 1),
|
CropAspectRatio(height: 1, width: 1),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
if (result == null) {
|
if (result == null) {
|
||||||
@ -260,8 +252,6 @@ class EditRealmScreen extends HookConsumerWidget {
|
|||||||
'description': descriptionController.text,
|
'description': descriptionController.text,
|
||||||
'background_id': background.value?.id,
|
'background_id': background.value?.id,
|
||||||
'picture_id': picture.value?.id,
|
'picture_id': picture.value?.id,
|
||||||
'is_public': isPublic.value,
|
|
||||||
'is_community': isCommunity.value,
|
|
||||||
},
|
},
|
||||||
options: Options(method: slug == null ? 'POST' : 'PATCH'),
|
options: Options(method: slug == null ? 'POST' : 'PATCH'),
|
||||||
);
|
);
|
||||||
@ -294,9 +284,9 @@ class EditRealmScreen extends HookConsumerWidget {
|
|||||||
child:
|
child:
|
||||||
background.value != null
|
background.value != null
|
||||||
? CloudFileWidget(
|
? CloudFileWidget(
|
||||||
item: background.value!,
|
item: background.value!,
|
||||||
fit: BoxFit.cover,
|
fit: BoxFit.cover,
|
||||||
)
|
)
|
||||||
: const SizedBox.shrink(),
|
: const SizedBox.shrink(),
|
||||||
),
|
),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
@ -324,6 +314,7 @@ class EditRealmScreen extends HookConsumerWidget {
|
|||||||
key: formKey,
|
key: formKey,
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
spacing: 16,
|
||||||
children: [
|
children: [
|
||||||
TextFormField(
|
TextFormField(
|
||||||
controller: slugController,
|
controller: slugController,
|
||||||
@ -334,14 +325,12 @@ class EditRealmScreen extends HookConsumerWidget {
|
|||||||
onTapOutside:
|
onTapOutside:
|
||||||
(_) => FocusManager.instance.primaryFocus?.unfocus(),
|
(_) => FocusManager.instance.primaryFocus?.unfocus(),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
|
||||||
TextFormField(
|
TextFormField(
|
||||||
controller: nameController,
|
controller: nameController,
|
||||||
decoration: InputDecoration(labelText: 'name'.tr()),
|
decoration: InputDecoration(labelText: 'name'.tr()),
|
||||||
onTapOutside:
|
onTapOutside:
|
||||||
(_) => FocusManager.instance.primaryFocus?.unfocus(),
|
(_) => FocusManager.instance.primaryFocus?.unfocus(),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
|
||||||
TextFormField(
|
TextFormField(
|
||||||
controller: descriptionController,
|
controller: descriptionController,
|
||||||
decoration: InputDecoration(labelText: 'description'.tr()),
|
decoration: InputDecoration(labelText: 'description'.tr()),
|
||||||
@ -350,20 +339,6 @@ class EditRealmScreen extends HookConsumerWidget {
|
|||||||
onTapOutside:
|
onTapOutside:
|
||||||
(_) => FocusManager.instance.primaryFocus?.unfocus(),
|
(_) => 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(
|
Align(
|
||||||
alignment: Alignment.centerRight,
|
alignment: Alignment.centerRight,
|
||||||
child: TextButton.icon(
|
child: TextButton.icon(
|
||||||
@ -435,47 +410,47 @@ class _RealmInviteSheet extends HookConsumerWidget {
|
|||||||
(items) =>
|
(items) =>
|
||||||
items.isEmpty
|
items.isEmpty
|
||||||
? Center(
|
? Center(
|
||||||
child:
|
child:
|
||||||
Text(
|
Text(
|
||||||
'invitesEmpty',
|
'invitesEmpty',
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
).tr(),
|
).tr(),
|
||||||
)
|
)
|
||||||
: ListView.builder(
|
: ListView.builder(
|
||||||
shrinkWrap: true,
|
shrinkWrap: true,
|
||||||
itemCount: items.length,
|
itemCount: items.length,
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
final invite = items[index];
|
final invite = items[index];
|
||||||
return ListTile(
|
return ListTile(
|
||||||
leading: ProfilePictureWidget(
|
leading: ProfilePictureWidget(
|
||||||
fileId: invite.realm!.picture?.id,
|
fileId: invite.realm!.picture?.id,
|
||||||
fallbackIcon: Symbols.group,
|
fallbackIcon: Symbols.group,
|
||||||
),
|
),
|
||||||
title: Text(invite.realm!.name),
|
title: Text(invite.realm!.name),
|
||||||
subtitle:
|
subtitle:
|
||||||
Text(
|
Text(
|
||||||
invite.role >= 100
|
invite.role >= 100
|
||||||
? 'permissionOwner'
|
? 'permissionOwner'
|
||||||
: invite.role >= 50
|
: invite.role >= 50
|
||||||
? 'permissionModerator'
|
? 'permissionModerator'
|
||||||
: 'permissionMember',
|
: 'permissionMember',
|
||||||
).tr(),
|
).tr(),
|
||||||
trailing: Row(
|
trailing: Row(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: const Icon(Symbols.check),
|
icon: const Icon(Symbols.check),
|
||||||
onPressed: () => acceptInvite(invite),
|
onPressed: () => acceptInvite(invite),
|
||||||
),
|
),
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: const Icon(Symbols.close),
|
icon: const Icon(Symbols.close),
|
||||||
onPressed: () => declineInvite(invite),
|
onPressed: () => declineInvite(invite),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
loading: () => const Center(child: CircularProgressIndicator()),
|
loading: () => const Center(child: CircularProgressIndicator()),
|
||||||
error:
|
error:
|
||||||
(error, _) => ResponseErrorWidget(
|
(error, _) => ResponseErrorWidget(
|
||||||
@ -485,4 +460,4 @@ class _RealmInviteSheet extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -233,27 +233,16 @@ class MessageItem extends HookConsumerWidget {
|
|||||||
if (remoteMessage.meta['embeds'] != null)
|
if (remoteMessage.meta['embeds'] != null)
|
||||||
...((remoteMessage.meta['embeds'] as List<dynamic>)
|
...((remoteMessage.meta['embeds'] as List<dynamic>)
|
||||||
.where((embed) => embed['Type'] == 'link')
|
.where((embed) => embed['Type'] == 'link')
|
||||||
.map(
|
.map((embed) => SnEmbedLink.fromJson(embed as Map<String, dynamic>))
|
||||||
(embed) => SnEmbedLink.fromJson(
|
.map((link) => LayoutBuilder(
|
||||||
embed as Map<String, dynamic>,
|
builder: (context, constraints) {
|
||||||
),
|
return EmbedLinkWidget(
|
||||||
)
|
link: link,
|
||||||
.map(
|
maxWidth: math.min(constraints.maxWidth, 480),
|
||||||
(link) => LayoutBuilder(
|
margin: const EdgeInsets.symmetric(vertical: 4),
|
||||||
builder: (context, constraints) {
|
);
|
||||||
return EmbedLinkWidget(
|
},
|
||||||
link: link,
|
))
|
||||||
maxWidth: math.min(
|
|
||||||
constraints.maxWidth,
|
|
||||||
480,
|
|
||||||
),
|
|
||||||
margin: const EdgeInsets.symmetric(
|
|
||||||
vertical: 4,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.toList()),
|
.toList()),
|
||||||
if (progress != null && progress!.isNotEmpty)
|
if (progress != null && progress!.isNotEmpty)
|
||||||
Column(
|
Column(
|
||||||
@ -493,11 +482,7 @@ class _MessageItemContent extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
case 'text':
|
case 'text':
|
||||||
default:
|
default:
|
||||||
return MarkdownTextContent(
|
return MarkdownTextContent(content: item.content!, isSelectable: true);
|
||||||
content: item.content!,
|
|
||||||
isSelectable: true,
|
|
||||||
linesMargin: EdgeInsets.zero,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,82 +0,0 @@
|
|||||||
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/pods/network.dart';
|
|
||||||
import 'package:material_symbols_icons/symbols.dart';
|
|
||||||
|
|
||||||
class RealmCard extends ConsumerWidget {
|
|
||||||
final SnRealm realm;
|
|
||||||
|
|
||||||
const RealmCard({super.key, required this.realm});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
|
||||||
final client = ref.watch(apiClientProvider);
|
|
||||||
|
|
||||||
Widget imageWidget;
|
|
||||||
if (realm.picture != null) {
|
|
||||||
final imageUrl = '${client.options.baseUrl}/files/${realm.picture!.id}';
|
|
||||||
imageWidget = Image.network(
|
|
||||||
imageUrl,
|
|
||||||
fit: BoxFit.cover,
|
|
||||||
width: double.infinity,
|
|
||||||
height: double.infinity,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
imageWidget = Container(
|
|
||||||
color: Theme.of(context).colorScheme.secondaryContainer,
|
|
||||||
child: Center(
|
|
||||||
child: Icon(
|
|
||||||
Symbols.photo_camera,
|
|
||||||
color: Theme.of(context).colorScheme.onSecondaryContainer,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Card(
|
|
||||||
clipBehavior: Clip.antiAlias,
|
|
||||||
child: InkWell(
|
|
||||||
onTap: () {
|
|
||||||
context.push('/realms/${realm.slug}');
|
|
||||||
},
|
|
||||||
child: AspectRatio(
|
|
||||||
aspectRatio: 16 / 7,
|
|
||||||
child: Stack(
|
|
||||||
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: Text(
|
|
||||||
realm.name,
|
|
||||||
style: Theme.of(context).textTheme.titleSmall?.copyWith(
|
|
||||||
color: Colors.white,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
maxLines: 2,
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,77 +0,0 @@
|
|||||||
import 'package:flutter/material.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() {
|
|
||||||
return fetch(cursor: null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<CursorPagingData<SnRealm>> fetch({required String? cursor}) async {
|
|
||||||
final client = ref.read(apiClientProvider);
|
|
||||||
final offset = cursor == null ? 0 : int.parse(cursor);
|
|
||||||
|
|
||||||
final queryParams = {'offset': offset, 'take': _pageSize};
|
|
||||||
|
|
||||||
final response = await client.get(
|
|
||||||
'/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});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
|
||||||
return PagingHelperSliverView(
|
|
||||||
provider: realmListNotifierProvider,
|
|
||||||
futureRefreshable: realmListNotifierProvider.future,
|
|
||||||
notifierRefreshable: realmListNotifierProvider.notifier,
|
|
||||||
contentBuilder:
|
|
||||||
(data, widgetCount, endItemView) => SliverList.builder(
|
|
||||||
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),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,30 +0,0 @@
|
|||||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
|
||||||
|
|
||||||
part of 'realm_list.dart';
|
|
||||||
|
|
||||||
// **************************************************************************
|
|
||||||
// RiverpodGenerator
|
|
||||||
// **************************************************************************
|
|
||||||
|
|
||||||
String _$realmListNotifierHash() => r'440eb8c61db2059699191b904b6518a0b01ccd25';
|
|
||||||
|
|
||||||
/// See also [RealmListNotifier].
|
|
||||||
@ProviderFor(RealmListNotifier)
|
|
||||||
final realmListNotifierProvider = AutoDisposeAsyncNotifierProvider<
|
|
||||||
RealmListNotifier,
|
|
||||||
CursorPagingData<SnRealm>
|
|
||||||
>.internal(
|
|
||||||
RealmListNotifier.new,
|
|
||||||
name: r'realmListNotifierProvider',
|
|
||||||
debugGetCreateSourceHash:
|
|
||||||
const bool.fromEnvironment('dart.vm.product')
|
|
||||||
? null
|
|
||||||
: _$realmListNotifierHash,
|
|
||||||
dependencies: null,
|
|
||||||
allTransitiveDependencies: null,
|
|
||||||
);
|
|
||||||
|
|
||||||
typedef _$RealmListNotifier =
|
|
||||||
AutoDisposeAsyncNotifier<CursorPagingData<SnRealm>>;
|
|
||||||
// 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
|
|
@ -1,20 +0,0 @@
|
|||||||
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}'),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user