mirror of
https://gitlab.com/famedly/fluffychat.git
synced 2025-01-23 02:24:12 +01:00
fix: Follow up for spaces hierarchy
- fix endless spinner - fix rooms shon twice - fix spaces accidentally opened as rooms - add missing spaces header to spaces view Signed-off-by: TheOneWithTheBraid <the-one@with-the-braid.cf>
This commit is contained in:
parent
82cb094b44
commit
a522a90e35
@ -22,6 +22,7 @@ import 'config/themes.dart';
|
||||
import 'utils/background_push.dart';
|
||||
import 'utils/custom_scroll_behaviour.dart';
|
||||
import 'utils/localized_exception_extension.dart';
|
||||
import 'utils/space_navigator.dart';
|
||||
import 'widgets/lock_screen.dart';
|
||||
import 'widgets/matrix.dart';
|
||||
|
||||
@ -132,6 +133,9 @@ class _FluffyChatAppState extends State<FluffyChatApp> {
|
||||
localizationsDelegates: const [
|
||||
...L10n.localizationsDelegates,
|
||||
],
|
||||
navigatorObservers: [
|
||||
SpaceNavigator.routeObserver,
|
||||
],
|
||||
supportedLocales: L10n.supportedLocales,
|
||||
initialUrl: _initialUrl ?? '/',
|
||||
routes: AppRoutes(columnMode ?? false).routes,
|
||||
|
@ -18,6 +18,7 @@ import 'package:fluffychat/pages/chat_list/spaces_entry.dart';
|
||||
import 'package:fluffychat/utils/famedlysdk_store.dart';
|
||||
import 'package:fluffychat/utils/localized_exception_extension.dart';
|
||||
import 'package:fluffychat/utils/platform_infos.dart';
|
||||
import 'package:fluffychat/utils/space_navigator.dart';
|
||||
import '../../../utils/account_bundles.dart';
|
||||
import '../../main.dart';
|
||||
import '../../utils/matrix_sdk_extensions.dart/matrix_file_extension.dart';
|
||||
@ -47,7 +48,8 @@ class ChatList extends StatefulWidget {
|
||||
ChatListController createState() => ChatListController();
|
||||
}
|
||||
|
||||
class ChatListController extends State<ChatList> with TickerProviderStateMixin {
|
||||
class ChatListController extends State<ChatList>
|
||||
with TickerProviderStateMixin, RouteAware {
|
||||
StreamSubscription? _intentDataStreamSubscription;
|
||||
|
||||
StreamSubscription? _intentFileStreamSubscription;
|
||||
@ -66,6 +68,8 @@ class ChatListController extends State<ChatList> with TickerProviderStateMixin {
|
||||
bool isSearching = false;
|
||||
static const String _serverStoreNamespace = 'im.fluffychat.search.server';
|
||||
|
||||
StreamSubscription<String?>? _spacesSubscription;
|
||||
|
||||
void setServer() async {
|
||||
final newServer = await showTextInputDialog(
|
||||
useRootNavigator: false,
|
||||
@ -177,11 +181,6 @@ class ChatListController extends State<ChatList> with TickerProviderStateMixin {
|
||||
}
|
||||
}
|
||||
|
||||
void setActiveSpacesEntry(BuildContext context, SpacesEntry? spaceId) {
|
||||
Scaffold.of(context).closeDrawer();
|
||||
setState(() => _activeSpacesEntry = spaceId);
|
||||
}
|
||||
|
||||
void editSpace(BuildContext context, String spaceId) async {
|
||||
await Matrix.of(context).client.getRoomById(spaceId)!.postLoad();
|
||||
VRouter.of(context).toSegments(['spaces', spaceId]);
|
||||
@ -310,6 +309,8 @@ class ChatListController extends State<ChatList> with TickerProviderStateMixin {
|
||||
|
||||
_checkTorBrowser();
|
||||
|
||||
_subscribeSpaceChanges();
|
||||
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@ -336,6 +337,7 @@ class ChatListController extends State<ChatList> with TickerProviderStateMixin {
|
||||
_intentDataStreamSubscription?.cancel();
|
||||
_intentFileStreamSubscription?.cancel();
|
||||
_intentUriStreamSubscription?.cancel();
|
||||
_spacesSubscription?.cancel();
|
||||
scrollController.removeListener(_onScroll);
|
||||
super.dispose();
|
||||
}
|
||||
@ -671,6 +673,27 @@ class ChatListController extends State<ChatList> with TickerProviderStateMixin {
|
||||
|
||||
Future<void> dehydrate() =>
|
||||
SettingsAccountController.dehydrateDevice(context);
|
||||
|
||||
_adjustSpaceQuery(String? spaceId) {
|
||||
cancelSearch();
|
||||
setState(() {
|
||||
if (spaceId != null) {
|
||||
final matching =
|
||||
spacesEntries.where((element) => element.routeHandle == spaceId);
|
||||
if (matching.isNotEmpty) {
|
||||
_activeSpacesEntry = matching.first;
|
||||
} else {
|
||||
_activeSpacesEntry = defaultSpacesEntry;
|
||||
}
|
||||
} else {
|
||||
_activeSpacesEntry = defaultSpacesEntry;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void _subscribeSpaceChanges() {
|
||||
_spacesSubscription = SpaceNavigator.stream.listen(_adjustSpaceQuery);
|
||||
}
|
||||
}
|
||||
|
||||
enum EditBundleAction { addToBundle, removeFromBundle }
|
||||
|
@ -5,12 +5,14 @@ import 'package:flutter/material.dart';
|
||||
import 'package:animations/animations.dart';
|
||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||
import 'package:matrix/matrix.dart';
|
||||
import 'package:matrix_link_text/link_text.dart';
|
||||
|
||||
import 'package:fluffychat/pages/chat_list/chat_list.dart';
|
||||
import 'package:fluffychat/pages/chat_list/chat_list_item.dart';
|
||||
import 'package:fluffychat/pages/chat_list/search_title.dart';
|
||||
import 'package:fluffychat/pages/chat_list/spaces_entry.dart';
|
||||
import 'package:fluffychat/pages/chat_list/stories_header.dart';
|
||||
import 'package:fluffychat/utils/url_launcher.dart';
|
||||
import 'package:fluffychat/widgets/avatar.dart';
|
||||
import 'package:fluffychat/widgets/connection_status_header.dart';
|
||||
import 'package:fluffychat/widgets/profile_bottom_sheet.dart';
|
||||
@ -75,6 +77,7 @@ class _ChatListViewBodyState extends State<ChatListViewBody> {
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const ConnectionStatusHeader(),
|
||||
SpaceRoomListTopBar(widget.controller),
|
||||
if (roomSearchResult != null) ...[
|
||||
SearchTitle(
|
||||
title: L10n.of(context)!.publicRooms,
|
||||
@ -205,7 +208,7 @@ class _ChatListViewBodyState extends State<ChatListViewBody> {
|
||||
title: L10n.of(context)!.chats,
|
||||
icon: const Icon(Icons.chat_outlined),
|
||||
),
|
||||
if (rooms.isEmpty)
|
||||
if (rooms.isEmpty && !widget.controller.isSearchMode)
|
||||
Column(
|
||||
key: const ValueKey(null),
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
@ -366,6 +369,63 @@ class _ChatListViewBodyState extends State<ChatListViewBody> {
|
||||
_lastSpace = widget.controller.activeSpacesEntry;
|
||||
return reversed;
|
||||
}
|
||||
|
||||
@override
|
||||
void didUpdateWidget(covariant ChatListViewBody oldWidget) {
|
||||
setState(() {});
|
||||
super.didUpdateWidget(oldWidget);
|
||||
}
|
||||
}
|
||||
|
||||
class SpaceRoomListTopBar extends StatefulWidget {
|
||||
final ChatListController controller;
|
||||
|
||||
const SpaceRoomListTopBar(this.controller, {Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<SpaceRoomListTopBar> createState() => _SpaceRoomListTopBarState();
|
||||
}
|
||||
|
||||
class _SpaceRoomListTopBarState extends State<SpaceRoomListTopBar> {
|
||||
bool _limitSize = true;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (widget.controller.activeSpacesEntry is SpaceSpacesEntry &&
|
||||
!widget.controller.isSearchMode &&
|
||||
(widget.controller.activeSpacesEntry as SpaceSpacesEntry)
|
||||
.space
|
||||
.topic
|
||||
.isNotEmpty) {
|
||||
return GestureDetector(
|
||||
onTap: () => setState(() {
|
||||
_limitSize = !_limitSize;
|
||||
}),
|
||||
child: Column(
|
||||
children: [
|
||||
Padding(
|
||||
child: LinkText(
|
||||
text: (widget.controller.activeSpacesEntry as SpaceSpacesEntry)
|
||||
.space
|
||||
.topic,
|
||||
maxLines: _limitSize ? 3 : null,
|
||||
linkStyle: const TextStyle(color: Colors.blueAccent),
|
||||
textStyle: TextStyle(
|
||||
fontSize: 14,
|
||||
color: Theme.of(context).textTheme.bodyText2!.color,
|
||||
),
|
||||
onLinkTap: (url) => UrlLauncher(context, url).launchUrl(),
|
||||
),
|
||||
padding: const EdgeInsets.all(8),
|
||||
),
|
||||
const Divider(),
|
||||
],
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return Container();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class _SearchItem extends StatelessWidget {
|
||||
|
@ -9,9 +9,13 @@ import 'package:fluffychat/widgets/public_room_bottom_sheet.dart';
|
||||
|
||||
class RecommendedRoomListItem extends StatelessWidget {
|
||||
final SpaceRoomsChunk room;
|
||||
final VoidCallback onRoomJoined;
|
||||
|
||||
const RecommendedRoomListItem({Key? key, required this.room})
|
||||
: super(key: key);
|
||||
const RecommendedRoomListItem({
|
||||
Key? key,
|
||||
required this.room,
|
||||
required this.onRoomJoined,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@ -59,28 +63,30 @@ class RecommendedRoomListItem extends StatelessWidget {
|
||||
),
|
||||
],
|
||||
);
|
||||
final subtitle = Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: Text(
|
||||
room.topic ?? 'topic',
|
||||
softWrap: false,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).textTheme.bodyText2!.color,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
final subtitle = room.topic != null
|
||||
? Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: Text(
|
||||
room.topic!,
|
||||
softWrap: false,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).textTheme.bodyText2!.color,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
: null;
|
||||
void handler() => showModalBottomSheet(
|
||||
context: context,
|
||||
builder: (c) => PublicRoomBottomSheet(
|
||||
roomAlias: room.canonicalAlias!,
|
||||
outerContext: context,
|
||||
chunk: room,
|
||||
onRoomJoined: onRoomJoined,
|
||||
),
|
||||
);
|
||||
if (room.roomType == 'm.space') {
|
||||
|
@ -4,6 +4,7 @@ import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||
|
||||
import 'package:fluffychat/pages/chat_list/chat_list.dart';
|
||||
import 'package:fluffychat/pages/chat_list/spaces_drawer.dart';
|
||||
import 'package:fluffychat/utils/space_navigator.dart';
|
||||
import 'package:fluffychat/widgets/avatar.dart';
|
||||
|
||||
class SpacesDrawerEntry extends StatelessWidget {
|
||||
@ -46,10 +47,11 @@ class SpacesDrawerEntry extends StatelessWidget {
|
||||
overflow: TextOverflow.fade,
|
||||
),
|
||||
);
|
||||
void onTap() => controller.setActiveSpacesEntry(
|
||||
context,
|
||||
space,
|
||||
);
|
||||
void onTap() {
|
||||
SpaceNavigator.navigateToSpace(space.routeHandle);
|
||||
Scaffold.of(context).closeDrawer();
|
||||
}
|
||||
|
||||
final trailing = room != null
|
||||
? SizedBox(
|
||||
width: 32,
|
||||
|
@ -19,18 +19,25 @@ abstract class SpacesEntry {
|
||||
|
||||
// Gets the (translated) name of this entry.
|
||||
String getName(BuildContext context);
|
||||
|
||||
// Gets an icon for this entry (avoided if a space is given)
|
||||
Icon getIcon(bool active) => active
|
||||
? const Icon(CupertinoIcons.chat_bubble_2_fill)
|
||||
: const Icon(CupertinoIcons.chat_bubble_2);
|
||||
|
||||
// If this is a specific Room, returns the space Room for various purposes.
|
||||
Room? getSpace(BuildContext context) => null;
|
||||
|
||||
// Gets a list of rooms - this is done as part of _ChatListViewBodyState to get the full list of rooms visible from this SpacesEntry.
|
||||
List<Room> getRooms(BuildContext context);
|
||||
|
||||
// Checks that this entry is still valid.
|
||||
bool stillValid(BuildContext context) => true;
|
||||
|
||||
// Returns true if the Stories header should be shown.
|
||||
bool shouldShowStoriesHeader(BuildContext context) => false;
|
||||
|
||||
String? get routeHandle;
|
||||
}
|
||||
|
||||
// Common room validity checks
|
||||
@ -58,7 +65,9 @@ bool _roomInsideSpace(Room room, Room space) {
|
||||
// "All rooms" entry.
|
||||
class AllRoomsSpacesEntry extends SpacesEntry {
|
||||
static final AllRoomsSpacesEntry _value = AllRoomsSpacesEntry._();
|
||||
|
||||
AllRoomsSpacesEntry._();
|
||||
|
||||
factory AllRoomsSpacesEntry() {
|
||||
return _value;
|
||||
}
|
||||
@ -75,6 +84,9 @@ class AllRoomsSpacesEntry extends SpacesEntry {
|
||||
.toList();
|
||||
}
|
||||
|
||||
@override
|
||||
final String? routeHandle = null;
|
||||
|
||||
@override
|
||||
bool shouldShowStoriesHeader(BuildContext context) => true;
|
||||
|
||||
@ -90,7 +102,9 @@ class AllRoomsSpacesEntry extends SpacesEntry {
|
||||
// "Direct Chats" entry.
|
||||
class DirectChatsSpacesEntry extends SpacesEntry {
|
||||
static final DirectChatsSpacesEntry _value = DirectChatsSpacesEntry._();
|
||||
|
||||
DirectChatsSpacesEntry._();
|
||||
|
||||
factory DirectChatsSpacesEntry() {
|
||||
return _value;
|
||||
}
|
||||
@ -107,6 +121,9 @@ class DirectChatsSpacesEntry extends SpacesEntry {
|
||||
.toList();
|
||||
}
|
||||
|
||||
@override
|
||||
final String? routeHandle = null;
|
||||
|
||||
@override
|
||||
bool shouldShowStoriesHeader(BuildContext context) => true;
|
||||
|
||||
@ -122,7 +139,9 @@ class DirectChatsSpacesEntry extends SpacesEntry {
|
||||
// "Groups" entry.
|
||||
class GroupsSpacesEntry extends SpacesEntry {
|
||||
static final GroupsSpacesEntry _value = GroupsSpacesEntry._();
|
||||
|
||||
GroupsSpacesEntry._();
|
||||
|
||||
factory GroupsSpacesEntry() {
|
||||
return _value;
|
||||
}
|
||||
@ -147,6 +166,9 @@ class GroupsSpacesEntry extends SpacesEntry {
|
||||
.toList();
|
||||
}
|
||||
|
||||
@override
|
||||
final String? routeHandle = 'groups';
|
||||
|
||||
bool separatedGroup(Room room, List<Room> spaces) {
|
||||
return !spaces.any((space) => _roomInsideSpace(room, space));
|
||||
}
|
||||
@ -163,6 +185,7 @@ class GroupsSpacesEntry extends SpacesEntry {
|
||||
// All rooms associated with a specific space.
|
||||
class SpaceSpacesEntry extends SpacesEntry {
|
||||
final Room space;
|
||||
|
||||
const SpaceSpacesEntry(this.space);
|
||||
|
||||
@override
|
||||
@ -204,6 +227,9 @@ class SpaceSpacesEntry extends SpacesEntry {
|
||||
bool stillValid(BuildContext context) =>
|
||||
Matrix.of(context).client.getRoomById(space.id) != null;
|
||||
|
||||
@override
|
||||
String? get routeHandle => space.id;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return hashCode == other.hashCode;
|
||||
|
@ -94,14 +94,12 @@ class _SpacesHierarchyProposalsState extends State<SpacesHierarchyProposals> {
|
||||
strokeWidth: 1,
|
||||
),
|
||||
),
|
||||
onTap: () => setState(
|
||||
() => SpacesHierarchyProposals._cache[widget.space!]!
|
||||
.invalidate(),
|
||||
),
|
||||
onTap: _refreshRooms,
|
||||
),
|
||||
...rooms.map(
|
||||
(e) => RecommendedRoomListItem(
|
||||
room: e,
|
||||
onRoomJoined: _refreshRooms,
|
||||
),
|
||||
),
|
||||
],
|
||||
@ -109,9 +107,9 @@ class _SpacesHierarchyProposalsState extends State<SpacesHierarchyProposals> {
|
||||
} else {
|
||||
child = Column(
|
||||
key: const ValueKey(null),
|
||||
children: const [
|
||||
LinearProgressIndicator(),
|
||||
ListTile(),
|
||||
children: [
|
||||
if (!snapshot.hasError) const LinearProgressIndicator(),
|
||||
const ListTile(),
|
||||
],
|
||||
);
|
||||
}
|
||||
@ -143,4 +141,8 @@ class _SpacesHierarchyProposalsState extends State<SpacesHierarchyProposals> {
|
||||
return Container();
|
||||
}
|
||||
}
|
||||
|
||||
void _refreshRooms() => setState(
|
||||
() => SpacesHierarchyProposals._cache[widget.space!]!.invalidate(),
|
||||
);
|
||||
}
|
||||
|
23
lib/utils/space_navigator.dart
Normal file
23
lib/utils/space_navigator.dart
Normal file
@ -0,0 +1,23 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// this is a workaround to allow navigation of spaces out from any widget.
|
||||
/// Reason is that we have no reliable way to listen on *query* changes of
|
||||
/// VRouter.
|
||||
///
|
||||
/// Time wasted: 3h
|
||||
abstract class SpaceNavigator {
|
||||
const SpaceNavigator._();
|
||||
|
||||
// TODO(TheOneWithTheBraid): adjust routing table in order to represent spaces
|
||||
// ... in any present path
|
||||
static final routeObserver = RouteObserver();
|
||||
|
||||
static final StreamController<String?> _controller =
|
||||
StreamController.broadcast();
|
||||
|
||||
static Stream<String?> get stream => _controller.stream;
|
||||
|
||||
static void navigateToSpace(String? spaceId) => _controller.add(spaceId);
|
||||
}
|
@ -10,6 +10,7 @@ import 'package:url_launcher/url_launcher.dart';
|
||||
import 'package:vrouter/vrouter.dart';
|
||||
|
||||
import 'package:fluffychat/config/app_config.dart';
|
||||
import 'package:fluffychat/utils/space_navigator.dart';
|
||||
import 'package:fluffychat/widgets/matrix.dart';
|
||||
import 'package:fluffychat/widgets/profile_bottom_sheet.dart';
|
||||
import 'package:fluffychat/widgets/public_room_bottom_sheet.dart';
|
||||
@ -18,6 +19,7 @@ import 'platform_infos.dart';
|
||||
class UrlLauncher {
|
||||
final String? url;
|
||||
final BuildContext context;
|
||||
|
||||
const UrlLauncher(this.context, this.url);
|
||||
|
||||
void launchUrl() {
|
||||
@ -130,6 +132,11 @@ class UrlLauncher {
|
||||
}
|
||||
servers.addAll(identityParts.via);
|
||||
if (room != null) {
|
||||
if (room.isSpace) {
|
||||
SpaceNavigator.navigateToSpace(room.id);
|
||||
VRouter.of(context).toSegments(['rooms']);
|
||||
return;
|
||||
}
|
||||
// we have the room, so....just open it
|
||||
if (event != null) {
|
||||
VRouter.of(context).toSegments(['rooms', room.id],
|
||||
|
@ -3,39 +3,48 @@ import 'dart:math';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||
import 'package:flutter_matrix_html/flutter_html.dart';
|
||||
import 'package:future_loading_dialog/future_loading_dialog.dart';
|
||||
import 'package:matrix/matrix.dart';
|
||||
import 'package:matrix_link_text/link_text.dart';
|
||||
import 'package:vrouter/vrouter.dart';
|
||||
|
||||
import 'package:fluffychat/config/themes.dart';
|
||||
import 'package:fluffychat/utils/url_launcher.dart';
|
||||
import 'package:fluffychat/widgets/content_banner.dart';
|
||||
import 'package:fluffychat/widgets/matrix.dart';
|
||||
import '../utils/localized_exception_extension.dart';
|
||||
|
||||
class PublicRoomBottomSheet extends StatelessWidget {
|
||||
final String roomAlias;
|
||||
final String? roomAlias;
|
||||
final BuildContext outerContext;
|
||||
final PublicRoomsChunk? chunk;
|
||||
const PublicRoomBottomSheet({
|
||||
required this.roomAlias,
|
||||
final VoidCallback? onRoomJoined;
|
||||
|
||||
PublicRoomBottomSheet({
|
||||
this.roomAlias,
|
||||
required this.outerContext,
|
||||
this.chunk,
|
||||
this.onRoomJoined,
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
}) : super(key: key) {
|
||||
assert(roomAlias != null || chunk != null);
|
||||
}
|
||||
|
||||
void _joinRoom(BuildContext context) async {
|
||||
final client = Matrix.of(context).client;
|
||||
final result = await showFutureLoadingDialog<String>(
|
||||
context: context,
|
||||
future: () => client.joinRoom(roomAlias),
|
||||
future: () => client.joinRoom(roomAlias ?? chunk!.roomId),
|
||||
);
|
||||
if (result.error == null) {
|
||||
if (client.getRoomById(result.result!) == null) {
|
||||
await client.onSync.stream.firstWhere(
|
||||
(sync) => sync.rooms?.join?.containsKey(result.result) ?? false);
|
||||
}
|
||||
VRouter.of(context).toSegments(['rooms', result.result!]);
|
||||
// don't open the room if the joined room is a space
|
||||
if (!client.getRoomById(result.result!)!.isSpace) {
|
||||
VRouter.of(context).toSegments(['rooms', result.result!]);
|
||||
}
|
||||
Navigator.of(context, rootNavigator: false).pop();
|
||||
return;
|
||||
}
|
||||
@ -47,7 +56,7 @@ class PublicRoomBottomSheet extends StatelessWidget {
|
||||
final chunk = this.chunk;
|
||||
if (chunk != null) return chunk;
|
||||
final query = await Matrix.of(context).client.queryPublicRooms(
|
||||
server: roomAlias.domain,
|
||||
server: roomAlias!.domain,
|
||||
filter: PublicRoomQueryFilter(
|
||||
genericSearchTerm: roomAlias,
|
||||
),
|
||||
@ -76,7 +85,7 @@ class PublicRoomBottomSheet extends StatelessWidget {
|
||||
backgroundColor:
|
||||
Theme.of(context).scaffoldBackgroundColor.withOpacity(0.5),
|
||||
title: Text(
|
||||
roomAlias,
|
||||
roomAlias ?? chunk!.name ?? chunk!.roomId,
|
||||
overflow: TextOverflow.fade,
|
||||
),
|
||||
leading: IconButton(
|
||||
@ -118,15 +127,37 @@ class PublicRoomBottomSheet extends StatelessWidget {
|
||||
client: Matrix.of(context).client,
|
||||
),
|
||||
ListTile(
|
||||
title:
|
||||
Text(profile?.name ?? roomAlias.localpart ?? ''),
|
||||
title: Text(profile?.name ??
|
||||
roomAlias?.localpart ??
|
||||
chunk!.roomId.localpart ??
|
||||
''),
|
||||
subtitle: Text(
|
||||
'${L10n.of(context)!.participant}: ${profile?.numJoinedMembers ?? 0}'),
|
||||
'${L10n.of(context)!.participant}: ${profile?.numJoinedMembers ?? 0}',
|
||||
),
|
||||
trailing: const Icon(Icons.account_box_outlined),
|
||||
),
|
||||
if (profile?.topic?.isNotEmpty ?? false)
|
||||
ListTile(
|
||||
subtitle: Html(data: profile!.topic!),
|
||||
title: Text(
|
||||
L10n.of(context)!.groupDescription,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.secondary,
|
||||
),
|
||||
),
|
||||
subtitle: LinkText(
|
||||
text: profile!.topic!,
|
||||
linkStyle:
|
||||
const TextStyle(color: Colors.blueAccent),
|
||||
textStyle: TextStyle(
|
||||
fontSize: 14,
|
||||
color: Theme.of(context)
|
||||
.textTheme
|
||||
.bodyText2!
|
||||
.color,
|
||||
),
|
||||
onLinkTap: (url) =>
|
||||
UrlLauncher(context, url).launchUrl(),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
|
Loading…
Reference in New Issue
Block a user