You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			145 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			Dart
		
	
			
		
		
	
	
			145 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			Dart
		
	
import 'dart:async';
 | 
						|
 | 
						|
import 'package:flutter/material.dart';
 | 
						|
 | 
						|
import 'package:adaptive_dialog/adaptive_dialog.dart';
 | 
						|
import 'package:flutter_gen/gen_l10n/l10n.dart';
 | 
						|
import 'package:flutter_linkify/flutter_linkify.dart';
 | 
						|
import 'package:matrix/matrix.dart';
 | 
						|
 | 
						|
import 'package:fluffychat/config/app_config.dart';
 | 
						|
import 'package:fluffychat/pages/chat/chat.dart';
 | 
						|
import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_locals.dart';
 | 
						|
import 'package:fluffychat/utils/url_launcher.dart';
 | 
						|
 | 
						|
class PinnedEvents extends StatelessWidget {
 | 
						|
  final ChatController controller;
 | 
						|
 | 
						|
  const PinnedEvents(this.controller, {Key? key}) : super(key: key);
 | 
						|
 | 
						|
  Future<void> _displayPinnedEventsDialog(
 | 
						|
    BuildContext context,
 | 
						|
    List<Event?> events,
 | 
						|
  ) async {
 | 
						|
    final eventId = events.length == 1
 | 
						|
        ? events.single?.eventId
 | 
						|
        : await showConfirmationDialog<String>(
 | 
						|
            context: context,
 | 
						|
            title: L10n.of(context)!.pinMessage,
 | 
						|
            actions: events
 | 
						|
                .map(
 | 
						|
                  (event) => AlertDialogAction(
 | 
						|
                    key: event?.eventId ?? '',
 | 
						|
                    label: event?.calcLocalizedBodyFallback(
 | 
						|
                          MatrixLocals(L10n.of(context)!),
 | 
						|
                          withSenderNamePrefix: true,
 | 
						|
                          hideReply: true,
 | 
						|
                        ) ??
 | 
						|
                        'UNKNOWN',
 | 
						|
                  ),
 | 
						|
                )
 | 
						|
                .toList(),
 | 
						|
          );
 | 
						|
 | 
						|
    if (eventId != null) controller.scrollToEventId(eventId);
 | 
						|
  }
 | 
						|
 | 
						|
  @override
 | 
						|
  Widget build(BuildContext context) {
 | 
						|
    final pinnedEventIds = controller.room.pinnedEventIds;
 | 
						|
 | 
						|
    if (pinnedEventIds.isEmpty) {
 | 
						|
      return const SizedBox.shrink();
 | 
						|
    }
 | 
						|
    final completers = pinnedEventIds.map<Completer<Event?>>((e) {
 | 
						|
      final completer = Completer<Event?>();
 | 
						|
      controller.room
 | 
						|
          .getEventById(e)
 | 
						|
          .then((value) => completer.complete(value));
 | 
						|
      return completer;
 | 
						|
    });
 | 
						|
    return FutureBuilder<List<Event?>>(
 | 
						|
      future: Future.wait(completers.map((e) => e.future).toList()),
 | 
						|
      builder: (context, snapshot) {
 | 
						|
        final pinnedEvents = snapshot.data;
 | 
						|
        final event = (pinnedEvents != null && pinnedEvents.isNotEmpty)
 | 
						|
            ? snapshot.data?.last
 | 
						|
            : null;
 | 
						|
 | 
						|
        if (event == null || pinnedEvents == null) {
 | 
						|
          return Container();
 | 
						|
        }
 | 
						|
 | 
						|
        final fontSize = AppConfig.messageFontSize * AppConfig.fontSizeFactor;
 | 
						|
        return Material(
 | 
						|
          color: Theme.of(context).colorScheme.surfaceVariant,
 | 
						|
          child: InkWell(
 | 
						|
            onTap: () => _displayPinnedEventsDialog(
 | 
						|
              context,
 | 
						|
              pinnedEvents,
 | 
						|
            ),
 | 
						|
            child: Row(
 | 
						|
              children: [
 | 
						|
                IconButton(
 | 
						|
                  splashRadius: 20,
 | 
						|
                  iconSize: 20,
 | 
						|
                  color: Theme.of(context).colorScheme.onSurfaceVariant,
 | 
						|
                  icon: const Icon(Icons.push_pin),
 | 
						|
                  tooltip: L10n.of(context)!.unpin,
 | 
						|
                  onPressed:
 | 
						|
                      controller.room.canSendEvent(EventTypes.RoomPinnedEvents)
 | 
						|
                          ? () => controller.unpinEvent(event.eventId)
 | 
						|
                          : null,
 | 
						|
                ),
 | 
						|
                Expanded(
 | 
						|
                  child: Padding(
 | 
						|
                    padding: const EdgeInsets.symmetric(horizontal: 4.0),
 | 
						|
                    child: FutureBuilder<String>(
 | 
						|
                      future: event.calcLocalizedBody(
 | 
						|
                        MatrixLocals(L10n.of(context)!),
 | 
						|
                        withSenderNamePrefix: true,
 | 
						|
                        hideReply: true,
 | 
						|
                      ),
 | 
						|
                      builder: (context, snapshot) {
 | 
						|
                        return Linkify(
 | 
						|
                          text: snapshot.data ??
 | 
						|
                              event.calcLocalizedBodyFallback(
 | 
						|
                                MatrixLocals(L10n.of(context)!),
 | 
						|
                                withSenderNamePrefix: true,
 | 
						|
                                hideReply: true,
 | 
						|
                              ),
 | 
						|
                          options: const LinkifyOptions(humanize: false),
 | 
						|
                          maxLines: 2,
 | 
						|
                          style: TextStyle(
 | 
						|
                            color:
 | 
						|
                                Theme.of(context).colorScheme.onSurfaceVariant,
 | 
						|
                            overflow: TextOverflow.ellipsis,
 | 
						|
                            fontSize: fontSize,
 | 
						|
                            decoration: event.redacted
 | 
						|
                                ? TextDecoration.lineThrough
 | 
						|
                                : null,
 | 
						|
                          ),
 | 
						|
                          linkStyle: TextStyle(
 | 
						|
                            color:
 | 
						|
                                Theme.of(context).colorScheme.onSurfaceVariant,
 | 
						|
                            fontSize: fontSize,
 | 
						|
                            decoration: TextDecoration.underline,
 | 
						|
                            decorationColor:
 | 
						|
                                Theme.of(context).colorScheme.onSurfaceVariant,
 | 
						|
                          ),
 | 
						|
                          onOpen: (url) =>
 | 
						|
                              UrlLauncher(context, url.url).launchUrl(),
 | 
						|
                        );
 | 
						|
                      },
 | 
						|
                    ),
 | 
						|
                  ),
 | 
						|
                ),
 | 
						|
              ],
 | 
						|
            ),
 | 
						|
          ),
 | 
						|
        );
 | 
						|
      },
 | 
						|
    );
 | 
						|
  }
 | 
						|
}
 |