feat: new design
							parent
							
								
									7355d6609d
								
							
						
					
					
						commit
						22fdb667ba
					
				@ -0,0 +1,98 @@
 | 
			
		||||
import 'dart:convert';
 | 
			
		||||
 | 
			
		||||
import 'package:flutter/material.dart';
 | 
			
		||||
 | 
			
		||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
 | 
			
		||||
import 'package:matrix/matrix.dart';
 | 
			
		||||
 | 
			
		||||
import 'package:fluffychat/utils/date_time_extension.dart';
 | 
			
		||||
import 'package:fluffychat/widgets/avatar.dart';
 | 
			
		||||
 | 
			
		||||
extension EventInfoDialogExtension on Event {
 | 
			
		||||
  void showInfoDialog(BuildContext context) => showModalBottomSheet(
 | 
			
		||||
        context: context,
 | 
			
		||||
        builder: (context) =>
 | 
			
		||||
            EventInfoDialog(l10n: L10n.of(context), event: this),
 | 
			
		||||
      );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class EventInfoDialog extends StatelessWidget {
 | 
			
		||||
  final Event event;
 | 
			
		||||
  final L10n l10n;
 | 
			
		||||
  const EventInfoDialog({
 | 
			
		||||
    @required this.event,
 | 
			
		||||
    @required this.l10n,
 | 
			
		||||
    Key key,
 | 
			
		||||
  }) : super(key: key);
 | 
			
		||||
 | 
			
		||||
  String get prettyJson {
 | 
			
		||||
    const JsonDecoder decoder = JsonDecoder();
 | 
			
		||||
    const JsonEncoder encoder = JsonEncoder.withIndent('  ');
 | 
			
		||||
    final object = decoder.convert(jsonEncode(event.toJson()));
 | 
			
		||||
    return encoder.convert(object);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
    return Scaffold(
 | 
			
		||||
      appBar: AppBar(
 | 
			
		||||
        title: Text(L10n.of(context).messageInfo),
 | 
			
		||||
        leading: IconButton(
 | 
			
		||||
          icon: const Icon(Icons.arrow_downward_outlined),
 | 
			
		||||
          onPressed: Navigator.of(context, rootNavigator: false).pop,
 | 
			
		||||
          tooltip: L10n.of(context).close,
 | 
			
		||||
        ),
 | 
			
		||||
      ),
 | 
			
		||||
      body: ListView(
 | 
			
		||||
        children: [
 | 
			
		||||
          ListTile(
 | 
			
		||||
            leading:
 | 
			
		||||
                Avatar(event.sender.avatarUrl, event.sender.calcDisplayname()),
 | 
			
		||||
            title: Text(L10n.of(context).sender),
 | 
			
		||||
            subtitle:
 | 
			
		||||
                Text('${event.sender.calcDisplayname()} <${event.senderId}>'),
 | 
			
		||||
          ),
 | 
			
		||||
          ListTile(
 | 
			
		||||
            title: Text(L10n.of(context).time),
 | 
			
		||||
            subtitle: Text(event.originServerTs.localizedTime(context)),
 | 
			
		||||
          ),
 | 
			
		||||
          ListTile(
 | 
			
		||||
            title: Text(L10n.of(context).messageType),
 | 
			
		||||
            subtitle: Text(event.humanreadableType),
 | 
			
		||||
          ),
 | 
			
		||||
          ListTile(
 | 
			
		||||
            title: Text(L10n.of(context).sourceCode),
 | 
			
		||||
          ),
 | 
			
		||||
          Padding(
 | 
			
		||||
            padding: const EdgeInsets.all(12.0),
 | 
			
		||||
            child: SingleChildScrollView(
 | 
			
		||||
              scrollDirection: Axis.horizontal,
 | 
			
		||||
              child: Text(
 | 
			
		||||
                prettyJson,
 | 
			
		||||
                style: const TextStyle(
 | 
			
		||||
                  fontFamily: 'Roboto-Mono',
 | 
			
		||||
                  fontSize: 16,
 | 
			
		||||
                ),
 | 
			
		||||
              ),
 | 
			
		||||
            ),
 | 
			
		||||
          ),
 | 
			
		||||
        ],
 | 
			
		||||
      ),
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
extension on Event {
 | 
			
		||||
  String get humanreadableType {
 | 
			
		||||
    if (type == EventTypes.Message) {
 | 
			
		||||
      return messageType.split('m.').last;
 | 
			
		||||
    }
 | 
			
		||||
    if (type.startsWith('m.room.')) {
 | 
			
		||||
      return type.split('m.room.').last;
 | 
			
		||||
    }
 | 
			
		||||
    if (type.startsWith('m.')) {
 | 
			
		||||
      return type.split('m.').last;
 | 
			
		||||
    }
 | 
			
		||||
    return type;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,68 @@
 | 
			
		||||
import 'package:flutter/material.dart';
 | 
			
		||||
 | 
			
		||||
import 'package:fluffychat/pages/chat/chat.dart';
 | 
			
		||||
import 'package:fluffychat/utils/room_status_extension.dart';
 | 
			
		||||
import 'package:fluffychat/widgets/avatar.dart';
 | 
			
		||||
import 'package:fluffychat/widgets/matrix.dart';
 | 
			
		||||
 | 
			
		||||
class SeenByRow extends StatelessWidget {
 | 
			
		||||
  final ChatController controller;
 | 
			
		||||
  const SeenByRow(this.controller, {Key key}) : super(key: key);
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
    final seenByUsers = controller.room.getSeenByUsers(
 | 
			
		||||
      controller.timeline,
 | 
			
		||||
      controller.filteredEvents,
 | 
			
		||||
      controller.unfolded,
 | 
			
		||||
    );
 | 
			
		||||
    const maxAvatars = 7;
 | 
			
		||||
    return AnimatedContainer(
 | 
			
		||||
      height: seenByUsers.isEmpty ? 0 : 24,
 | 
			
		||||
      duration: seenByUsers.isEmpty
 | 
			
		||||
          ? const Duration(milliseconds: 0)
 | 
			
		||||
          : const Duration(milliseconds: 300),
 | 
			
		||||
      alignment: controller.filteredEvents.isNotEmpty &&
 | 
			
		||||
              controller.filteredEvents.first.senderId ==
 | 
			
		||||
                  Matrix.of(context).client.userID
 | 
			
		||||
          ? Alignment.topRight
 | 
			
		||||
          : Alignment.topLeft,
 | 
			
		||||
      padding: const EdgeInsets.only(
 | 
			
		||||
        left: 16,
 | 
			
		||||
        right: 16,
 | 
			
		||||
        bottom: 4,
 | 
			
		||||
      ),
 | 
			
		||||
      child: Wrap(
 | 
			
		||||
        spacing: 4,
 | 
			
		||||
        children: [
 | 
			
		||||
          ...(seenByUsers.length > maxAvatars
 | 
			
		||||
                  ? seenByUsers.sublist(0, maxAvatars)
 | 
			
		||||
                  : seenByUsers)
 | 
			
		||||
              .map(
 | 
			
		||||
                (user) => Avatar(
 | 
			
		||||
                  user.avatarUrl,
 | 
			
		||||
                  user.calcDisplayname(),
 | 
			
		||||
                  size: 16,
 | 
			
		||||
                ),
 | 
			
		||||
              )
 | 
			
		||||
              .toList(),
 | 
			
		||||
          if (seenByUsers.length > maxAvatars)
 | 
			
		||||
            SizedBox(
 | 
			
		||||
              width: 16,
 | 
			
		||||
              height: 16,
 | 
			
		||||
              child: Material(
 | 
			
		||||
                color: Theme.of(context).backgroundColor,
 | 
			
		||||
                borderRadius: BorderRadius.circular(32),
 | 
			
		||||
                child: Center(
 | 
			
		||||
                  child: Text(
 | 
			
		||||
                    '+${seenByUsers.length - maxAvatars}',
 | 
			
		||||
                    style: const TextStyle(fontSize: 10),
 | 
			
		||||
                  ),
 | 
			
		||||
                ),
 | 
			
		||||
              ),
 | 
			
		||||
            ),
 | 
			
		||||
        ],
 | 
			
		||||
      ),
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
					Loading…
					
					
				
		Reference in New Issue