Compare commits
	
		
			3 Commits
		
	
	
		
			b48a1aac44
			...
			c9b71701c8
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| c9b71701c8 | |||
| 28e98488f1 | |||
| b4d476613e | 
| @@ -944,5 +944,21 @@ | |||||||
|   "unpinPostHint": "Are you sure you want to unpin this post?", |   "unpinPostHint": "Are you sure you want to unpin this post?", | ||||||
|   "all": "All", |   "all": "All", | ||||||
|   "statusPresent": "Present", |   "statusPresent": "Present", | ||||||
|   "accountAutomated": "Automated" |   "accountAutomated": "Automated", | ||||||
|  |   "chatBreakClearButton": "Clear", | ||||||
|  |   "chatBreak5m": "5m", | ||||||
|  |   "chatBreak10m": "10m", | ||||||
|  |   "chatBreak15m": "15m", | ||||||
|  |   "chatBreak30m": "30m", | ||||||
|  |   "chatBreakCustomMinutes": "Custom (minutes)", | ||||||
|  |   "chatBreakEnterMinutes": "Enter minutes", | ||||||
|  |   "errorGeneric": "Error: {}", | ||||||
|  |   "searchMessages": "Search Messages", | ||||||
|  |   "messagesCount": "{} messages", | ||||||
|  |   "dotSeparator": "·", | ||||||
|  |   "roleValidationHint": "Role must be between 0 and 100", | ||||||
|  |   "searchMessagesHint": "Search messages...", | ||||||
|  |   "searchLinks": "Links", | ||||||
|  |   "searchAttachments": "Attachments", | ||||||
|  |   "noMessagesFound": "No messages found" | ||||||
| } | } | ||||||
| @@ -68,6 +68,10 @@ class AppDatabase extends _$AppDatabase { | |||||||
|     return (delete(chatMessages)..where((m) => m.id.equals(id))).go(); |     return (delete(chatMessages)..where((m) => m.id.equals(id))).go(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   Future<int> getTotalMessagesForRoom(String roomId) { | ||||||
|  |     return (select(chatMessages)..where((m) => m.roomId.equals(roomId))).get().then((list) => list.length); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   Future<List<LocalChatMessage>> searchMessages( |   Future<List<LocalChatMessage>> searchMessages( | ||||||
|     String roomId, |     String roomId, | ||||||
|     String query, |     String query, | ||||||
|   | |||||||
| @@ -95,8 +95,24 @@ class LevelingScreen extends HookConsumerWidget { | |||||||
|           title: Text('levelingProgress'.tr()), |           title: Text('levelingProgress'.tr()), | ||||||
|           bottom: TabBar( |           bottom: TabBar( | ||||||
|             tabs: [ |             tabs: [ | ||||||
|               Tab(text: 'leveling'.tr()), |               Tab( | ||||||
|               Tab(text: 'stellarProgram'.tr()), |                 child: Text( | ||||||
|  |                   'leveling'.tr(), | ||||||
|  |                   textAlign: TextAlign.center, | ||||||
|  |                   style: TextStyle( | ||||||
|  |                     color: Theme.of(context).appBarTheme.foregroundColor!, | ||||||
|  |                   ), | ||||||
|  |                 ), | ||||||
|  |               ), | ||||||
|  |               Tab( | ||||||
|  |                 child: Text( | ||||||
|  |                   'stellarProgram'.tr(), | ||||||
|  |                   textAlign: TextAlign.center, | ||||||
|  |                   style: TextStyle( | ||||||
|  |                     color: Theme.of(context).appBarTheme.foregroundColor!, | ||||||
|  |                   ), | ||||||
|  |                 ), | ||||||
|  |               ), | ||||||
|             ], |             ], | ||||||
|           ), |           ), | ||||||
|         ), |         ), | ||||||
|   | |||||||
| @@ -355,17 +355,20 @@ class MessagesNotifier extends _$MessagesNotifier { | |||||||
|         offset: offset, |         offset: offset, | ||||||
|         limit: take, |         limit: take, | ||||||
|       ); |       ); | ||||||
|       dbMessages = chatMessagesFromDb.map(_database.companionToMessage).toList(); |       dbMessages = | ||||||
|  |           chatMessagesFromDb.map(_database.companionToMessage).toList(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     List<LocalChatMessage> filteredMessages = dbMessages; |     List<LocalChatMessage> filteredMessages = dbMessages; | ||||||
|  |  | ||||||
|     if (_withLinks == true) { |     if (_withLinks == true) { | ||||||
|       filteredMessages = filteredMessages.where((msg) => _hasLink(msg)).toList(); |       filteredMessages = | ||||||
|  |           filteredMessages.where((msg) => _hasLink(msg)).toList(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (_withAttachments == true) { |     if (_withAttachments == true) { | ||||||
|       filteredMessages = filteredMessages.where((msg) => _hasAttachment(msg)).toList(); |       filteredMessages = | ||||||
|  |           filteredMessages.where((msg) => _hasAttachment(msg)).toList(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     final dbLocalMessages = filteredMessages; |     final dbLocalMessages = filteredMessages; | ||||||
| @@ -513,7 +516,9 @@ class MessagesNotifier extends _$MessagesNotifier { | |||||||
|       showErrorAlert(err); |       showErrorAlert(err); | ||||||
|     } finally { |     } finally { | ||||||
|       developer.log('Finished message sync', name: 'MessagesNotifier'); |       developer.log('Finished message sync', name: 'MessagesNotifier'); | ||||||
|       Future.microtask(() => ref.read(isSyncingProvider.notifier).state = false); |       Future.microtask( | ||||||
|  |         () => ref.read(isSyncingProvider.notifier).state = false, | ||||||
|  |       ); | ||||||
|       _isSyncing = false; |       _isSyncing = false; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| @@ -524,7 +529,9 @@ class MessagesNotifier extends _$MessagesNotifier { | |||||||
|     bool synced = false, |     bool synced = false, | ||||||
|   }) async { |   }) async { | ||||||
|     try { |     try { | ||||||
|       if (offset == 0 && !synced && (_searchQuery == null || _searchQuery!.isEmpty)) { |       if (offset == 0 && | ||||||
|  |           !synced && | ||||||
|  |           (_searchQuery == null || _searchQuery!.isEmpty)) { | ||||||
|         _fetchAndCacheMessages(offset: 0, take: take).catchError((_) { |         _fetchAndCacheMessages(offset: 0, take: take).catchError((_) { | ||||||
|           return <LocalChatMessage>[]; |           return <LocalChatMessage>[]; | ||||||
|         }); |         }); | ||||||
| @@ -584,7 +591,9 @@ class MessagesNotifier extends _$MessagesNotifier { | |||||||
|         _hasMore = false; |         _hasMore = false; | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       state = AsyncValue.data(_sortMessages([...currentMessages, ...newMessages])); |       state = AsyncValue.data( | ||||||
|  |         _sortMessages([...currentMessages, ...newMessages]), | ||||||
|  |       ); | ||||||
|     } catch (err, stackTrace) { |     } catch (err, stackTrace) { | ||||||
|       developer.log( |       developer.log( | ||||||
|         'Error loading more messages', |         'Error loading more messages', | ||||||
| @@ -1481,12 +1490,6 @@ class ChatRoomScreen extends HookConsumerWidget { | |||||||
|               ), |               ), | ||||||
|         ), |         ), | ||||||
|         actions: [ |         actions: [ | ||||||
|           IconButton( |  | ||||||
|             icon: const Icon(Icons.search), |  | ||||||
|             onPressed: () { |  | ||||||
|               context.pushNamed('searchMessages', pathParameters: {'id': id}); |  | ||||||
|             }, |  | ||||||
|           ), |  | ||||||
|           AudioCallButton(roomId: id), |           AudioCallButton(roomId: id), | ||||||
|           IconButton( |           IconButton( | ||||||
|             icon: const Icon(Icons.more_vert), |             icon: const Icon(Icons.more_vert), | ||||||
| @@ -1496,7 +1499,8 @@ class ChatRoomScreen extends HookConsumerWidget { | |||||||
|           ), |           ), | ||||||
|           const Gap(8), |           const Gap(8), | ||||||
|         ], |         ], | ||||||
|         bottom: isSyncing |         bottom: | ||||||
|  |             isSyncing | ||||||
|                 ? const PreferredSize( |                 ? const PreferredSize( | ||||||
|                   preferredSize: Size.fromHeight(2), |                   preferredSize: Size.fromHeight(2), | ||||||
|                   child: LinearProgressIndicator( |                   child: LinearProgressIndicator( | ||||||
|   | |||||||
| @@ -6,7 +6,7 @@ part of 'room.dart'; | |||||||
| // RiverpodGenerator | // RiverpodGenerator | ||||||
| // ************************************************************************** | // ************************************************************************** | ||||||
|  |  | ||||||
| String _$messagesNotifierHash() => r'dda98f5bf525f3b2bc0a7c89bc6eaa3c8b95f142'; | String _$messagesNotifierHash() => r'fc3b66dfb8dd3fc55d142dae5c5e7bdc67eca5d4'; | ||||||
|  |  | ||||||
| /// Copied from Dart SDK | /// Copied from Dart SDK | ||||||
| class _SystemHash { | class _SystemHash { | ||||||
|   | |||||||
| @@ -20,10 +20,17 @@ 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:styled_widget/styled_widget.dart'; | import 'package:styled_widget/styled_widget.dart'; | ||||||
|  | import 'package:island/pods/database.dart'; | ||||||
|  |  | ||||||
| part 'room_detail.freezed.dart'; | part 'room_detail.freezed.dart'; | ||||||
| part 'room_detail.g.dart'; | part 'room_detail.g.dart'; | ||||||
|  |  | ||||||
|  | @riverpod | ||||||
|  | Future<int> totalMessagesCount(Ref ref, String roomId) async { | ||||||
|  |   final database = ref.watch(databaseProvider); | ||||||
|  |   return database.getTotalMessagesForRoom(roomId); | ||||||
|  | } | ||||||
|  |  | ||||||
| class ChatDetailScreen extends HookConsumerWidget { | class ChatDetailScreen extends HookConsumerWidget { | ||||||
|   final String id; |   final String id; | ||||||
|   const ChatDetailScreen({super.key, required this.id}); |   const ChatDetailScreen({super.key, required this.id}); | ||||||
| @@ -32,6 +39,7 @@ class ChatDetailScreen extends HookConsumerWidget { | |||||||
|   Widget build(BuildContext context, WidgetRef ref) { |   Widget build(BuildContext context, WidgetRef ref) { | ||||||
|     final roomState = ref.watch(chatroomProvider(id)); |     final roomState = ref.watch(chatroomProvider(id)); | ||||||
|     final roomIdentity = ref.watch(chatroomIdentityProvider(id)); |     final roomIdentity = ref.watch(chatroomIdentityProvider(id)); | ||||||
|  |     final totalMessages = ref.watch(totalMessagesCountProvider(id)); | ||||||
|  |  | ||||||
|     const kNotifyLevelText = [ |     const kNotifyLevelText = [ | ||||||
|       'chatNotifyLevelAll', |       'chatNotifyLevelAll', | ||||||
| @@ -132,7 +140,7 @@ class ChatDetailScreen extends HookConsumerWidget { | |||||||
|                   const Text('chatBreakDescription').tr(), |                   const Text('chatBreakDescription').tr(), | ||||||
|                   const Gap(16), |                   const Gap(16), | ||||||
|                   ListTile( |                   ListTile( | ||||||
|                     title: const Text('Clear').tr(), |                     title: const Text('chatBreakClearButton').tr(), | ||||||
|                     subtitle: const Text('chatBreakClear').tr(), |                     subtitle: const Text('chatBreakClear').tr(), | ||||||
|                     leading: const Icon(Icons.notifications_active), |                     leading: const Icon(Icons.notifications_active), | ||||||
|                     onTap: () { |                     onTap: () { | ||||||
| @@ -144,8 +152,8 @@ class ChatDetailScreen extends HookConsumerWidget { | |||||||
|                     }, |                     }, | ||||||
|                   ), |                   ), | ||||||
|                   ListTile( |                   ListTile( | ||||||
|                     title: const Text('5m'), |                     title: const Text('chatBreak5m').tr(), | ||||||
|                     subtitle: const Text('chatBreakHour').tr(args: ['5m']), |                     subtitle: const Text('chatBreakHour').tr(args: ['chatBreak5m'.tr()]), | ||||||
|                     leading: const Icon(Symbols.circle), |                     leading: const Icon(Symbols.circle), | ||||||
|                     onTap: () { |                     onTap: () { | ||||||
|                       setChatBreak(now.add(const Duration(minutes: 5))); |                       setChatBreak(now.add(const Duration(minutes: 5))); | ||||||
| @@ -156,8 +164,8 @@ class ChatDetailScreen extends HookConsumerWidget { | |||||||
|                     }, |                     }, | ||||||
|                   ), |                   ), | ||||||
|                   ListTile( |                   ListTile( | ||||||
|                     title: const Text('10m'), |                     title: const Text('chatBreak10m').tr(), | ||||||
|                     subtitle: const Text('chatBreakHour').tr(args: ['10m']), |                     subtitle: const Text('chatBreakHour').tr(args: ['chatBreak10m'.tr()]), | ||||||
|                     leading: const Icon(Symbols.circle), |                     leading: const Icon(Symbols.circle), | ||||||
|                     onTap: () { |                     onTap: () { | ||||||
|                       setChatBreak(now.add(const Duration(minutes: 10))); |                       setChatBreak(now.add(const Duration(minutes: 10))); | ||||||
| @@ -168,8 +176,8 @@ class ChatDetailScreen extends HookConsumerWidget { | |||||||
|                     }, |                     }, | ||||||
|                   ), |                   ), | ||||||
|                   ListTile( |                   ListTile( | ||||||
|                     title: const Text('15m'), |                     title: const Text('chatBreak15m').tr(), | ||||||
|                     subtitle: const Text('chatBreakHour').tr(args: ['15m']), |                     subtitle: const Text('chatBreakHour').tr(args: ['chatBreak15m'.tr()]), | ||||||
|                     leading: const Icon(Symbols.timer_3), |                     leading: const Icon(Symbols.timer_3), | ||||||
|                     onTap: () { |                     onTap: () { | ||||||
|                       setChatBreak(now.add(const Duration(minutes: 15))); |                       setChatBreak(now.add(const Duration(minutes: 15))); | ||||||
| @@ -180,8 +188,8 @@ class ChatDetailScreen extends HookConsumerWidget { | |||||||
|                     }, |                     }, | ||||||
|                   ), |                   ), | ||||||
|                   ListTile( |                   ListTile( | ||||||
|                     title: const Text('30m'), |                     title: const Text('chatBreak30m').tr(), | ||||||
|                     subtitle: const Text('chatBreakHour').tr(args: ['30m']), |                     subtitle: const Text('chatBreakHour').tr(args: ['chatBreak30m'.tr()]), | ||||||
|                     leading: const Icon(Symbols.timer), |                     leading: const Icon(Symbols.timer), | ||||||
|                     onTap: () { |                     onTap: () { | ||||||
|                       setChatBreak(now.add(const Duration(minutes: 30))); |                       setChatBreak(now.add(const Duration(minutes: 30))); | ||||||
| @@ -195,8 +203,8 @@ class ChatDetailScreen extends HookConsumerWidget { | |||||||
|                   TextField( |                   TextField( | ||||||
|                     controller: durationController, |                     controller: durationController, | ||||||
|                     decoration: InputDecoration( |                     decoration: InputDecoration( | ||||||
|                       labelText: 'Custom (minutes)'.tr(), |                       labelText: 'chatBreakCustomMinutes'.tr(), | ||||||
|                       hintText: 'Enter minutes'.tr(), |                       hintText: 'chatBreakEnterMinutes'.tr(), | ||||||
|                       border: const OutlineInputBorder(), |                       border: const OutlineInputBorder(), | ||||||
|                       suffixIcon: IconButton( |                       suffixIcon: IconButton( | ||||||
|                         icon: const Icon(Icons.check), |                         icon: const Icon(Icons.check), | ||||||
| @@ -239,7 +247,7 @@ class ChatDetailScreen extends HookConsumerWidget { | |||||||
|     return AppScaffold( |     return AppScaffold( | ||||||
|       body: roomState.when( |       body: roomState.when( | ||||||
|         loading: () => const Center(child: CircularProgressIndicator()), |         loading: () => const Center(child: CircularProgressIndicator()), | ||||||
|         error: (error, _) => Center(child: Text('Error: $error')), |         error: (error, _) => Center(child: Text('errorGeneric'.tr(args: [error.toString()]))), | ||||||
|         data: |         data: | ||||||
|             (currentRoom) => CustomScrollView( |             (currentRoom) => CustomScrollView( | ||||||
|               slivers: [ |               slivers: [ | ||||||
| @@ -365,7 +373,12 @@ class ChatDetailScreen extends HookConsumerWidget { | |||||||
|                                   ), |                                   ), | ||||||
|                                   leading: const Icon(Icons.search), |                                   leading: const Icon(Icons.search), | ||||||
|                                   trailing: const Icon(Symbols.chevron_right), |                                   trailing: const Icon(Symbols.chevron_right), | ||||||
|                                   title: const Text('Search Messages').tr(), |                                   title: const Text('searchMessages').tr(), | ||||||
|  |                                   subtitle: totalMessages.when( | ||||||
|  |                                     data: (count) => Text('messagesCount'.tr(args: [count.toString()])), | ||||||
|  |                                     loading: () => const CircularProgressIndicator(), | ||||||
|  |                                     error: (err, stack) => Text('errorGeneric'.tr(args: [err.toString()])), | ||||||
|  |                                   ), | ||||||
|                                   onTap: () { |                                   onTap: () { | ||||||
|                                     context.pushNamed('searchMessages', pathParameters: {'id': id}); |                                     context.pushNamed('searchMessages', pathParameters: {'id': id}); | ||||||
|                                   }, |                                   }, | ||||||
| @@ -703,7 +716,7 @@ class _ChatMemberListSheet extends HookConsumerWidget { | |||||||
|                                 ? 'permissionModerator' |                                 ? 'permissionModerator' | ||||||
|                                 : 'permissionMember', |                                 : 'permissionMember', | ||||||
|                           ).tr(), |                           ).tr(), | ||||||
|                           Text('·').bold().padding(horizontal: 6), |                           Text('dotSeparator').bold().padding(horizontal: 6), | ||||||
|                           Expanded(child: Text("@${member.account.name}")), |                           Expanded(child: Text("@${member.account.name}")), | ||||||
|                         ], |                         ], | ||||||
|                       ), |                       ), | ||||||
| @@ -863,7 +876,7 @@ class _ChatMemberRoleSheet extends HookConsumerWidget { | |||||||
|                     try { |                     try { | ||||||
|                       final newRole = int.parse(roleController.text); |                       final newRole = int.parse(roleController.text); | ||||||
|                       if (newRole < 0 || newRole > 100) { |                       if (newRole < 0 || newRole > 100) { | ||||||
|                         throw 'Role must be between 0 and 100'; |                         throw 'roleValidationHint'.tr(); | ||||||
|                       } |                       } | ||||||
|  |  | ||||||
|                       final apiClient = ref.read(apiClientProvider); |                       final apiClient = ref.read(apiClientProvider); | ||||||
|   | |||||||
| @@ -6,8 +6,8 @@ part of 'room_detail.dart'; | |||||||
| // RiverpodGenerator | // RiverpodGenerator | ||||||
| // ************************************************************************** | // ************************************************************************** | ||||||
|  |  | ||||||
| String _$chatMemberListNotifierHash() => | String _$totalMessagesCountHash() => | ||||||
|     r'3ea30150278523e9f6b23f9200ea9a9fbae9c973'; |     r'a15c03461f25c2d4d39c0926509bf626ae2550a6'; | ||||||
|  |  | ||||||
| /// Copied from Dart SDK | /// Copied from Dart SDK | ||||||
| class _SystemHash { | class _SystemHash { | ||||||
| @@ -30,6 +30,128 @@ class _SystemHash { | |||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /// See also [totalMessagesCount]. | ||||||
|  | @ProviderFor(totalMessagesCount) | ||||||
|  | const totalMessagesCountProvider = TotalMessagesCountFamily(); | ||||||
|  |  | ||||||
|  | /// See also [totalMessagesCount]. | ||||||
|  | class TotalMessagesCountFamily extends Family<AsyncValue<int>> { | ||||||
|  |   /// See also [totalMessagesCount]. | ||||||
|  |   const TotalMessagesCountFamily(); | ||||||
|  |  | ||||||
|  |   /// See also [totalMessagesCount]. | ||||||
|  |   TotalMessagesCountProvider call(String roomId) { | ||||||
|  |     return TotalMessagesCountProvider(roomId); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @override | ||||||
|  |   TotalMessagesCountProvider getProviderOverride( | ||||||
|  |     covariant TotalMessagesCountProvider provider, | ||||||
|  |   ) { | ||||||
|  |     return call(provider.roomId); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   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'totalMessagesCountProvider'; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /// See also [totalMessagesCount]. | ||||||
|  | class TotalMessagesCountProvider extends AutoDisposeFutureProvider<int> { | ||||||
|  |   /// See also [totalMessagesCount]. | ||||||
|  |   TotalMessagesCountProvider(String roomId) | ||||||
|  |     : this._internal( | ||||||
|  |         (ref) => totalMessagesCount(ref as TotalMessagesCountRef, roomId), | ||||||
|  |         from: totalMessagesCountProvider, | ||||||
|  |         name: r'totalMessagesCountProvider', | ||||||
|  |         debugGetCreateSourceHash: | ||||||
|  |             const bool.fromEnvironment('dart.vm.product') | ||||||
|  |                 ? null | ||||||
|  |                 : _$totalMessagesCountHash, | ||||||
|  |         dependencies: TotalMessagesCountFamily._dependencies, | ||||||
|  |         allTransitiveDependencies: | ||||||
|  |             TotalMessagesCountFamily._allTransitiveDependencies, | ||||||
|  |         roomId: roomId, | ||||||
|  |       ); | ||||||
|  |  | ||||||
|  |   TotalMessagesCountProvider._internal( | ||||||
|  |     super._createNotifier, { | ||||||
|  |     required super.name, | ||||||
|  |     required super.dependencies, | ||||||
|  |     required super.allTransitiveDependencies, | ||||||
|  |     required super.debugGetCreateSourceHash, | ||||||
|  |     required super.from, | ||||||
|  |     required this.roomId, | ||||||
|  |   }) : super.internal(); | ||||||
|  |  | ||||||
|  |   final String roomId; | ||||||
|  |  | ||||||
|  |   @override | ||||||
|  |   Override overrideWith( | ||||||
|  |     FutureOr<int> Function(TotalMessagesCountRef provider) create, | ||||||
|  |   ) { | ||||||
|  |     return ProviderOverride( | ||||||
|  |       origin: this, | ||||||
|  |       override: TotalMessagesCountProvider._internal( | ||||||
|  |         (ref) => create(ref as TotalMessagesCountRef), | ||||||
|  |         from: from, | ||||||
|  |         name: null, | ||||||
|  |         dependencies: null, | ||||||
|  |         allTransitiveDependencies: null, | ||||||
|  |         debugGetCreateSourceHash: null, | ||||||
|  |         roomId: roomId, | ||||||
|  |       ), | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @override | ||||||
|  |   AutoDisposeFutureProviderElement<int> createElement() { | ||||||
|  |     return _TotalMessagesCountProviderElement(this); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @override | ||||||
|  |   bool operator ==(Object other) { | ||||||
|  |     return other is TotalMessagesCountProvider && other.roomId == roomId; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @override | ||||||
|  |   int get hashCode { | ||||||
|  |     var hash = _SystemHash.combine(0, runtimeType.hashCode); | ||||||
|  |     hash = _SystemHash.combine(hash, roomId.hashCode); | ||||||
|  |  | ||||||
|  |     return _SystemHash.finish(hash); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @Deprecated('Will be removed in 3.0. Use Ref instead') | ||||||
|  | // ignore: unused_element | ||||||
|  | mixin TotalMessagesCountRef on AutoDisposeFutureProviderRef<int> { | ||||||
|  |   /// The parameter `roomId` of this provider. | ||||||
|  |   String get roomId; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | class _TotalMessagesCountProviderElement | ||||||
|  |     extends AutoDisposeFutureProviderElement<int> | ||||||
|  |     with TotalMessagesCountRef { | ||||||
|  |   _TotalMessagesCountProviderElement(super.provider); | ||||||
|  |  | ||||||
|  |   @override | ||||||
|  |   String get roomId => (origin as TotalMessagesCountProvider).roomId; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | String _$chatMemberListNotifierHash() => | ||||||
|  |     r'3ea30150278523e9f6b23f9200ea9a9fbae9c973'; | ||||||
|  |  | ||||||
| abstract class _$ChatMemberListNotifier | abstract class _$ChatMemberListNotifier | ||||||
|     extends BuildlessAutoDisposeAsyncNotifier<CursorPagingData<SnChatMember>> { |     extends BuildlessAutoDisposeAsyncNotifier<CursorPagingData<SnChatMember>> { | ||||||
|   late final String roomId; |   late final String roomId; | ||||||
|   | |||||||
| @@ -32,7 +32,7 @@ class SearchMessagesScreen extends HookConsumerWidget { | |||||||
|     }, []); |     }, []); | ||||||
|  |  | ||||||
|     return AppScaffold( |     return AppScaffold( | ||||||
|       appBar: AppBar(title: const Text('Search Messages')), |       appBar: AppBar(title: const Text('searchMessages').tr()), | ||||||
|       body: Column( |       body: Column( | ||||||
|         children: [ |         children: [ | ||||||
|           Column( |           Column( | ||||||
| @@ -40,7 +40,7 @@ class SearchMessagesScreen extends HookConsumerWidget { | |||||||
|               TextField( |               TextField( | ||||||
|                 controller: searchController, |                 controller: searchController, | ||||||
|                 decoration: InputDecoration( |                 decoration: InputDecoration( | ||||||
|                   hintText: 'Search messages...', |                   hintText: 'searchMessagesHint'.tr(), | ||||||
|                   border: InputBorder.none, |                   border: InputBorder.none, | ||||||
|                   isDense: true, |                   isDense: true, | ||||||
|                   contentPadding: EdgeInsets.only( |                   contentPadding: EdgeInsets.only( | ||||||
| @@ -72,7 +72,7 @@ class SearchMessagesScreen extends HookConsumerWidget { | |||||||
|                   Expanded( |                   Expanded( | ||||||
|                     child: CheckboxListTile( |                     child: CheckboxListTile( | ||||||
|                       secondary: const Icon(Symbols.link), |                       secondary: const Icon(Symbols.link), | ||||||
|                       title: const Text('Links'), |                       title: const Text('searchLinks').tr(), | ||||||
|                       value: withLinks.value, |                       value: withLinks.value, | ||||||
|                       onChanged: (bool? value) { |                       onChanged: (bool? value) { | ||||||
|                         withLinks.value = value!; |                         withLinks.value = value!; | ||||||
| @@ -87,7 +87,7 @@ class SearchMessagesScreen extends HookConsumerWidget { | |||||||
|                   Expanded( |                   Expanded( | ||||||
|                     child: CheckboxListTile( |                     child: CheckboxListTile( | ||||||
|                       secondary: const Icon(Symbols.file_copy), |                       secondary: const Icon(Symbols.file_copy), | ||||||
|                       title: const Text('Attachments'), |                       title: const Text('searchAttachments').tr(), | ||||||
|                       value: withAttachments.value, |                       value: withAttachments.value, | ||||||
|                       onChanged: (bool? value) { |                       onChanged: (bool? value) { | ||||||
|                         withAttachments.value = value!; |                         withAttachments.value = value!; | ||||||
| @@ -109,7 +109,7 @@ class SearchMessagesScreen extends HookConsumerWidget { | |||||||
|               data: |               data: | ||||||
|                   (messageList) => |                   (messageList) => | ||||||
|                       messageList.isEmpty |                       messageList.isEmpty | ||||||
|                           ? Center(child: Text('No messages found'.tr())) |                           ? Center(child: Text('noMessagesFound'.tr())) | ||||||
|                           : SuperListView.builder( |                           : SuperListView.builder( | ||||||
|                             padding: const EdgeInsets.symmetric(vertical: 16), |                             padding: const EdgeInsets.symmetric(vertical: 16), | ||||||
|                             reverse: true, // Show newest messages at the bottom |                             reverse: true, // Show newest messages at the bottom | ||||||
| @@ -129,7 +129,7 @@ class SearchMessagesScreen extends HookConsumerWidget { | |||||||
|                             }, |                             }, | ||||||
|                           ), |                           ), | ||||||
|               loading: () => const Center(child: CircularProgressIndicator()), |               loading: () => const Center(child: CircularProgressIndicator()), | ||||||
|               error: (error, _) => Center(child: Text('Error: $error')), |               error: (error, _) => Center(child: Text('errorGeneric'.tr(args: [error.toString()]))), | ||||||
|             ), |             ), | ||||||
|           ), |           ), | ||||||
|         ], |         ], | ||||||
|   | |||||||
| @@ -27,7 +27,9 @@ class AppDetailScreen extends HookConsumerWidget { | |||||||
|   @override |   @override | ||||||
|   Widget build(BuildContext context, WidgetRef ref) { |   Widget build(BuildContext context, WidgetRef ref) { | ||||||
|     final tabController = useTabController(initialLength: 2); |     final tabController = useTabController(initialLength: 2); | ||||||
|     final appData = ref.watch(customAppProvider(publisherName, projectId, appId)); |     final appData = ref.watch( | ||||||
|  |       customAppProvider(publisherName, projectId, appId), | ||||||
|  |     ); | ||||||
|  |  | ||||||
|     return AppScaffold( |     return AppScaffold( | ||||||
|       appBar: AppBar( |       appBar: AppBar( | ||||||
| @@ -35,7 +37,8 @@ class AppDetailScreen extends HookConsumerWidget { | |||||||
|         actions: [ |         actions: [ | ||||||
|           IconButton( |           IconButton( | ||||||
|             icon: const Icon(Symbols.edit), |             icon: const Icon(Symbols.edit), | ||||||
|             onPressed: appData.value == null |             onPressed: | ||||||
|  |                 appData.value == null | ||||||
|                     ? null |                     ? null | ||||||
|                     : () { |                     : () { | ||||||
|                       context.pushNamed( |                       context.pushNamed( | ||||||
| @@ -51,7 +54,26 @@ class AppDetailScreen extends HookConsumerWidget { | |||||||
|         ], |         ], | ||||||
|         bottom: TabBar( |         bottom: TabBar( | ||||||
|           controller: tabController, |           controller: tabController, | ||||||
|           tabs: [Tab(text: 'overview'.tr()), Tab(text: 'secrets'.tr())], |           tabs: [ | ||||||
|  |             Tab( | ||||||
|  |               child: Text( | ||||||
|  |                 'overview'.tr(), | ||||||
|  |                 textAlign: TextAlign.center, | ||||||
|  |                 style: TextStyle( | ||||||
|  |                   color: Theme.of(context).appBarTheme.foregroundColor!, | ||||||
|  |                 ), | ||||||
|  |               ), | ||||||
|  |             ), | ||||||
|  |             Tab( | ||||||
|  |               child: Text( | ||||||
|  |                 'secrets'.tr(), | ||||||
|  |                 textAlign: TextAlign.center, | ||||||
|  |                 style: TextStyle( | ||||||
|  |                   color: Theme.of(context).appBarTheme.foregroundColor!, | ||||||
|  |                 ), | ||||||
|  |               ), | ||||||
|  |             ), | ||||||
|  |           ], | ||||||
|         ), |         ), | ||||||
|       ), |       ), | ||||||
|       body: appData.when( |       body: appData.when( | ||||||
| @@ -70,9 +92,11 @@ class AppDetailScreen extends HookConsumerWidget { | |||||||
|           ); |           ); | ||||||
|         }, |         }, | ||||||
|         loading: () => const Center(child: CircularProgressIndicator()), |         loading: () => const Center(child: CircularProgressIndicator()), | ||||||
|         error: (err, stack) => ResponseErrorWidget( |         error: | ||||||
|  |             (err, stack) => ResponseErrorWidget( | ||||||
|               error: err, |               error: err, | ||||||
|           onRetry: () => ref.invalidate( |               onRetry: | ||||||
|  |                   () => ref.invalidate( | ||||||
|                     customAppProvider(publisherName, projectId, appId), |                     customAppProvider(publisherName, projectId, appId), | ||||||
|                   ), |                   ), | ||||||
|             ), |             ), | ||||||
| @@ -98,7 +122,8 @@ class _AppOverview extends StatelessWidget { | |||||||
|               children: [ |               children: [ | ||||||
|                 Container( |                 Container( | ||||||
|                   color: Theme.of(context).colorScheme.surfaceContainer, |                   color: Theme.of(context).colorScheme.surfaceContainer, | ||||||
|                   child: app.background != null |                   child: | ||||||
|  |                       app.background != null | ||||||
|                           ? CloudFileWidget( |                           ? CloudFileWidget( | ||||||
|                             item: app.background!, |                             item: app.background!, | ||||||
|                             fit: BoxFit.cover, |                             fit: BoxFit.cover, | ||||||
|   | |||||||
| @@ -52,7 +52,26 @@ class BotDetailScreen extends HookConsumerWidget { | |||||||
|         ], |         ], | ||||||
|         bottom: TabBar( |         bottom: TabBar( | ||||||
|           controller: tabController, |           controller: tabController, | ||||||
|           tabs: [Tab(text: 'overview'.tr()), Tab(text: 'keys'.tr())], |           tabs: [ | ||||||
|  |             Tab( | ||||||
|  |               child: Text( | ||||||
|  |                 'overview'.tr(), | ||||||
|  |                 textAlign: TextAlign.center, | ||||||
|  |                 style: TextStyle( | ||||||
|  |                   color: Theme.of(context).appBarTheme.foregroundColor!, | ||||||
|  |                 ), | ||||||
|  |               ), | ||||||
|  |             ), | ||||||
|  |             Tab( | ||||||
|  |               child: Text( | ||||||
|  |                 'keys'.tr(), | ||||||
|  |                 textAlign: TextAlign.center, | ||||||
|  |                 style: TextStyle( | ||||||
|  |                   color: Theme.of(context).appBarTheme.foregroundColor!, | ||||||
|  |                 ), | ||||||
|  |               ), | ||||||
|  |             ), | ||||||
|  |           ], | ||||||
|         ), |         ), | ||||||
|       ), |       ), | ||||||
|       body: botData.when( |       body: botData.when( | ||||||
|   | |||||||
| @@ -58,7 +58,26 @@ class ProjectDetailScreen extends HookConsumerWidget { | |||||||
|         ], |         ], | ||||||
|         bottom: TabBar( |         bottom: TabBar( | ||||||
|           controller: tabController, |           controller: tabController, | ||||||
|           tabs: [Tab(text: 'customApps'.tr()), Tab(text: 'bots'.tr())], |           tabs: [ | ||||||
|  |             Tab( | ||||||
|  |               child: Text( | ||||||
|  |                 'customApps'.tr(), | ||||||
|  |                 textAlign: TextAlign.center, | ||||||
|  |                 style: TextStyle( | ||||||
|  |                   color: Theme.of(context).appBarTheme.foregroundColor!, | ||||||
|  |                 ), | ||||||
|  |               ), | ||||||
|  |             ), | ||||||
|  |             Tab( | ||||||
|  |               child: Text( | ||||||
|  |                 'bots'.tr(), | ||||||
|  |                 textAlign: TextAlign.center, | ||||||
|  |                 style: TextStyle( | ||||||
|  |                   color: Theme.of(context).appBarTheme.foregroundColor!, | ||||||
|  |                 ), | ||||||
|  |               ), | ||||||
|  |             ), | ||||||
|  |           ], | ||||||
|         ), |         ), | ||||||
|       ), |       ), | ||||||
|       body: TabBarView( |       body: TabBarView( | ||||||
|   | |||||||
| @@ -143,8 +143,26 @@ class ArticlesScreen extends ConsumerWidget { | |||||||
|               bottom: TabBar( |               bottom: TabBar( | ||||||
|                 isScrollable: true, |                 isScrollable: true, | ||||||
|                 tabs: [ |                 tabs: [ | ||||||
|                   const Tab(text: 'All'), |                   Tab( | ||||||
|                   ...feeds.map((feed) => Tab(text: feed.title)), |                     child: Text( | ||||||
|  |                       'All', | ||||||
|  |                       textAlign: TextAlign.center, | ||||||
|  |                       style: TextStyle( | ||||||
|  |                         color: Theme.of(context).appBarTheme.foregroundColor!, | ||||||
|  |                       ), | ||||||
|  |                     ), | ||||||
|  |                   ), | ||||||
|  |                   ...feeds.map( | ||||||
|  |                     (feed) => Tab( | ||||||
|  |                       child: Text( | ||||||
|  |                         feed.title, | ||||||
|  |                         textAlign: TextAlign.center, | ||||||
|  |                         style: TextStyle( | ||||||
|  |                           color: Theme.of(context).appBarTheme.foregroundColor!, | ||||||
|  |                         ), | ||||||
|  |                       ), | ||||||
|  |                     ), | ||||||
|  |                   ), | ||||||
|                 ], |                 ], | ||||||
|               ), |               ), | ||||||
|             ), |             ), | ||||||
|   | |||||||
| @@ -16,7 +16,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev | |||||||
| # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html | # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html | ||||||
| # In Windows, build-name is used as the major, minor, and patch parts | # In Windows, build-name is used as the major, minor, and patch parts | ||||||
| # of the product and file versions while build-number is used as the build suffix. | # of the product and file versions while build-number is used as the build suffix. | ||||||
| version: 3.2.0+128 | version: 3.2.0+129 | ||||||
|  |  | ||||||
| environment: | environment: | ||||||
|   sdk: ^3.7.2 |   sdk: ^3.7.2 | ||||||
| @@ -139,6 +139,7 @@ dependencies: | |||||||
|   material_color_utilities: ^0.11.1 |   material_color_utilities: ^0.11.1 | ||||||
|   screenshot: ^3.0.0 |   screenshot: ^3.0.0 | ||||||
|   flutter_card_swiper: ^7.0.2 |   flutter_card_swiper: ^7.0.2 | ||||||
|  |   file_saver: ^0.3.1 | ||||||
|  |  | ||||||
| dev_dependencies: | dev_dependencies: | ||||||
|   flutter_test: |   flutter_test: | ||||||
| @@ -236,3 +237,4 @@ msix_config: | |||||||
|   msix_version: 3.2.0.0 |   msix_version: 3.2.0.0 | ||||||
|   logo_path: .\assets\icons\icon.png |   logo_path: .\assets\icons\icon.png | ||||||
|   capabilities: internetClientServer, location, microphone, webcam |   capabilities: internetClientServer, location, microphone, webcam | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user