horrible implementation of thread list in room
This commit is contained in:
parent
1757a7a4af
commit
0f5c19b0ce
|
|
@ -1,6 +1,5 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:extera_next/pages/chat_thread/chat_threads.dart';
|
||||
import 'package:extera_next/pages/chat_thread/thread.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
|
|
@ -153,13 +152,6 @@ abstract class AppRoutes {
|
|||
routes: [
|
||||
GoRoute(
|
||||
path: 'threads',
|
||||
pageBuilder: (context, state) => defaultPageBuilder(
|
||||
context,
|
||||
state,
|
||||
ChatThreads(
|
||||
roomId: state.pathParameters['roomid']!,
|
||||
),
|
||||
),
|
||||
redirect: loggedOutRedirect,
|
||||
routes: [
|
||||
GoRoute(
|
||||
|
|
@ -377,6 +369,7 @@ abstract class AppRoutes {
|
|||
roomId: state.pathParameters['roomid']!,
|
||||
shareItems: shareItems,
|
||||
eventId: state.uri.queryParameters['event'],
|
||||
showThreadRoots: state.uri.queryParameters['threads'] == 'true',
|
||||
),
|
||||
);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -51,12 +51,14 @@ class ChatPage extends StatelessWidget {
|
|||
final String roomId;
|
||||
final List<ShareItem>? shareItems;
|
||||
final String? eventId;
|
||||
final bool? showThreadRoots;
|
||||
|
||||
const ChatPage({
|
||||
super.key,
|
||||
required this.roomId,
|
||||
this.eventId,
|
||||
this.shareItems,
|
||||
this.showThreadRoots,
|
||||
});
|
||||
|
||||
@override
|
||||
|
|
@ -79,6 +81,7 @@ class ChatPage extends StatelessWidget {
|
|||
room: room,
|
||||
shareItems: shareItems,
|
||||
eventId: eventId,
|
||||
showThreadRoots: showThreadRoots,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -88,6 +91,7 @@ class ChatPageWithRoom extends StatefulWidget {
|
|||
final Thread? thread;
|
||||
final List<ShareItem>? shareItems;
|
||||
final String? eventId;
|
||||
final bool? showThreadRoots;
|
||||
|
||||
const ChatPageWithRoom({
|
||||
super.key,
|
||||
|
|
@ -95,6 +99,7 @@ class ChatPageWithRoom extends StatefulWidget {
|
|||
this.thread,
|
||||
this.shareItems,
|
||||
this.eventId,
|
||||
this.showThreadRoots,
|
||||
});
|
||||
|
||||
@override
|
||||
|
|
@ -104,6 +109,7 @@ class ChatPageWithRoom extends StatefulWidget {
|
|||
class ChatController extends State<ChatPageWithRoom>
|
||||
with WidgetsBindingObserver {
|
||||
Room get room => sendingClient.getRoomById(roomId) ?? widget.room;
|
||||
bool get showThreadRoots => (widget.showThreadRoots ?? false);
|
||||
Thread? get thread =>
|
||||
sendingClient.getRoomById(roomId)?.threads[threadRootEventId] ??
|
||||
widget.room.threads[threadRootEventId];
|
||||
|
|
|
|||
|
|
@ -15,10 +15,12 @@ import 'package:extera_next/utils/platform_infos.dart';
|
|||
|
||||
class ChatEventList extends StatelessWidget {
|
||||
final ChatController controller;
|
||||
final bool showThreadRoots;
|
||||
|
||||
const ChatEventList({
|
||||
super.key,
|
||||
required this.controller,
|
||||
this.showThreadRoots = false,
|
||||
});
|
||||
|
||||
@override
|
||||
|
|
@ -37,7 +39,14 @@ class ChatEventList extends StatelessWidget {
|
|||
|
||||
final horizontalPadding = FluffyThemes.isColumnMode(context) ? 8.0 : 0.0;
|
||||
|
||||
final events = timeline.events.filterByVisibleInGui().filterByThreaded(controller.thread != null);
|
||||
var events = timeline.events.filterByVisibleInGui();
|
||||
|
||||
if (showThreadRoots) {
|
||||
events = events.filterThreadRoots();
|
||||
} else {
|
||||
events = events.filterByThreaded(controller.thread != null);
|
||||
}
|
||||
|
||||
final animateInEventIndex = controller.animateInEventIndex;
|
||||
final threads = controller.room.threads;
|
||||
|
||||
|
|
|
|||
|
|
@ -330,6 +330,7 @@ class ChatView extends StatelessWidget {
|
|||
onTap: controller.clearSingleSelectedEvent,
|
||||
child: ChatEventList(
|
||||
controller: controller,
|
||||
showThreadRoots: controller.showThreadRoots,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
@ -349,7 +350,8 @@ class ChatView extends StatelessWidget {
|
|||
),
|
||||
)
|
||||
else if (controller.room.canSendDefaultMessages &&
|
||||
controller.room.membership == Membership.join)
|
||||
controller.room.membership == Membership.join &&
|
||||
!controller.showThreadRoots)
|
||||
Container(
|
||||
margin: EdgeInsets.all(bottomSheetPadding),
|
||||
constraints: const BoxConstraints(
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
import 'package:extera_next/pages/chat_thread/chat_threads_view.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:collection/collection.dart';
|
||||
|
|
|
|||
|
|
@ -271,7 +271,7 @@ class ChatDetailsView extends StatelessWidget {
|
|||
subtitle:
|
||||
Text(L10n.of(context).chatThreadsDescription),
|
||||
onTap: () =>
|
||||
context.push('/rooms/${room.id}/threads'),
|
||||
context.push('/rooms/${room.id}?threads=true'),
|
||||
trailing: const Icon(Icons.chevron_right_outlined),
|
||||
),
|
||||
ListTile(
|
||||
|
|
|
|||
|
|
@ -1,53 +0,0 @@
|
|||
import 'package:extera_next/pages/chat_thread/chat_threads_view.dart';
|
||||
import 'package:extera_next/widgets/matrix.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:matrix/matrix.dart';
|
||||
import 'package:scroll_to_index/scroll_to_index.dart';
|
||||
|
||||
class ChatThreads extends StatefulWidget {
|
||||
final String roomId;
|
||||
|
||||
const ChatThreads({
|
||||
super.key,
|
||||
required this.roomId,
|
||||
});
|
||||
|
||||
@override
|
||||
ChatThreadsController createState() => ChatThreadsController();
|
||||
}
|
||||
|
||||
class ChatThreadsController extends State<ChatThreads> {
|
||||
String get roomId => widget.roomId;
|
||||
Room? get room => Matrix.of(context).client.getRoomById(roomId);
|
||||
|
||||
bool isLoadingThreads = false;
|
||||
|
||||
final AutoScrollController scrollController = AutoScrollController();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => ChatThreadsView(this);
|
||||
|
||||
void loadThreads([dynamic _]) async {
|
||||
final room = Matrix.of(context).client.getRoomById(roomId);
|
||||
|
||||
if (room == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
isLoadingThreads = true;
|
||||
|
||||
await room.loadThreadsFromServer();
|
||||
|
||||
isLoadingThreads = false;
|
||||
}
|
||||
|
||||
List<Thread>? get threads => room?.threads.values.toList();
|
||||
|
||||
Stream get onChanged => Matrix.of(context).client.onSync.stream.where(
|
||||
(e) =>
|
||||
(e.rooms?.join?.containsKey(roomId) ?? false) &&
|
||||
(e.rooms!.join![roomId]?.timeline?.events
|
||||
?.any((s) => s.type == EventTypes.Message && s.content['m.relates_to'] != null) ??
|
||||
false),
|
||||
);
|
||||
}
|
||||
|
|
@ -1,110 +0,0 @@
|
|||
import 'package:extera_next/config/themes.dart';
|
||||
import 'package:extera_next/generated/l10n/l10n.dart';
|
||||
import 'package:extera_next/pages/chat_thread/chat_threads.dart';
|
||||
import 'package:extera_next/utils/platform_infos.dart';
|
||||
import 'package:extera_next/widgets/avatar.dart';
|
||||
import 'package:extera_next/widgets/layouts/max_width_body.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:matrix/matrix.dart';
|
||||
import 'package:scroll_to_index/scroll_to_index.dart';
|
||||
|
||||
class ChatThreadsView extends StatelessWidget {
|
||||
final ChatThreadsController controller;
|
||||
|
||||
const ChatThreadsView(this.controller, {super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final horizontalPadding = FluffyThemes.isColumnMode(context) ? 8.0 : 0.0;
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
leading: const Center(child: BackButton()),
|
||||
title: Text(L10n.of(context).chatThreads),
|
||||
),
|
||||
body: MaxWidthBody(
|
||||
child: ListView.custom(
|
||||
padding: EdgeInsets.only(
|
||||
top: 16,
|
||||
bottom: 8,
|
||||
left: horizontalPadding,
|
||||
right: horizontalPadding,
|
||||
),
|
||||
reverse: true,
|
||||
controller: controller.scrollController,
|
||||
keyboardDismissBehavior: PlatformInfos.isIOS
|
||||
? ScrollViewKeyboardDismissBehavior.onDrag
|
||||
: ScrollViewKeyboardDismissBehavior.manual,
|
||||
childrenDelegate: SliverChildBuilderDelegate(
|
||||
(BuildContext context, int i) {
|
||||
if (i == (controller.threads?.length ?? 0) + 1) {
|
||||
if (controller.isLoadingThreads) {
|
||||
return const Center(
|
||||
child: CircularProgressIndicator.adaptive(strokeWidth: 2),
|
||||
);
|
||||
} else if (!(controller.room?.loadedAllThreads ?? false)) {
|
||||
return Builder(
|
||||
builder: (context) {
|
||||
WidgetsBinding.instance
|
||||
.addPostFrameCallback(controller.loadThreads);
|
||||
return Center(
|
||||
child: IconButton(
|
||||
onPressed: controller.loadThreads,
|
||||
icon: const Icon(Icons.refresh_outlined),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
i--;
|
||||
|
||||
final thread = controller.threads![i];
|
||||
|
||||
return AutoScrollTag(
|
||||
key: ValueKey(thread.rootEvent.eventId),
|
||||
index: i,
|
||||
controller: controller.scrollController,
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 16.0,
|
||||
vertical: 8.0,
|
||||
),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
FutureBuilder<User?>(
|
||||
future: thread.rootEvent.fetchSenderUser(),
|
||||
builder: (context, snapshot) {
|
||||
final user = snapshot.data ??
|
||||
thread.rootEvent.senderFromMemoryOrFallback;
|
||||
|
||||
return Avatar(
|
||||
mxContent: user.avatarUrl,
|
||||
name: user.calcDisplayname(),
|
||||
size: 48,
|
||||
);
|
||||
},
|
||||
),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Text(thread.rootEvent.senderFromMemoryOrFallback.calcDisplayname()),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 4.0),
|
||||
Text(thread.rootEvent.text),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
childCount: (controller.threads?.length ?? 0) + 1,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue