Merge branch 'krille/better-chat-list-page' into 'main'

Krille/better chat list page

See merge request famedly/fluffychat!653
This commit is contained in:
Krille Fear 2021-12-30 09:17:02 +00:00
commit dc62c2aaa3
4 changed files with 97 additions and 134 deletions

View File

@ -2182,7 +2182,7 @@
"senderName": {} "senderName": {}
} }
}, },
"startYourFirstChat": "Start your first chat right now! 🙂\n- Tap on the message button\n- Enter the username of a friend\n- Have fun chatting", "startYourFirstChat": "Start your first chat right now! 🙂\n- Tap on 'New chat'\n- Scan the QR code of a friend\n- Have fun chatting",
"@startYourFirstChat": { "@startYourFirstChat": {
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}

View File

@ -1,5 +1,4 @@
import 'dart:async'; import 'dart:async';
import 'dart:math';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@ -284,10 +283,10 @@ class _ChatListViewBodyState extends State<_ChatListViewBody> {
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: <Widget>[ children: <Widget>[
const Icon( Image.asset(
Icons.maps_ugc_outlined, 'assets/private_chat_wallpaper.png',
size: 80, width: 160,
color: Colors.grey, height: 160,
), ),
Center( Center(
child: Text( child: Text(
@ -301,7 +300,7 @@ class _ChatListViewBodyState extends State<_ChatListViewBody> {
), ),
], ],
); );
} } else {
final displayStoriesHeader = widget.controller.activeSpaceId == null; final displayStoriesHeader = widget.controller.activeSpaceId == null;
child = ListView.builder( child = ListView.builder(
key: ValueKey(Matrix.of(context).client.userID.toString() + key: ValueKey(Matrix.of(context).client.userID.toString() +
@ -326,12 +325,65 @@ class _ChatListViewBodyState extends State<_ChatListViewBody> {
); );
}, },
); );
}
} else { } else {
child = ListView( const dummyChatCount = 8;
key: const ValueKey(false), final titleColor =
children: List.filled( Theme.of(context).textTheme.bodyText1.color.withAlpha(100);
8, final subtitleColor =
const _DummyChat(), Theme.of(context).textTheme.bodyText1.color.withAlpha(50);
child = ListView.builder(
itemCount: dummyChatCount,
itemBuilder: (context, i) => Opacity(
opacity: (dummyChatCount - i) / dummyChatCount,
child: ListTile(
leading: CircleAvatar(
backgroundColor: titleColor,
child: CircularProgressIndicator(
strokeWidth: 1,
color: Theme.of(context).textTheme.bodyText1.color,
),
),
title: Row(
children: [
Expanded(
child: Container(
height: 14,
decoration: BoxDecoration(
color: titleColor,
borderRadius: BorderRadius.circular(3),
),
),
),
const SizedBox(width: 36),
Container(
height: 14,
width: 14,
decoration: BoxDecoration(
color: subtitleColor,
borderRadius: BorderRadius.circular(14),
),
),
const SizedBox(width: 12),
Container(
height: 14,
width: 14,
decoration: BoxDecoration(
color: subtitleColor,
borderRadius: BorderRadius.circular(14),
),
),
],
),
subtitle: Container(
decoration: BoxDecoration(
color: subtitleColor,
borderRadius: BorderRadius.circular(3),
),
height: 12,
margin: const EdgeInsets.only(right: 22),
),
),
), ),
); );
} }
@ -389,100 +441,6 @@ class _ChatListViewBodyState extends State<_ChatListViewBody> {
} }
} }
class _DummyChat extends StatefulWidget {
const _DummyChat({Key key}) : super(key: key);
@override
State<_DummyChat> createState() => _DummyChatState();
}
class _DummyChatState extends State<_DummyChat> {
double opacity = Random().nextDouble();
Timer _timer;
static const duration = Duration(seconds: 1);
void _setRandomOpacity(_) {
if (mounted) {
setState(() => opacity = Random().nextDouble());
}
}
@override
void initState() {
WidgetsBinding.instance.addPostFrameCallback(_setRandomOpacity);
_timer ??= Timer.periodic(duration, _setRandomOpacity);
super.initState();
}
@override
void dispose() {
_timer?.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
final titleColor =
Theme.of(context).textTheme.bodyText1.color.withAlpha(100);
final subtitleColor =
Theme.of(context).textTheme.bodyText1.color.withAlpha(50);
return AnimatedOpacity(
opacity: opacity,
duration: duration,
child: ListTile(
leading: CircleAvatar(
backgroundColor: titleColor,
child: CircularProgressIndicator(
strokeWidth: 1,
color: Theme.of(context).textTheme.bodyText1.color,
),
),
title: Row(
children: [
Expanded(
child: Container(
height: 14,
decoration: BoxDecoration(
color: titleColor,
borderRadius: BorderRadius.circular(3),
),
),
),
const SizedBox(width: 36),
Container(
height: 14,
width: 14,
decoration: BoxDecoration(
color: subtitleColor,
borderRadius: BorderRadius.circular(14),
),
),
const SizedBox(width: 12),
Container(
height: 14,
width: 14,
decoration: BoxDecoration(
color: subtitleColor,
borderRadius: BorderRadius.circular(14),
),
),
],
),
subtitle: Container(
decoration: BoxDecoration(
color: subtitleColor,
borderRadius: BorderRadius.circular(3),
),
height: 12,
margin: const EdgeInsets.only(right: 22),
),
),
);
}
}
enum ChatListPopupMenuItemActions { enum ChatListPopupMenuItemActions {
createGroup, createGroup,
createSpace, createSpace,

View File

@ -112,8 +112,8 @@ class SearchController extends State<Search> {
@override @override
void initState() { void initState() {
super.initState(); super.initState();
controller.text = VRouter.of(context).queryParameters['query'] ?? '';
WidgetsBinding.instance?.addPostFrameCallback((_) async { WidgetsBinding.instance?.addPostFrameCallback((_) async {
controller.text = VRouter.of(context).queryParameters['query'] ?? '';
final server = await Store().getItem(_serverStoreNamespace) as String?; final server = await Store().getItem(_serverStoreNamespace) as String?;
if (server?.isNotEmpty ?? false) { if (server?.isNotEmpty ?? false) {
this.server = server; this.server = server;

View File

@ -87,6 +87,7 @@ class StoryView extends StatelessWidget {
child: PopupMenuButton<PopupStoryAction>( child: PopupMenuButton<PopupStoryAction>(
onSelected: controller.onPopupStoryAction, onSelected: controller.onPopupStoryAction,
itemBuilder: (context) => [ itemBuilder: (context) => [
if (controller.currentEvent?.canRedact ?? false)
PopupMenuItem( PopupMenuItem(
value: PopupStoryAction.delete, value: PopupStoryAction.delete,
child: Text(L10n.of(context)!.delete), child: Text(L10n.of(context)!.delete),
@ -336,6 +337,10 @@ class StoryView extends StatelessWidget {
child: SafeArea( child: SafeArea(
child: Center( child: Center(
child: OutlinedButton.icon( child: OutlinedButton.icon(
style: OutlinedButton.styleFrom(
backgroundColor:
Theme.of(context).colorScheme.surface,
),
onPressed: controller.displaySeenByUsers, onPressed: controller.displaySeenByUsers,
icon: const Icon( icon: const Icon(
Icons.visibility_outlined, Icons.visibility_outlined,