From 401df0f49caf68e8ee088e8b68219e87e76ba75f Mon Sep 17 00:00:00 2001 From: LittleSheep Date: Sat, 17 May 2025 03:08:50 +0800 Subject: [PATCH] :sparkles: Create chat belongs to realm --- assets/i18n/en-US.json | 2 +- lib/models/post.dart | 1 + lib/models/post.freezed.dart | 31 +++++----- lib/models/post.g.dart | 2 + lib/screens/account/me/publishers.dart | 64 +++++--------------- lib/screens/chat/chat.dart | 41 ++++++++++--- lib/screens/chat/room.dart | 6 ++ lib/widgets/alert.dart | 2 +- lib/widgets/realms/selection_dropdown.dart | 70 ++++++++++++++++++++++ 9 files changed, 148 insertions(+), 71 deletions(-) create mode 100644 lib/widgets/realms/selection_dropdown.dart diff --git a/assets/i18n/en-US.json b/assets/i18n/en-US.json index 04ac212..733b3aa 100644 --- a/assets/i18n/en-US.json +++ b/assets/i18n/en-US.json @@ -181,7 +181,7 @@ "uploadAll": "Upload All", "stickerCopyPlaceholder": "Copy Placeholder", "realmSelection": "Select a Realm", - "publisherIndividual": "Individual Publishers", + "individual": "Individual", "firstPostBadgeName": "First Post", "firstPostBadgeDescription": "Created your first post on Solar Network", "popularPostBadgeName": "Popular Post", diff --git a/lib/models/post.dart b/lib/models/post.dart index 86dd64f..a344892 100644 --- a/lib/models/post.dart +++ b/lib/models/post.dart @@ -58,6 +58,7 @@ abstract class SnPublisher with _$SnPublisher { required DateTime createdAt, required DateTime updatedAt, required DateTime? deletedAt, + required String? realmId, }) = _SnPublisher; factory SnPublisher.fromJson(Map json) => diff --git a/lib/models/post.freezed.dart b/lib/models/post.freezed.dart index 9cae9e1..7e342a7 100644 --- a/lib/models/post.freezed.dart +++ b/lib/models/post.freezed.dart @@ -370,7 +370,7 @@ $SnPublisherCopyWith<$Res> get publisher { /// @nodoc mixin _$SnPublisher { - String get id; int get type; String get name; String get nick; String get bio; String? get pictureId; SnCloudFile? get picture; String? get backgroundId; SnCloudFile? get background; String? get accountId; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt; + String get id; int get type; String get name; String get nick; String get bio; String? get pictureId; SnCloudFile? get picture; String? get backgroundId; SnCloudFile? get background; String? get accountId; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt; String? get realmId; /// Create a copy of SnPublisher /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @@ -383,16 +383,16 @@ $SnPublisherCopyWith get copyWith => _$SnPublisherCopyWithImpl Object.hash(runtimeType,id,type,name,nick,bio,pictureId,picture,backgroundId,background,accountId,createdAt,updatedAt,deletedAt); +int get hashCode => Object.hash(runtimeType,id,type,name,nick,bio,pictureId,picture,backgroundId,background,accountId,createdAt,updatedAt,deletedAt,realmId); @override String toString() { - return 'SnPublisher(id: $id, type: $type, name: $name, nick: $nick, bio: $bio, pictureId: $pictureId, picture: $picture, backgroundId: $backgroundId, background: $background, accountId: $accountId, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)'; + return 'SnPublisher(id: $id, type: $type, name: $name, nick: $nick, bio: $bio, pictureId: $pictureId, picture: $picture, backgroundId: $backgroundId, background: $background, accountId: $accountId, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, realmId: $realmId)'; } @@ -403,7 +403,7 @@ abstract mixin class $SnPublisherCopyWith<$Res> { factory $SnPublisherCopyWith(SnPublisher value, $Res Function(SnPublisher) _then) = _$SnPublisherCopyWithImpl; @useResult $Res call({ - String id, int type, String name, String nick, String bio, String? pictureId, SnCloudFile? picture, String? backgroundId, SnCloudFile? background, String? accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt + String id, int type, String name, String nick, String bio, String? pictureId, SnCloudFile? picture, String? backgroundId, SnCloudFile? background, String? accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, String? realmId }); @@ -420,7 +420,7 @@ class _$SnPublisherCopyWithImpl<$Res> /// Create a copy of SnPublisher /// with the given fields replaced by the non-null parameter values. -@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? type = null,Object? name = null,Object? nick = null,Object? bio = null,Object? pictureId = freezed,Object? picture = freezed,Object? backgroundId = freezed,Object? background = freezed,Object? accountId = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) { +@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? type = null,Object? name = null,Object? nick = null,Object? bio = null,Object? pictureId = freezed,Object? picture = freezed,Object? backgroundId = freezed,Object? background = freezed,Object? accountId = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,Object? realmId = freezed,}) { return _then(_self.copyWith( id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable as String,type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable @@ -435,7 +435,8 @@ as SnCloudFile?,accountId: freezed == accountId ? _self.accountId : accountId // as String?,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable -as DateTime?, +as DateTime?,realmId: freezed == realmId ? _self.realmId : realmId // ignore: cast_nullable_to_non_nullable +as String?, )); } /// Create a copy of SnPublisher @@ -470,7 +471,7 @@ $SnCloudFileCopyWith<$Res>? get background { @JsonSerializable() class _SnPublisher implements SnPublisher { - const _SnPublisher({required this.id, required this.type, required this.name, required this.nick, required this.bio, required this.pictureId, required this.picture, required this.backgroundId, required this.background, required this.accountId, required this.createdAt, required this.updatedAt, required this.deletedAt}); + const _SnPublisher({required this.id, required this.type, required this.name, required this.nick, required this.bio, required this.pictureId, required this.picture, required this.backgroundId, required this.background, required this.accountId, required this.createdAt, required this.updatedAt, required this.deletedAt, required this.realmId}); factory _SnPublisher.fromJson(Map json) => _$SnPublisherFromJson(json); @override final String id; @@ -486,6 +487,7 @@ class _SnPublisher implements SnPublisher { @override final DateTime createdAt; @override final DateTime updatedAt; @override final DateTime? deletedAt; +@override final String? realmId; /// Create a copy of SnPublisher /// with the given fields replaced by the non-null parameter values. @@ -500,16 +502,16 @@ Map toJson() { @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnPublisher&&(identical(other.id, id) || other.id == id)&&(identical(other.type, type) || other.type == type)&&(identical(other.name, name) || other.name == name)&&(identical(other.nick, nick) || other.nick == nick)&&(identical(other.bio, bio) || other.bio == bio)&&(identical(other.pictureId, pictureId) || other.pictureId == pictureId)&&(identical(other.picture, picture) || other.picture == picture)&&(identical(other.backgroundId, backgroundId) || other.backgroundId == backgroundId)&&(identical(other.background, background) || other.background == background)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)); + return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnPublisher&&(identical(other.id, id) || other.id == id)&&(identical(other.type, type) || other.type == type)&&(identical(other.name, name) || other.name == name)&&(identical(other.nick, nick) || other.nick == nick)&&(identical(other.bio, bio) || other.bio == bio)&&(identical(other.pictureId, pictureId) || other.pictureId == pictureId)&&(identical(other.picture, picture) || other.picture == picture)&&(identical(other.backgroundId, backgroundId) || other.backgroundId == backgroundId)&&(identical(other.background, background) || other.background == background)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)&&(identical(other.realmId, realmId) || other.realmId == realmId)); } @JsonKey(includeFromJson: false, includeToJson: false) @override -int get hashCode => Object.hash(runtimeType,id,type,name,nick,bio,pictureId,picture,backgroundId,background,accountId,createdAt,updatedAt,deletedAt); +int get hashCode => Object.hash(runtimeType,id,type,name,nick,bio,pictureId,picture,backgroundId,background,accountId,createdAt,updatedAt,deletedAt,realmId); @override String toString() { - return 'SnPublisher(id: $id, type: $type, name: $name, nick: $nick, bio: $bio, pictureId: $pictureId, picture: $picture, backgroundId: $backgroundId, background: $background, accountId: $accountId, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)'; + return 'SnPublisher(id: $id, type: $type, name: $name, nick: $nick, bio: $bio, pictureId: $pictureId, picture: $picture, backgroundId: $backgroundId, background: $background, accountId: $accountId, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, realmId: $realmId)'; } @@ -520,7 +522,7 @@ abstract mixin class _$SnPublisherCopyWith<$Res> implements $SnPublisherCopyWith factory _$SnPublisherCopyWith(_SnPublisher value, $Res Function(_SnPublisher) _then) = __$SnPublisherCopyWithImpl; @override @useResult $Res call({ - String id, int type, String name, String nick, String bio, String? pictureId, SnCloudFile? picture, String? backgroundId, SnCloudFile? background, String? accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt + String id, int type, String name, String nick, String bio, String? pictureId, SnCloudFile? picture, String? backgroundId, SnCloudFile? background, String? accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, String? realmId }); @@ -537,7 +539,7 @@ class __$SnPublisherCopyWithImpl<$Res> /// Create a copy of SnPublisher /// with the given fields replaced by the non-null parameter values. -@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? type = null,Object? name = null,Object? nick = null,Object? bio = null,Object? pictureId = freezed,Object? picture = freezed,Object? backgroundId = freezed,Object? background = freezed,Object? accountId = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) { +@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? type = null,Object? name = null,Object? nick = null,Object? bio = null,Object? pictureId = freezed,Object? picture = freezed,Object? backgroundId = freezed,Object? background = freezed,Object? accountId = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,Object? realmId = freezed,}) { return _then(_SnPublisher( id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable as String,type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable @@ -552,7 +554,8 @@ as SnCloudFile?,accountId: freezed == accountId ? _self.accountId : accountId // as String?,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable -as DateTime?, +as DateTime?,realmId: freezed == realmId ? _self.realmId : realmId // ignore: cast_nullable_to_non_nullable +as String?, )); } diff --git a/lib/models/post.g.dart b/lib/models/post.g.dart index f8beba5..a6a33ed 100644 --- a/lib/models/post.g.dart +++ b/lib/models/post.g.dart @@ -117,6 +117,7 @@ _SnPublisher _$SnPublisherFromJson(Map json) => _SnPublisher( json['deleted_at'] == null ? null : DateTime.parse(json['deleted_at'] as String), + realmId: json['realm_id'] as String?, ); Map _$SnPublisherToJson(_SnPublisher instance) => @@ -134,6 +135,7 @@ Map _$SnPublisherToJson(_SnPublisher instance) => 'created_at': instance.createdAt.toIso8601String(), 'updated_at': instance.updatedAt.toIso8601String(), 'deleted_at': instance.deletedAt?.toIso8601String(), + 'realm_id': instance.realmId, }; _SnPublisherStats _$SnPublisherStatsFromJson(Map json) => diff --git a/lib/screens/account/me/publishers.dart b/lib/screens/account/me/publishers.dart index 093ce36..40d2ac9 100644 --- a/lib/screens/account/me/publishers.dart +++ b/lib/screens/account/me/publishers.dart @@ -1,7 +1,7 @@ import 'package:auto_route/auto_route.dart'; +import 'package:collection/collection.dart'; import 'package:croppy/croppy.dart' hide cropImage; import 'package:dio/dio.dart'; -import 'package:dropdown_button2/dropdown_button2.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; @@ -18,6 +18,7 @@ import 'package:island/services/file.dart'; import 'package:island/widgets/alert.dart'; import 'package:island/widgets/app_scaffold.dart'; import 'package:island/widgets/content/cloud_files.dart'; +import 'package:island/widgets/realms/selection_dropdown.dart'; import 'package:material_symbols_icons/symbols.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; import 'package:styled_widget/styled_widget.dart'; @@ -268,6 +269,9 @@ class EditPublisherScreen extends HookConsumerWidget { nameController.text = publisher.value!.name; nickController.text = publisher.value!.nick; bioController.text = publisher.value!.bio; + currentRealm.value = joinedRealms.value?.firstWhereOrNull( + (realm) => realm.id == publisher.value!.realmId, + ); } return null; }, [publisher]); @@ -310,54 +314,18 @@ class EditPublisherScreen extends HookConsumerWidget { ), body: Column( children: [ - DropdownButtonHideUnderline( - child: DropdownButton2( - isExpanded: true, - hint: Text('realmSelection').tr(), - value: currentRealm.value, - items: [ - DropdownMenuItem( - value: null, - child: Row( - spacing: 12, - children: [ - CircleAvatar(radius: 16, child: Icon(Symbols.person)), - Text('publisherIndividual').tr(), - ], - ), - ), - ...joinedRealms.when( - data: - (realms) => - realms - .map( - (realm) => DropdownMenuItem( - value: realm, - child: Row( - spacing: 12, - children: [ - ProfilePictureWidget( - fileId: realm.pictureId, - fallbackIcon: Symbols.workspaces, - radius: 16, - ), - Text(realm.name), - ], - ), - ), - ) - .toList(), - loading: () => [], - error: (_, __) => [], - ), - ], - onChanged: (SnRealm? value) { - currentRealm.value = value; - }, - buttonStyleData: ButtonStyleData( - padding: const EdgeInsets.only(left: 4, right: 16), - ), + RealmSelectionDropdown( + value: currentRealm.value, + realms: joinedRealms.when( + data: (realms) => realms, + loading: () => [], + error: (_, __) => [], ), + onChanged: (SnRealm? value) { + currentRealm.value = value; + }, + isLoading: joinedRealms.isLoading, + error: joinedRealms.error?.toString(), ), AspectRatio( aspectRatio: 16 / 7, diff --git a/lib/screens/chat/chat.dart b/lib/screens/chat/chat.dart index 69ed800..eeb5424 100644 --- a/lib/screens/chat/chat.dart +++ b/lib/screens/chat/chat.dart @@ -1,4 +1,5 @@ import 'package:auto_route/auto_route.dart'; +import 'package:collection/collection.dart'; import 'package:croppy/croppy.dart' hide cropImage; import 'package:dio/dio.dart'; import 'package:easy_localization/easy_localization.dart'; @@ -10,14 +11,17 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:image_picker/image_picker.dart'; import 'package:island/models/chat.dart'; import 'package:island/models/file.dart'; +import 'package:island/models/realm.dart'; import 'package:island/pods/config.dart'; import 'package:island/pods/network.dart'; import 'package:island/route.gr.dart'; +import 'package:island/screens/realm/realms.dart'; import 'package:island/services/file.dart'; import 'package:island/widgets/account/account_picker.dart'; import 'package:island/widgets/alert.dart'; import 'package:island/widgets/app_scaffold.dart'; import 'package:island/widgets/content/cloud_files.dart'; +import 'package:island/widgets/realms/selection_dropdown.dart'; import 'package:material_symbols_icons/symbols.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; import 'package:styled_widget/styled_widget.dart'; @@ -34,6 +38,8 @@ Future> chatroomsJoined(Ref ref) async { .toList(); } +final chatFabKey = GlobalKey(); + @RoutePage() class ChatListScreen extends HookConsumerWidget { const ChatListScreen({super.key}); @@ -42,8 +48,6 @@ class ChatListScreen extends HookConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { final chats = ref.watch(chatroomsJoinedProvider); - final fabKey = useMemoized(() => GlobalKey(), []); - Future createDirectMessage() async { final result = await showModalBottomSheet( context: context, @@ -78,7 +82,7 @@ class ChatListScreen extends HookConsumerWidget { ), floatingActionButtonLocation: ExpandableFab.location, floatingActionButton: ExpandableFab( - key: fabKey, + key: chatFabKey, distance: 75, type: ExpandableFabType.up, childrenAnimation: ExpandableFabAnimation.none, @@ -88,7 +92,7 @@ class ChatListScreen extends HookConsumerWidget { ).colorScheme.surface.withAlpha((255 * 0.5).round()), ), openButtonBuilder: RotateFloatingActionButtonBuilder( - child: const Icon(Symbols.add, size: 28), + child: const Icon(Icons.add), fabSize: ExpandableFabSize.regular, foregroundColor: Theme.of(context).floatingActionButtonTheme.foregroundColor, @@ -96,8 +100,7 @@ class ChatListScreen extends HookConsumerWidget { Theme.of(context).floatingActionButtonTheme.backgroundColor, ), closeButtonBuilder: DefaultFloatingActionButtonBuilder( - heroTag: Key("chat-page-fab"), - child: const Icon(Symbols.close, size: 28), + child: const Icon(Icons.close), fabSize: ExpandableFabSize.regular, foregroundColor: Theme.of(context).floatingActionButtonTheme.foregroundColor, @@ -113,6 +116,7 @@ class ChatListScreen extends HookConsumerWidget { heroTag: null, tooltip: 'createChatRoom'.tr(), onPressed: () { + chatFabKey.currentState?.toggle(); context.pushRoute(NewChatRoute()).then((value) { if (value != null) { ref.invalidate(chatroomsJoinedProvider); @@ -130,7 +134,10 @@ class ChatListScreen extends HookConsumerWidget { FloatingActionButton( heroTag: null, tooltip: 'createDirectMessage'.tr(), - onPressed: createDirectMessage, + onPressed: () { + chatFabKey.currentState?.toggle(); + createDirectMessage(); + }, child: const Icon(Symbols.communication), ), ], @@ -234,12 +241,18 @@ class EditChatScreen extends HookConsumerWidget { final chat = ref.watch(chatroomProvider(id)); + final joinedRealms = ref.watch(realmsJoinedProvider); + final currentRealm = useState(null); + useEffect(() { if (chat.value != null) { nameController.text = chat.value!.name; descriptionController.text = chat.value!.description; picture.value = chat.value!.picture; background.value = chat.value!.background; + currentRealm.value = joinedRealms.value?.firstWhereOrNull( + (realm) => realm.id == chat.value!.realmId, + ); } return; }, [chat]); @@ -322,6 +335,7 @@ class EditChatScreen extends HookConsumerWidget { 'description': descriptionController.text, 'background_id': background.value?.id, 'picture_id': picture.value?.id, + 'realm_id': currentRealm.value?.id, }, options: Options(method: id == null ? 'POST' : 'PATCH'), ); @@ -342,6 +356,19 @@ class EditChatScreen extends HookConsumerWidget { ), body: Column( children: [ + RealmSelectionDropdown( + value: currentRealm.value, + realms: joinedRealms.when( + data: (realms) => realms, + loading: () => [], + error: (_, __) => [], + ), + onChanged: (SnRealm? value) { + currentRealm.value = value; + }, + isLoading: joinedRealms.isLoading, + error: joinedRealms.error?.toString(), + ), AspectRatio( aspectRatio: 16 / 7, child: Stack( diff --git a/lib/screens/chat/room.dart b/lib/screens/chat/room.dart index 6c485dd..a5f617e 100644 --- a/lib/screens/chat/room.dart +++ b/lib/screens/chat/room.dart @@ -470,6 +470,12 @@ class ChatRoomScreen extends HookConsumerWidget { error: (_, __) => const Text('Error'), ), actions: [ + IconButton( + icon: const Icon(Symbols.video_call), + onPressed: () { + showInfoAlert('Oops', 'Not implemented yet...'); + }, + ), IconButton( icon: const Icon(Icons.more_vert), onPressed: () { diff --git a/lib/widgets/alert.dart b/lib/widgets/alert.dart index 14a7e59..0952e02 100644 --- a/lib/widgets/alert.dart +++ b/lib/widgets/alert.dart @@ -53,7 +53,7 @@ void showLoadingModal(BuildContext context) { color: Colors.black54, child: Center( child: Material( - color: Colors.white, + color: Theme.of(context).colorScheme.surface, borderRadius: BorderRadius.circular(8), elevation: 4, child: Column( diff --git a/lib/widgets/realms/selection_dropdown.dart b/lib/widgets/realms/selection_dropdown.dart new file mode 100644 index 0000000..3c13f44 --- /dev/null +++ b/lib/widgets/realms/selection_dropdown.dart @@ -0,0 +1,70 @@ +import 'package:dropdown_button2/dropdown_button2.dart'; +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; +import 'package:island/models/realm.dart'; +import 'package:island/widgets/content/cloud_files.dart'; +import 'package:material_symbols_icons/symbols.dart'; + +class RealmSelectionDropdown extends StatelessWidget { + final SnRealm? value; + final List realms; + final ValueChanged onChanged; + final bool isLoading; + final String? error; + + const RealmSelectionDropdown({ + super.key, + required this.value, + required this.realms, + required this.onChanged, + this.isLoading = false, + this.error, + }); + + @override + Widget build(BuildContext context) { + return DropdownButtonHideUnderline( + child: DropdownButton2( + isExpanded: true, + hint: Text('realmSelection').tr(), + value: value, + items: [ + DropdownMenuItem( + value: null, + child: Row( + children: [ + const CircleAvatar( + radius: 16, + child: Icon(Symbols.person, fill: 1), + ), + const SizedBox(width: 12), + Text('individual').tr(), + ], + ), + ), + if (!isLoading && error == null) + ...realms.map( + (realm) => DropdownMenuItem( + value: realm, + child: Row( + children: [ + ProfilePictureWidget( + fileId: realm.pictureId, + fallbackIcon: Symbols.workspaces, + radius: 16, + ), + const SizedBox(width: 12), + Text(realm.name), + ], + ), + ), + ), + ], + onChanged: onChanged, + buttonStyleData: const ButtonStyleData( + padding: EdgeInsets.only(left: 4, right: 16), + ), + ), + ); + } +}