diff --git a/lib/database/drift_db.dart b/lib/database/drift_db.dart index 311d8994..b6ad2f1b 100644 --- a/lib/database/drift_db.dart +++ b/lib/database/drift_db.dart @@ -68,6 +68,10 @@ class AppDatabase extends _$AppDatabase { return (delete(chatMessages)..where((m) => m.id.equals(id))).go(); } + Future getTotalMessagesForRoom(String roomId) { + return (select(chatMessages)..where((m) => m.roomId.equals(roomId))).get().then((list) => list.length); + } + Future> searchMessages( String roomId, String query, diff --git a/lib/screens/account/leveling.dart b/lib/screens/account/leveling.dart index a771dbac..721c2cb4 100644 --- a/lib/screens/account/leveling.dart +++ b/lib/screens/account/leveling.dart @@ -95,8 +95,24 @@ class LevelingScreen extends HookConsumerWidget { title: Text('levelingProgress'.tr()), bottom: TabBar( tabs: [ - Tab(text: 'leveling'.tr()), - Tab(text: 'stellarProgram'.tr()), + Tab( + 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!, + ), + ), + ), ], ), ), diff --git a/lib/screens/chat/room.dart b/lib/screens/chat/room.dart index 24ec1554..62348d2c 100644 --- a/lib/screens/chat/room.dart +++ b/lib/screens/chat/room.dart @@ -355,17 +355,20 @@ class MessagesNotifier extends _$MessagesNotifier { offset: offset, limit: take, ); - dbMessages = chatMessagesFromDb.map(_database.companionToMessage).toList(); + dbMessages = + chatMessagesFromDb.map(_database.companionToMessage).toList(); } List filteredMessages = dbMessages; if (_withLinks == true) { - filteredMessages = filteredMessages.where((msg) => _hasLink(msg)).toList(); + filteredMessages = + filteredMessages.where((msg) => _hasLink(msg)).toList(); } if (_withAttachments == true) { - filteredMessages = filteredMessages.where((msg) => _hasAttachment(msg)).toList(); + filteredMessages = + filteredMessages.where((msg) => _hasAttachment(msg)).toList(); } final dbLocalMessages = filteredMessages; @@ -513,7 +516,9 @@ class MessagesNotifier extends _$MessagesNotifier { showErrorAlert(err); } finally { 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; } } @@ -524,7 +529,9 @@ class MessagesNotifier extends _$MessagesNotifier { bool synced = false, }) async { try { - if (offset == 0 && !synced && (_searchQuery == null || _searchQuery!.isEmpty)) { + if (offset == 0 && + !synced && + (_searchQuery == null || _searchQuery!.isEmpty)) { _fetchAndCacheMessages(offset: 0, take: take).catchError((_) { return []; }); @@ -584,7 +591,9 @@ class MessagesNotifier extends _$MessagesNotifier { _hasMore = false; } - state = AsyncValue.data(_sortMessages([...currentMessages, ...newMessages])); + state = AsyncValue.data( + _sortMessages([...currentMessages, ...newMessages]), + ); } catch (err, stackTrace) { developer.log( 'Error loading more messages', @@ -1481,12 +1490,6 @@ class ChatRoomScreen extends HookConsumerWidget { ), ), actions: [ - IconButton( - icon: const Icon(Icons.search), - onPressed: () { - context.pushNamed('searchMessages', pathParameters: {'id': id}); - }, - ), AudioCallButton(roomId: id), IconButton( icon: const Icon(Icons.more_vert), @@ -1496,14 +1499,15 @@ class ChatRoomScreen extends HookConsumerWidget { ), const Gap(8), ], - bottom: isSyncing - ? const PreferredSize( - preferredSize: Size.fromHeight(2), - child: LinearProgressIndicator( - borderRadius: BorderRadius.zero, - ), - ) - : null, + bottom: + isSyncing + ? const PreferredSize( + preferredSize: Size.fromHeight(2), + child: LinearProgressIndicator( + borderRadius: BorderRadius.zero, + ), + ) + : null, ), body: Stack( children: [ diff --git a/lib/screens/chat/room.g.dart b/lib/screens/chat/room.g.dart index 9889c234..079eae90 100644 --- a/lib/screens/chat/room.g.dart +++ b/lib/screens/chat/room.g.dart @@ -6,7 +6,7 @@ part of 'room.dart'; // RiverpodGenerator // ************************************************************************** -String _$messagesNotifierHash() => r'dda98f5bf525f3b2bc0a7c89bc6eaa3c8b95f142'; +String _$messagesNotifierHash() => r'fc3b66dfb8dd3fc55d142dae5c5e7bdc67eca5d4'; /// Copied from Dart SDK class _SystemHash { diff --git a/lib/screens/chat/room_detail.dart b/lib/screens/chat/room_detail.dart index 3981577b..8d3d7947 100644 --- a/lib/screens/chat/room_detail.dart +++ b/lib/screens/chat/room_detail.dart @@ -20,10 +20,17 @@ import 'package:material_symbols_icons/symbols.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; import 'package:riverpod_paging_utils/riverpod_paging_utils.dart'; import 'package:styled_widget/styled_widget.dart'; +import 'package:island/pods/database.dart'; part 'room_detail.freezed.dart'; part 'room_detail.g.dart'; +@riverpod +Future totalMessagesCount(Ref ref, String roomId) async { + final database = ref.watch(databaseProvider); + return database.getTotalMessagesForRoom(roomId); +} + class ChatDetailScreen extends HookConsumerWidget { final String id; const ChatDetailScreen({super.key, required this.id}); @@ -32,6 +39,7 @@ class ChatDetailScreen extends HookConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { final roomState = ref.watch(chatroomProvider(id)); final roomIdentity = ref.watch(chatroomIdentityProvider(id)); + final totalMessages = ref.watch(totalMessagesCountProvider(id)); const kNotifyLevelText = [ 'chatNotifyLevelAll', @@ -366,6 +374,11 @@ class ChatDetailScreen extends HookConsumerWidget { leading: const Icon(Icons.search), trailing: const Icon(Symbols.chevron_right), title: const Text('Search Messages').tr(), + subtitle: totalMessages.when( + data: (count) => Text('$count messages').tr(), + loading: () => const CircularProgressIndicator(), + error: (err, stack) => Text('Error: $err'), + ), onTap: () { context.pushNamed('searchMessages', pathParameters: {'id': id}); }, diff --git a/lib/screens/chat/room_detail.g.dart b/lib/screens/chat/room_detail.g.dart index 54b8247b..60685d83 100644 --- a/lib/screens/chat/room_detail.g.dart +++ b/lib/screens/chat/room_detail.g.dart @@ -6,8 +6,8 @@ part of 'room_detail.dart'; // RiverpodGenerator // ************************************************************************** -String _$chatMemberListNotifierHash() => - r'3ea30150278523e9f6b23f9200ea9a9fbae9c973'; +String _$totalMessagesCountHash() => + r'a15c03461f25c2d4d39c0926509bf626ae2550a6'; /// Copied from Dart SDK class _SystemHash { @@ -30,6 +30,128 @@ class _SystemHash { } } +/// See also [totalMessagesCount]. +@ProviderFor(totalMessagesCount) +const totalMessagesCountProvider = TotalMessagesCountFamily(); + +/// See also [totalMessagesCount]. +class TotalMessagesCountFamily extends Family> { + /// 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? _dependencies = null; + + @override + Iterable? get dependencies => _dependencies; + + static const Iterable? _allTransitiveDependencies = null; + + @override + Iterable? get allTransitiveDependencies => + _allTransitiveDependencies; + + @override + String? get name => r'totalMessagesCountProvider'; +} + +/// See also [totalMessagesCount]. +class TotalMessagesCountProvider extends AutoDisposeFutureProvider { + /// 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 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 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 { + /// The parameter `roomId` of this provider. + String get roomId; +} + +class _TotalMessagesCountProviderElement + extends AutoDisposeFutureProviderElement + with TotalMessagesCountRef { + _TotalMessagesCountProviderElement(super.provider); + + @override + String get roomId => (origin as TotalMessagesCountProvider).roomId; +} + +String _$chatMemberListNotifierHash() => + r'3ea30150278523e9f6b23f9200ea9a9fbae9c973'; + abstract class _$ChatMemberListNotifier extends BuildlessAutoDisposeAsyncNotifier> { late final String roomId; diff --git a/lib/screens/developers/app_detail.dart b/lib/screens/developers/app_detail.dart index 2d782b2e..67d1ef25 100644 --- a/lib/screens/developers/app_detail.dart +++ b/lib/screens/developers/app_detail.dart @@ -27,7 +27,9 @@ class AppDetailScreen extends HookConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { final tabController = useTabController(initialLength: 2); - final appData = ref.watch(customAppProvider(publisherName, projectId, appId)); + final appData = ref.watch( + customAppProvider(publisherName, projectId, appId), + ); return AppScaffold( appBar: AppBar( @@ -35,23 +37,43 @@ class AppDetailScreen extends HookConsumerWidget { actions: [ IconButton( icon: const Icon(Symbols.edit), - onPressed: appData.value == null - ? null - : () { - context.pushNamed( - 'developerAppEdit', - pathParameters: { - 'name': publisherName, - 'projectId': projectId, - 'id': appId, - }, - ); - }, + onPressed: + appData.value == null + ? null + : () { + context.pushNamed( + 'developerAppEdit', + pathParameters: { + 'name': publisherName, + 'projectId': projectId, + 'id': appId, + }, + ); + }, ), ], bottom: TabBar( 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( @@ -70,12 +92,14 @@ class AppDetailScreen extends HookConsumerWidget { ); }, loading: () => const Center(child: CircularProgressIndicator()), - error: (err, stack) => ResponseErrorWidget( - error: err, - onRetry: () => ref.invalidate( - customAppProvider(publisherName, projectId, appId), - ), - ), + error: + (err, stack) => ResponseErrorWidget( + error: err, + onRetry: + () => ref.invalidate( + customAppProvider(publisherName, projectId, appId), + ), + ), ), ); } @@ -98,12 +122,13 @@ class _AppOverview extends StatelessWidget { children: [ Container( color: Theme.of(context).colorScheme.surfaceContainer, - child: app.background != null - ? CloudFileWidget( - item: app.background!, - fit: BoxFit.cover, - ) - : const SizedBox.shrink(), + child: + app.background != null + ? CloudFileWidget( + item: app.background!, + fit: BoxFit.cover, + ) + : const SizedBox.shrink(), ), Positioned( left: 20, diff --git a/lib/screens/developers/bot_detail.dart b/lib/screens/developers/bot_detail.dart index a04dbb9e..6f632eb2 100644 --- a/lib/screens/developers/bot_detail.dart +++ b/lib/screens/developers/bot_detail.dart @@ -52,7 +52,26 @@ class BotDetailScreen extends HookConsumerWidget { ], bottom: TabBar( 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( diff --git a/lib/screens/developers/project_detail.dart b/lib/screens/developers/project_detail.dart index aef390ad..42371f4b 100644 --- a/lib/screens/developers/project_detail.dart +++ b/lib/screens/developers/project_detail.dart @@ -58,7 +58,26 @@ class ProjectDetailScreen extends HookConsumerWidget { ], bottom: TabBar( 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( diff --git a/lib/screens/discovery/articles.dart b/lib/screens/discovery/articles.dart index 8ce949c0..38a9508f 100644 --- a/lib/screens/discovery/articles.dart +++ b/lib/screens/discovery/articles.dart @@ -143,8 +143,26 @@ class ArticlesScreen extends ConsumerWidget { bottom: TabBar( isScrollable: true, tabs: [ - const Tab(text: 'All'), - ...feeds.map((feed) => Tab(text: feed.title)), + Tab( + 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!, + ), + ), + ), + ), ], ), ),