140 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			Dart
		
	
	
	
			
		
		
	
	
			140 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			Dart
		
	
	
	
| import 'package:flutter/material.dart';
 | |
| 
 | |
| import 'package:flutter_gen/gen_l10n/l10n.dart';
 | |
| import 'package:go_router/go_router.dart';
 | |
| import 'package:matrix/matrix.dart';
 | |
| 
 | |
| import 'package:fluffychat/config/themes.dart';
 | |
| import 'package:fluffychat/pages/chat/chat.dart';
 | |
| import 'package:fluffychat/utils/date_time_extension.dart';
 | |
| import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_locals.dart';
 | |
| import 'package:fluffychat/utils/sync_status_localization.dart';
 | |
| import 'package:fluffychat/widgets/avatar.dart';
 | |
| import 'package:fluffychat/widgets/presence_builder.dart';
 | |
| 
 | |
| class ChatAppBarTitle extends StatelessWidget {
 | |
|   final ChatController controller;
 | |
|   const ChatAppBarTitle(this.controller, {super.key});
 | |
| 
 | |
|   @override
 | |
|   Widget build(BuildContext context) {
 | |
|     final room = controller.room;
 | |
|     if (controller.selectedEvents.isNotEmpty) {
 | |
|       return Text(
 | |
|         controller.selectedEvents.length.toString(),
 | |
|         style: TextStyle(
 | |
|           color: Theme.of(context).colorScheme.tertiary,
 | |
|         ),
 | |
|       );
 | |
|     }
 | |
|     return InkWell(
 | |
|       hoverColor: Colors.transparent,
 | |
|       splashColor: Colors.transparent,
 | |
|       highlightColor: Colors.transparent,
 | |
|       onTap: controller.isArchived
 | |
|           ? null
 | |
|           : () => FluffyThemes.isThreeColumnMode(context)
 | |
|               ? controller.toggleDisplayChatDetailsColumn()
 | |
|               : context.go('/rooms/${room.id}/details'),
 | |
|       child: Row(
 | |
|         children: [
 | |
|           Hero(
 | |
|             tag: 'content_banner',
 | |
|             child: Avatar(
 | |
|               mxContent: room.avatar,
 | |
|               name: room.getLocalizedDisplayname(
 | |
|                 MatrixLocals(L10n.of(context)),
 | |
|               ),
 | |
|               size: 32,
 | |
|             ),
 | |
|           ),
 | |
|           const SizedBox(width: 12),
 | |
|           Expanded(
 | |
|             child: Column(
 | |
|               crossAxisAlignment: CrossAxisAlignment.start,
 | |
|               children: [
 | |
|                 Text(
 | |
|                   room.getLocalizedDisplayname(MatrixLocals(L10n.of(context))),
 | |
|                   maxLines: 1,
 | |
|                   overflow: TextOverflow.ellipsis,
 | |
|                   style: const TextStyle(
 | |
|                     fontSize: 16,
 | |
|                   ),
 | |
|                 ),
 | |
|                 StreamBuilder(
 | |
|                   stream: room.client.onSyncStatus.stream,
 | |
|                   builder: (context, snapshot) {
 | |
|                     final status = room.client.onSyncStatus.value ??
 | |
|                         const SyncStatusUpdate(SyncStatus.waitingForResponse);
 | |
|                     final hide = FluffyThemes.isColumnMode(context) ||
 | |
|                         (room.client.onSync.value != null &&
 | |
|                             status.status != SyncStatus.error &&
 | |
|                             room.client.prevBatch != null);
 | |
|                     return AnimatedSize(
 | |
|                       duration: FluffyThemes.animationDuration,
 | |
|                       child: hide
 | |
|                           ? PresenceBuilder(
 | |
|                               userId: room.directChatMatrixID,
 | |
|                               builder: (context, presence) {
 | |
|                                 final lastActiveTimestamp =
 | |
|                                     presence?.lastActiveTimestamp;
 | |
|                                 final style =
 | |
|                                     Theme.of(context).textTheme.bodySmall;
 | |
|                                 if (presence?.currentlyActive == true) {
 | |
|                                   return Text(
 | |
|                                     L10n.of(context).currentlyActive,
 | |
|                                     style: style,
 | |
|                                   );
 | |
|                                 }
 | |
|                                 if (lastActiveTimestamp != null) {
 | |
|                                   return Text(
 | |
|                                     L10n.of(context).lastActiveAgo(
 | |
|                                       lastActiveTimestamp
 | |
|                                           .localizedTimeShort(context),
 | |
|                                     ),
 | |
|                                     style: style,
 | |
|                                   );
 | |
|                                 }
 | |
|                                 return const SizedBox.shrink();
 | |
|                               },
 | |
|                             )
 | |
|                           : Row(
 | |
|                               children: [
 | |
|                                 SizedBox.square(
 | |
|                                   dimension: 10,
 | |
|                                   child: CircularProgressIndicator.adaptive(
 | |
|                                     strokeWidth: 1,
 | |
|                                     value: status.progress,
 | |
|                                     valueColor: status.error != null
 | |
|                                         ? AlwaysStoppedAnimation<Color>(
 | |
|                                             Theme.of(context).colorScheme.error,
 | |
|                                           )
 | |
|                                         : null,
 | |
|                                   ),
 | |
|                                 ),
 | |
|                                 const SizedBox(width: 4),
 | |
|                                 Expanded(
 | |
|                                   child: Text(
 | |
|                                     status.calcLocalizedString(context),
 | |
|                                     style: TextStyle(
 | |
|                                       fontSize: 12,
 | |
|                                       color: status.error != null
 | |
|                                           ? Theme.of(context).colorScheme.error
 | |
|                                           : null,
 | |
|                                     ),
 | |
|                                   ),
 | |
|                                 ),
 | |
|                               ],
 | |
|                             ),
 | |
|                     );
 | |
|                   },
 | |
|                 ),
 | |
|               ],
 | |
|             ),
 | |
|           ),
 | |
|         ],
 | |
|       ),
 | |
|     );
 | |
|   }
 | |
| }
 |