mirror of
https://gitlab.com/famedly/fluffychat.git
synced 2024-11-23 20:49:26 +01:00
Merge branch 'braid/multi-account-fixes' into 'main'
fix: multi-account related issues See merge request famedly/fluffychat!874
This commit is contained in:
commit
8c86ff4331
@ -82,7 +82,10 @@ class ChatListController extends State<ChatList> with TickerProviderStateMixin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void setActiveSpacesEntry(BuildContext context, SpacesEntry? spaceId) {
|
void setActiveSpacesEntry(BuildContext context, SpacesEntry? spaceId) {
|
||||||
if (snappingSheetController.currentPosition != kSpacesBottomBarHeight) {
|
if ((snappingSheetController.isAttached
|
||||||
|
? snappingSheetController.currentPosition
|
||||||
|
: 0) !=
|
||||||
|
kSpacesBottomBarHeight) {
|
||||||
snapBackSpacesSheet();
|
snapBackSpacesSheet();
|
||||||
}
|
}
|
||||||
setState(() => _activeSpacesEntry = spaceId);
|
setState(() => _activeSpacesEntry = spaceId);
|
||||||
|
@ -9,6 +9,7 @@ import 'package:matrix/matrix.dart';
|
|||||||
import 'package:fluffychat/pages/chat_list/chat_list.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/chat_list_item.dart';
|
||||||
import 'package:fluffychat/pages/chat_list/spaces_bottom_bar.dart';
|
import 'package:fluffychat/pages/chat_list/spaces_bottom_bar.dart';
|
||||||
|
import 'package:fluffychat/pages/chat_list/spaces_entry.dart';
|
||||||
import 'package:fluffychat/pages/chat_list/stories_header.dart';
|
import 'package:fluffychat/pages/chat_list/stories_header.dart';
|
||||||
import '../../utils/stream_extension.dart';
|
import '../../utils/stream_extension.dart';
|
||||||
import '../../widgets/matrix.dart';
|
import '../../widgets/matrix.dart';
|
||||||
@ -28,7 +29,7 @@ class _ChatListViewBodyState extends State<ChatListViewBody> {
|
|||||||
|
|
||||||
// used to check the animation direction
|
// used to check the animation direction
|
||||||
String? _lastUserId;
|
String? _lastUserId;
|
||||||
String? _lastSpaceId;
|
SpacesEntry? _lastSpace;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
@ -175,11 +176,13 @@ class _ChatListViewBodyState extends State<ChatListViewBody> {
|
|||||||
return SharedAxisTransition(
|
return SharedAxisTransition(
|
||||||
animation: primaryAnimation,
|
animation: primaryAnimation,
|
||||||
secondaryAnimation: secondaryAnimation,
|
secondaryAnimation: secondaryAnimation,
|
||||||
transitionType:
|
transitionType: (widget.controller.snappingSheetController.isAttached
|
||||||
widget.controller.snappingSheetController.currentPosition ==
|
? widget
|
||||||
kSpacesBottomBarHeight
|
.controller.snappingSheetController.currentPosition
|
||||||
? SharedAxisTransitionType.horizontal
|
: 0) ==
|
||||||
: SharedAxisTransitionType.vertical,
|
kSpacesBottomBarHeight
|
||||||
|
? SharedAxisTransitionType.horizontal
|
||||||
|
: SharedAxisTransitionType.vertical,
|
||||||
fillColor: Theme.of(context).scaffoldBackgroundColor,
|
fillColor: Theme.of(context).scaffoldBackgroundColor,
|
||||||
child: child,
|
child: child,
|
||||||
);
|
);
|
||||||
@ -208,13 +211,13 @@ class _ChatListViewBodyState extends State<ChatListViewBody> {
|
|||||||
}
|
}
|
||||||
// otherwise, the space changed...
|
// otherwise, the space changed...
|
||||||
else {
|
else {
|
||||||
reversed = widget.controller.spaces
|
reversed = widget.controller.spacesEntries
|
||||||
.indexWhere((element) => element.id == _lastSpaceId) <
|
.indexWhere((element) => element == _lastSpace) <
|
||||||
widget.controller.spaces.indexWhere(
|
widget.controller.spacesEntries.indexWhere(
|
||||||
(element) => element.id == widget.controller.activeSpaceId);
|
(element) => element == widget.controller.activeSpacesEntry);
|
||||||
}
|
}
|
||||||
_lastUserId = newClient.userID;
|
_lastUserId = newClient.userID;
|
||||||
_lastSpaceId = widget.controller.activeSpaceId;
|
_lastSpace = widget.controller.activeSpacesEntry;
|
||||||
return reversed;
|
return reversed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
215
lib/pages/chat_list/chat_list_header.dart
Normal file
215
lib/pages/chat_list/chat_list_header.dart
Normal file
@ -0,0 +1,215 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
|
||||||
|
import 'package:animations/animations.dart';
|
||||||
|
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||||
|
import 'package:keyboard_shortcuts/keyboard_shortcuts.dart';
|
||||||
|
import 'package:vrouter/vrouter.dart';
|
||||||
|
|
||||||
|
import 'package:fluffychat/config/app_config.dart';
|
||||||
|
import 'package:fluffychat/pages/chat_list/chat_list.dart';
|
||||||
|
import 'package:fluffychat/pages/chat_list/client_chooser_button.dart';
|
||||||
|
import '../../widgets/matrix.dart';
|
||||||
|
|
||||||
|
class ChatListHeader extends StatelessWidget implements PreferredSizeWidget {
|
||||||
|
final ChatListController controller;
|
||||||
|
|
||||||
|
const ChatListHeader({Key? key, required this.controller}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final selectMode = controller.selectMode;
|
||||||
|
|
||||||
|
return AppBar(
|
||||||
|
elevation: controller.scrolledToTop ? 0 : null,
|
||||||
|
actionsIconTheme: IconThemeData(
|
||||||
|
color: controller.selectedRoomIds.isEmpty
|
||||||
|
? null
|
||||||
|
: Theme.of(context).colorScheme.primary,
|
||||||
|
),
|
||||||
|
leading: Matrix.of(context).isMultiAccount
|
||||||
|
? ClientChooserButton(controller)
|
||||||
|
: selectMode == SelectMode.normal
|
||||||
|
? null
|
||||||
|
: IconButton(
|
||||||
|
tooltip: L10n.of(context)!.cancel,
|
||||||
|
icon: const Icon(Icons.close_outlined),
|
||||||
|
onPressed: controller.cancelAction,
|
||||||
|
color: Theme.of(context).colorScheme.primary,
|
||||||
|
),
|
||||||
|
centerTitle: false,
|
||||||
|
actions: selectMode == SelectMode.share
|
||||||
|
? null
|
||||||
|
: selectMode == SelectMode.select
|
||||||
|
? [
|
||||||
|
if (controller.spaces.isNotEmpty)
|
||||||
|
IconButton(
|
||||||
|
tooltip: L10n.of(context)!.addToSpace,
|
||||||
|
icon: const Icon(Icons.group_work_outlined),
|
||||||
|
onPressed: controller.addOrRemoveToSpace,
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
tooltip: L10n.of(context)!.toggleUnread,
|
||||||
|
icon: Icon(controller.anySelectedRoomNotMarkedUnread
|
||||||
|
? Icons.mark_chat_read_outlined
|
||||||
|
: Icons.mark_chat_unread_outlined),
|
||||||
|
onPressed: controller.toggleUnread,
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
tooltip: L10n.of(context)!.toggleFavorite,
|
||||||
|
icon: Icon(controller.anySelectedRoomNotFavorite
|
||||||
|
? Icons.push_pin_outlined
|
||||||
|
: Icons.push_pin),
|
||||||
|
onPressed: controller.toggleFavouriteRoom,
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
icon: Icon(controller.anySelectedRoomNotMuted
|
||||||
|
? Icons.notifications_off_outlined
|
||||||
|
: Icons.notifications_outlined),
|
||||||
|
tooltip: L10n.of(context)!.toggleMuted,
|
||||||
|
onPressed: controller.toggleMuted,
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
icon: const Icon(Icons.delete_outlined),
|
||||||
|
tooltip: L10n.of(context)!.archive,
|
||||||
|
onPressed: controller.archiveAction,
|
||||||
|
),
|
||||||
|
]
|
||||||
|
: [
|
||||||
|
KeyBoardShortcuts(
|
||||||
|
keysToPress: {
|
||||||
|
LogicalKeyboardKey.controlLeft,
|
||||||
|
LogicalKeyboardKey.keyF
|
||||||
|
},
|
||||||
|
onKeysPressed: () => VRouter.of(context).to('/search'),
|
||||||
|
helpLabel: L10n.of(context)!.search,
|
||||||
|
child: IconButton(
|
||||||
|
icon: const Icon(Icons.search_outlined),
|
||||||
|
tooltip: L10n.of(context)!.search,
|
||||||
|
onPressed: () => VRouter.of(context).to('/search'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (selectMode == SelectMode.normal)
|
||||||
|
IconButton(
|
||||||
|
icon: const Icon(Icons.camera_alt_outlined),
|
||||||
|
tooltip: L10n.of(context)!.addToStory,
|
||||||
|
onPressed: () =>
|
||||||
|
VRouter.of(context).to('/stories/create'),
|
||||||
|
),
|
||||||
|
PopupMenuButton<PopupMenuAction>(
|
||||||
|
onSelected: controller.onPopupMenuSelect,
|
||||||
|
itemBuilder: (_) => [
|
||||||
|
PopupMenuItem(
|
||||||
|
value: PopupMenuAction.setStatus,
|
||||||
|
child: Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
const Icon(Icons.edit_outlined),
|
||||||
|
const SizedBox(width: 12),
|
||||||
|
Text(L10n.of(context)!.setStatus),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
PopupMenuItem(
|
||||||
|
value: PopupMenuAction.newGroup,
|
||||||
|
child: Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
const Icon(Icons.group_add_outlined),
|
||||||
|
const SizedBox(width: 12),
|
||||||
|
Text(L10n.of(context)!.createNewGroup),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
PopupMenuItem(
|
||||||
|
value: PopupMenuAction.newSpace,
|
||||||
|
child: Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
const Icon(Icons.group_work_outlined),
|
||||||
|
const SizedBox(width: 12),
|
||||||
|
Text(L10n.of(context)!.createNewSpace),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
PopupMenuItem(
|
||||||
|
value: PopupMenuAction.invite,
|
||||||
|
child: Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
const Icon(Icons.share_outlined),
|
||||||
|
const SizedBox(width: 12),
|
||||||
|
Text(L10n.of(context)!.inviteContact),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
PopupMenuItem(
|
||||||
|
value: PopupMenuAction.archive,
|
||||||
|
child: Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
const Icon(Icons.archive_outlined),
|
||||||
|
const SizedBox(width: 12),
|
||||||
|
Text(L10n.of(context)!.archive),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
PopupMenuItem(
|
||||||
|
value: PopupMenuAction.settings,
|
||||||
|
child: Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
const Icon(Icons.settings_outlined),
|
||||||
|
const SizedBox(width: 12),
|
||||||
|
Text(L10n.of(context)!.settings),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
title: PageTransitionSwitcher(
|
||||||
|
reverse: false,
|
||||||
|
transitionBuilder: (
|
||||||
|
Widget child,
|
||||||
|
Animation<double> primaryAnimation,
|
||||||
|
Animation<double> secondaryAnimation,
|
||||||
|
) {
|
||||||
|
return SharedAxisTransition(
|
||||||
|
animation: primaryAnimation,
|
||||||
|
secondaryAnimation: secondaryAnimation,
|
||||||
|
transitionType: SharedAxisTransitionType.scaled,
|
||||||
|
fillColor: Colors.transparent,
|
||||||
|
child: child,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
layoutBuilder: (children) => Stack(
|
||||||
|
alignment: AlignmentDirectional.centerStart,
|
||||||
|
children: children,
|
||||||
|
),
|
||||||
|
child: selectMode == SelectMode.share
|
||||||
|
? Text(
|
||||||
|
L10n.of(context)!.share,
|
||||||
|
key: const ValueKey(SelectMode.share),
|
||||||
|
)
|
||||||
|
: selectMode == SelectMode.select
|
||||||
|
? Text(
|
||||||
|
controller.selectedRoomIds.length.toString(),
|
||||||
|
key: const ValueKey(SelectMode.select),
|
||||||
|
)
|
||||||
|
: (() {
|
||||||
|
final name = controller.activeSpaceId == null
|
||||||
|
? AppConfig.applicationName
|
||||||
|
: Matrix.of(context)
|
||||||
|
.client
|
||||||
|
.getRoomById(controller.activeSpaceId!)!
|
||||||
|
.displayname;
|
||||||
|
return Text(name, key: ValueKey(name));
|
||||||
|
})(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Size get preferredSize => const Size.fromHeight(56);
|
||||||
|
}
|
@ -7,13 +7,12 @@ import 'package:keyboard_shortcuts/keyboard_shortcuts.dart';
|
|||||||
import 'package:snapping_sheet/snapping_sheet.dart';
|
import 'package:snapping_sheet/snapping_sheet.dart';
|
||||||
import 'package:vrouter/vrouter.dart';
|
import 'package:vrouter/vrouter.dart';
|
||||||
|
|
||||||
import 'package:fluffychat/config/app_config.dart';
|
|
||||||
import 'package:fluffychat/pages/chat_list/chat_list.dart';
|
import 'package:fluffychat/pages/chat_list/chat_list.dart';
|
||||||
import 'package:fluffychat/pages/chat_list/client_chooser_button.dart';
|
|
||||||
import 'package:fluffychat/pages/chat_list/spaces_bottom_bar.dart';
|
import 'package:fluffychat/pages/chat_list/spaces_bottom_bar.dart';
|
||||||
import 'package:fluffychat/widgets/connection_status_header.dart';
|
import 'package:fluffychat/widgets/connection_status_header.dart';
|
||||||
import '../../widgets/matrix.dart';
|
import '../../widgets/matrix.dart';
|
||||||
import 'chat_list_body.dart';
|
import 'chat_list_body.dart';
|
||||||
|
import 'chat_list_header.dart';
|
||||||
|
|
||||||
class ChatListView extends StatelessWidget {
|
class ChatListView extends StatelessWidget {
|
||||||
final ChatListController controller;
|
final ChatListController controller;
|
||||||
@ -35,167 +34,7 @@ class ChatListView extends StatelessWidget {
|
|||||||
if (selMode == SelectMode.select) redirector.stopRedirection();
|
if (selMode == SelectMode.select) redirector.stopRedirection();
|
||||||
},
|
},
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
appBar: AppBar(
|
appBar: ChatListHeader(controller: controller),
|
||||||
elevation: controller.scrolledToTop ? 0 : null,
|
|
||||||
actionsIconTheme: IconThemeData(
|
|
||||||
color: controller.selectedRoomIds.isEmpty
|
|
||||||
? null
|
|
||||||
: Theme.of(context).colorScheme.primary,
|
|
||||||
),
|
|
||||||
leading: Matrix.of(context).isMultiAccount
|
|
||||||
? ClientChooserButton(controller)
|
|
||||||
: selectMode == SelectMode.normal
|
|
||||||
? null
|
|
||||||
: IconButton(
|
|
||||||
tooltip: L10n.of(context)!.cancel,
|
|
||||||
icon: const Icon(Icons.close_outlined),
|
|
||||||
onPressed: controller.cancelAction,
|
|
||||||
color: Theme.of(context).colorScheme.primary,
|
|
||||||
),
|
|
||||||
centerTitle: false,
|
|
||||||
actions: selectMode == SelectMode.share
|
|
||||||
? null
|
|
||||||
: selectMode == SelectMode.select
|
|
||||||
? [
|
|
||||||
if (controller.spaces.isNotEmpty)
|
|
||||||
IconButton(
|
|
||||||
tooltip: L10n.of(context)!.addToSpace,
|
|
||||||
icon: const Icon(Icons.group_work_outlined),
|
|
||||||
onPressed: controller.addOrRemoveToSpace,
|
|
||||||
),
|
|
||||||
IconButton(
|
|
||||||
tooltip: L10n.of(context)!.toggleUnread,
|
|
||||||
icon: Icon(controller.anySelectedRoomNotMarkedUnread
|
|
||||||
? Icons.mark_chat_read_outlined
|
|
||||||
: Icons.mark_chat_unread_outlined),
|
|
||||||
onPressed: controller.toggleUnread,
|
|
||||||
),
|
|
||||||
IconButton(
|
|
||||||
tooltip: L10n.of(context)!.toggleFavorite,
|
|
||||||
icon: Icon(controller.anySelectedRoomNotFavorite
|
|
||||||
? Icons.push_pin_outlined
|
|
||||||
: Icons.push_pin),
|
|
||||||
onPressed: controller.toggleFavouriteRoom,
|
|
||||||
),
|
|
||||||
IconButton(
|
|
||||||
icon: Icon(controller.anySelectedRoomNotMuted
|
|
||||||
? Icons.notifications_off_outlined
|
|
||||||
: Icons.notifications_outlined),
|
|
||||||
tooltip: L10n.of(context)!.toggleMuted,
|
|
||||||
onPressed: controller.toggleMuted,
|
|
||||||
),
|
|
||||||
IconButton(
|
|
||||||
icon: const Icon(Icons.delete_outlined),
|
|
||||||
tooltip: L10n.of(context)!.archive,
|
|
||||||
onPressed: controller.archiveAction,
|
|
||||||
),
|
|
||||||
]
|
|
||||||
: [
|
|
||||||
KeyBoardShortcuts(
|
|
||||||
keysToPress: {
|
|
||||||
LogicalKeyboardKey.controlLeft,
|
|
||||||
LogicalKeyboardKey.keyF
|
|
||||||
},
|
|
||||||
onKeysPressed: () =>
|
|
||||||
VRouter.of(context).to('/search'),
|
|
||||||
helpLabel: L10n.of(context)!.search,
|
|
||||||
child: IconButton(
|
|
||||||
icon: const Icon(Icons.search_outlined),
|
|
||||||
tooltip: L10n.of(context)!.search,
|
|
||||||
onPressed: () =>
|
|
||||||
VRouter.of(context).to('/search'),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
if (selectMode == SelectMode.normal)
|
|
||||||
IconButton(
|
|
||||||
icon: const Icon(Icons.camera_alt_outlined),
|
|
||||||
tooltip: L10n.of(context)!.addToStory,
|
|
||||||
onPressed: () =>
|
|
||||||
VRouter.of(context).to('/stories/create'),
|
|
||||||
),
|
|
||||||
PopupMenuButton<PopupMenuAction>(
|
|
||||||
onSelected: controller.onPopupMenuSelect,
|
|
||||||
itemBuilder: (_) => [
|
|
||||||
PopupMenuItem(
|
|
||||||
value: PopupMenuAction.setStatus,
|
|
||||||
child: Row(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
const Icon(Icons.edit_outlined),
|
|
||||||
const SizedBox(width: 12),
|
|
||||||
Text(L10n.of(context)!.setStatus),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
PopupMenuItem(
|
|
||||||
value: PopupMenuAction.newGroup,
|
|
||||||
child: Row(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
const Icon(Icons.group_add_outlined),
|
|
||||||
const SizedBox(width: 12),
|
|
||||||
Text(L10n.of(context)!.createNewGroup),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
PopupMenuItem(
|
|
||||||
value: PopupMenuAction.newSpace,
|
|
||||||
child: Row(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
const Icon(Icons.group_work_outlined),
|
|
||||||
const SizedBox(width: 12),
|
|
||||||
Text(L10n.of(context)!.createNewSpace),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
PopupMenuItem(
|
|
||||||
value: PopupMenuAction.invite,
|
|
||||||
child: Row(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
const Icon(Icons.share_outlined),
|
|
||||||
const SizedBox(width: 12),
|
|
||||||
Text(L10n.of(context)!.inviteContact),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
PopupMenuItem(
|
|
||||||
value: PopupMenuAction.archive,
|
|
||||||
child: Row(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
const Icon(Icons.archive_outlined),
|
|
||||||
const SizedBox(width: 12),
|
|
||||||
Text(L10n.of(context)!.archive),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
PopupMenuItem(
|
|
||||||
value: PopupMenuAction.settings,
|
|
||||||
child: Row(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
const Icon(Icons.settings_outlined),
|
|
||||||
const SizedBox(width: 12),
|
|
||||||
Text(L10n.of(context)!.settings),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
title: Text(selectMode == SelectMode.share
|
|
||||||
? L10n.of(context)!.share
|
|
||||||
: selectMode == SelectMode.select
|
|
||||||
? controller.selectedRoomIds.length.toString()
|
|
||||||
: controller.activeSpaceId == null
|
|
||||||
? AppConfig.applicationName
|
|
||||||
: Matrix.of(context)
|
|
||||||
.client
|
|
||||||
.getRoomById(controller.activeSpaceId!)!
|
|
||||||
.displayname),
|
|
||||||
),
|
|
||||||
body: LayoutBuilder(
|
body: LayoutBuilder(
|
||||||
builder: (context, size) {
|
builder: (context, size) {
|
||||||
controller.snappingSheetContainerSize = size;
|
controller.snappingSheetContainerSize = size;
|
||||||
|
@ -123,12 +123,15 @@ class ClientChooserButton extends StatelessWidget {
|
|||||||
onKeysPressed: () => _previousAccount(matrix),
|
onKeysPressed: () => _previousAccount(matrix),
|
||||||
),
|
),
|
||||||
PopupMenuButton<Object>(
|
PopupMenuButton<Object>(
|
||||||
child: Avatar(
|
child: Material(
|
||||||
mxContent: snapshot.data?.avatarUrl,
|
borderRadius: BorderRadius.zero,
|
||||||
name: snapshot.data?.displayName ??
|
child: Avatar(
|
||||||
matrix.client.userID!.localpart,
|
mxContent: snapshot.data?.avatarUrl,
|
||||||
size: 28,
|
name: snapshot.data?.displayName ??
|
||||||
fontSize: 12,
|
matrix.client.userID!.localpart,
|
||||||
|
size: 28,
|
||||||
|
fontSize: 12,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
onSelected: _clientSelected,
|
onSelected: _clientSelected,
|
||||||
itemBuilder: _bundleMenuItems,
|
itemBuilder: _bundleMenuItems,
|
||||||
|
@ -12,6 +12,8 @@ import 'package:fluffychat/widgets/matrix.dart';
|
|||||||
|
|
||||||
const kSpacesBottomBarHeight = 56.0;
|
const kSpacesBottomBarHeight = 56.0;
|
||||||
|
|
||||||
|
final GlobalKey _globalKey = GlobalKey();
|
||||||
|
|
||||||
class SpacesBottomBar extends StatelessWidget {
|
class SpacesBottomBar extends StatelessWidget {
|
||||||
final ChatListController controller;
|
final ChatListController controller;
|
||||||
|
|
||||||
@ -37,13 +39,16 @@ class SpacesBottomBar extends StatelessWidget {
|
|||||||
return SingleChildScrollView(
|
return SingleChildScrollView(
|
||||||
controller: controller.snappingSheetScrollContentController,
|
controller: controller.snappingSheetScrollContentController,
|
||||||
child: AnimatedBuilder(
|
child: AnimatedBuilder(
|
||||||
child: _SpacesBottomNavigation(controller: controller),
|
child: _SpacesBottomNavigation(
|
||||||
|
key: _globalKey, controller: controller),
|
||||||
builder: (context, child) {
|
builder: (context, child) {
|
||||||
if (controller.snappingSheetContainerSize == null) {
|
if (controller.snappingSheetContainerSize == null) {
|
||||||
return child!;
|
return child!;
|
||||||
}
|
}
|
||||||
final rawPosition =
|
final rawPosition =
|
||||||
controller.snappingSheetController.currentPosition;
|
controller.snappingSheetController.isAttached
|
||||||
|
? controller.snappingSheetController.currentPosition
|
||||||
|
: 0;
|
||||||
final position = rawPosition /
|
final position = rawPosition /
|
||||||
controller.snappingSheetContainerSize!.maxHeight;
|
controller.snappingSheetContainerSize!.maxHeight;
|
||||||
|
|
||||||
|
@ -77,6 +77,14 @@ class AllRoomsSpacesEntry extends SpacesEntry {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool shouldShowStoriesHeader(BuildContext context) => true;
|
bool shouldShowStoriesHeader(BuildContext context) => true;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return runtimeType == other.runtimeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => runtimeType.hashCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
// "Direct Chats" entry.
|
// "Direct Chats" entry.
|
||||||
@ -101,6 +109,14 @@ class DirectChatsSpacesEntry extends SpacesEntry {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool shouldShowStoriesHeader(BuildContext context) => true;
|
bool shouldShowStoriesHeader(BuildContext context) => true;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return runtimeType == other.runtimeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => runtimeType.hashCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
// "Groups" entry.
|
// "Groups" entry.
|
||||||
@ -134,6 +150,14 @@ class GroupsSpacesEntry extends SpacesEntry {
|
|||||||
bool separatedGroup(Room room, List<Room> spaces) {
|
bool separatedGroup(Room room, List<Room> spaces) {
|
||||||
return !spaces.any((space) => _roomInsideSpace(room, space));
|
return !spaces.any((space) => _roomInsideSpace(room, space));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return runtimeType == other.runtimeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => runtimeType.hashCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
// All rooms associated with a specific space.
|
// All rooms associated with a specific space.
|
||||||
@ -179,12 +203,12 @@ class SpaceSpacesEntry extends SpacesEntry {
|
|||||||
@override
|
@override
|
||||||
bool stillValid(BuildContext context) =>
|
bool stillValid(BuildContext context) =>
|
||||||
Matrix.of(context).client.getRoomById(space.id) != null;
|
Matrix.of(context).client.getRoomById(space.id) != null;
|
||||||
}
|
|
||||||
|
|
||||||
// Produces a "rough equivalence" for maintaining the current spaces index.
|
@override
|
||||||
bool spacesEntryRoughEquivalence(SpacesEntry a, SpacesEntry b) {
|
bool operator ==(Object other) {
|
||||||
if ((a is SpaceSpacesEntry) && (b is SpaceSpacesEntry)) {
|
return hashCode == other.hashCode;
|
||||||
return a.space.id == b.space.id;
|
|
||||||
}
|
}
|
||||||
return a == b;
|
|
||||||
|
@override
|
||||||
|
int get hashCode => space.id.hashCode;
|
||||||
}
|
}
|
||||||
|
@ -88,12 +88,13 @@ class SignupPageView extends StatelessWidget {
|
|||||||
controller.loading ? null : [AutofillHints.username],
|
controller.loading ? null : [AutofillHints.username],
|
||||||
validator: controller.emailTextFieldValidator,
|
validator: controller.emailTextFieldValidator,
|
||||||
decoration: FluffyThemes.loginTextFieldDecoration(
|
decoration: FluffyThemes.loginTextFieldDecoration(
|
||||||
prefixIcon: const Icon(
|
prefixIcon: const Icon(
|
||||||
Icons.mail_outlined,
|
Icons.mail_outlined,
|
||||||
color: Colors.black,
|
color: Colors.black,
|
||||||
),
|
),
|
||||||
hintText: L10n.of(context)!.enterAnEmailAddress,
|
hintText: L10n.of(context)!.enterAnEmailAddress,
|
||||||
errorText: controller.error),
|
errorText: controller.error,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Hero(
|
Hero(
|
||||||
|
@ -66,6 +66,7 @@ class ContentBanner extends StatelessWidget {
|
|||||||
imageUrl: src.toString(),
|
imageUrl: src.toString(),
|
||||||
height: 300,
|
height: 300,
|
||||||
fit: BoxFit.cover,
|
fit: BoxFit.cover,
|
||||||
|
errorWidget: (c, m, e) => Icon(defaultIcon, size: 200),
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
: Icon(defaultIcon, size: 200),
|
: Icon(defaultIcon, size: 200),
|
||||||
|
Loading…
Reference in New Issue
Block a user