mirror of
https://gitlab.com/famedly/fluffychat.git
synced 2024-11-05 03:29:30 +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) {
|
||||
if (snappingSheetController.currentPosition != kSpacesBottomBarHeight) {
|
||||
if ((snappingSheetController.isAttached
|
||||
? snappingSheetController.currentPosition
|
||||
: 0) !=
|
||||
kSpacesBottomBarHeight) {
|
||||
snapBackSpacesSheet();
|
||||
}
|
||||
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_item.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 '../../utils/stream_extension.dart';
|
||||
import '../../widgets/matrix.dart';
|
||||
@ -28,7 +29,7 @@ class _ChatListViewBodyState extends State<ChatListViewBody> {
|
||||
|
||||
// used to check the animation direction
|
||||
String? _lastUserId;
|
||||
String? _lastSpaceId;
|
||||
SpacesEntry? _lastSpace;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@ -175,11 +176,13 @@ class _ChatListViewBodyState extends State<ChatListViewBody> {
|
||||
return SharedAxisTransition(
|
||||
animation: primaryAnimation,
|
||||
secondaryAnimation: secondaryAnimation,
|
||||
transitionType:
|
||||
widget.controller.snappingSheetController.currentPosition ==
|
||||
kSpacesBottomBarHeight
|
||||
? SharedAxisTransitionType.horizontal
|
||||
: SharedAxisTransitionType.vertical,
|
||||
transitionType: (widget.controller.snappingSheetController.isAttached
|
||||
? widget
|
||||
.controller.snappingSheetController.currentPosition
|
||||
: 0) ==
|
||||
kSpacesBottomBarHeight
|
||||
? SharedAxisTransitionType.horizontal
|
||||
: SharedAxisTransitionType.vertical,
|
||||
fillColor: Theme.of(context).scaffoldBackgroundColor,
|
||||
child: child,
|
||||
);
|
||||
@ -208,13 +211,13 @@ class _ChatListViewBodyState extends State<ChatListViewBody> {
|
||||
}
|
||||
// otherwise, the space changed...
|
||||
else {
|
||||
reversed = widget.controller.spaces
|
||||
.indexWhere((element) => element.id == _lastSpaceId) <
|
||||
widget.controller.spaces.indexWhere(
|
||||
(element) => element.id == widget.controller.activeSpaceId);
|
||||
reversed = widget.controller.spacesEntries
|
||||
.indexWhere((element) => element == _lastSpace) <
|
||||
widget.controller.spacesEntries.indexWhere(
|
||||
(element) => element == widget.controller.activeSpacesEntry);
|
||||
}
|
||||
_lastUserId = newClient.userID;
|
||||
_lastSpaceId = widget.controller.activeSpaceId;
|
||||
_lastSpace = widget.controller.activeSpacesEntry;
|
||||
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: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 'package:fluffychat/pages/chat_list/spaces_bottom_bar.dart';
|
||||
import 'package:fluffychat/widgets/connection_status_header.dart';
|
||||
import '../../widgets/matrix.dart';
|
||||
import 'chat_list_body.dart';
|
||||
import 'chat_list_header.dart';
|
||||
|
||||
class ChatListView extends StatelessWidget {
|
||||
final ChatListController controller;
|
||||
@ -35,167 +34,7 @@ class ChatListView extends StatelessWidget {
|
||||
if (selMode == SelectMode.select) redirector.stopRedirection();
|
||||
},
|
||||
child: Scaffold(
|
||||
appBar: 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: 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),
|
||||
),
|
||||
appBar: ChatListHeader(controller: controller),
|
||||
body: LayoutBuilder(
|
||||
builder: (context, size) {
|
||||
controller.snappingSheetContainerSize = size;
|
||||
|
@ -123,12 +123,15 @@ class ClientChooserButton extends StatelessWidget {
|
||||
onKeysPressed: () => _previousAccount(matrix),
|
||||
),
|
||||
PopupMenuButton<Object>(
|
||||
child: Avatar(
|
||||
mxContent: snapshot.data?.avatarUrl,
|
||||
name: snapshot.data?.displayName ??
|
||||
matrix.client.userID!.localpart,
|
||||
size: 28,
|
||||
fontSize: 12,
|
||||
child: Material(
|
||||
borderRadius: BorderRadius.zero,
|
||||
child: Avatar(
|
||||
mxContent: snapshot.data?.avatarUrl,
|
||||
name: snapshot.data?.displayName ??
|
||||
matrix.client.userID!.localpart,
|
||||
size: 28,
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
onSelected: _clientSelected,
|
||||
itemBuilder: _bundleMenuItems,
|
||||
|
@ -12,6 +12,8 @@ import 'package:fluffychat/widgets/matrix.dart';
|
||||
|
||||
const kSpacesBottomBarHeight = 56.0;
|
||||
|
||||
final GlobalKey _globalKey = GlobalKey();
|
||||
|
||||
class SpacesBottomBar extends StatelessWidget {
|
||||
final ChatListController controller;
|
||||
|
||||
@ -37,13 +39,16 @@ class SpacesBottomBar extends StatelessWidget {
|
||||
return SingleChildScrollView(
|
||||
controller: controller.snappingSheetScrollContentController,
|
||||
child: AnimatedBuilder(
|
||||
child: _SpacesBottomNavigation(controller: controller),
|
||||
child: _SpacesBottomNavigation(
|
||||
key: _globalKey, controller: controller),
|
||||
builder: (context, child) {
|
||||
if (controller.snappingSheetContainerSize == null) {
|
||||
return child!;
|
||||
}
|
||||
final rawPosition =
|
||||
controller.snappingSheetController.currentPosition;
|
||||
controller.snappingSheetController.isAttached
|
||||
? controller.snappingSheetController.currentPosition
|
||||
: 0;
|
||||
final position = rawPosition /
|
||||
controller.snappingSheetContainerSize!.maxHeight;
|
||||
|
||||
|
@ -77,6 +77,14 @@ class AllRoomsSpacesEntry extends SpacesEntry {
|
||||
|
||||
@override
|
||||
bool shouldShowStoriesHeader(BuildContext context) => true;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return runtimeType == other.runtimeType;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => runtimeType.hashCode;
|
||||
}
|
||||
|
||||
// "Direct Chats" entry.
|
||||
@ -101,6 +109,14 @@ class DirectChatsSpacesEntry extends SpacesEntry {
|
||||
|
||||
@override
|
||||
bool shouldShowStoriesHeader(BuildContext context) => true;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return runtimeType == other.runtimeType;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => runtimeType.hashCode;
|
||||
}
|
||||
|
||||
// "Groups" entry.
|
||||
@ -134,6 +150,14 @@ class GroupsSpacesEntry extends SpacesEntry {
|
||||
bool separatedGroup(Room room, List<Room> spaces) {
|
||||
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.
|
||||
@ -179,12 +203,12 @@ class SpaceSpacesEntry extends SpacesEntry {
|
||||
@override
|
||||
bool stillValid(BuildContext context) =>
|
||||
Matrix.of(context).client.getRoomById(space.id) != null;
|
||||
}
|
||||
|
||||
// Produces a "rough equivalence" for maintaining the current spaces index.
|
||||
bool spacesEntryRoughEquivalence(SpacesEntry a, SpacesEntry b) {
|
||||
if ((a is SpaceSpacesEntry) && (b is SpaceSpacesEntry)) {
|
||||
return a.space.id == b.space.id;
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return hashCode == other.hashCode;
|
||||
}
|
||||
return a == b;
|
||||
|
||||
@override
|
||||
int get hashCode => space.id.hashCode;
|
||||
}
|
||||
|
@ -88,12 +88,13 @@ class SignupPageView extends StatelessWidget {
|
||||
controller.loading ? null : [AutofillHints.username],
|
||||
validator: controller.emailTextFieldValidator,
|
||||
decoration: FluffyThemes.loginTextFieldDecoration(
|
||||
prefixIcon: const Icon(
|
||||
Icons.mail_outlined,
|
||||
color: Colors.black,
|
||||
),
|
||||
hintText: L10n.of(context)!.enterAnEmailAddress,
|
||||
errorText: controller.error),
|
||||
prefixIcon: const Icon(
|
||||
Icons.mail_outlined,
|
||||
color: Colors.black,
|
||||
),
|
||||
hintText: L10n.of(context)!.enterAnEmailAddress,
|
||||
errorText: controller.error,
|
||||
),
|
||||
),
|
||||
),
|
||||
Hero(
|
||||
|
@ -66,6 +66,7 @@ class ContentBanner extends StatelessWidget {
|
||||
imageUrl: src.toString(),
|
||||
height: 300,
|
||||
fit: BoxFit.cover,
|
||||
errorWidget: (c, m, e) => Icon(defaultIcon, size: 200),
|
||||
);
|
||||
})
|
||||
: Icon(defaultIcon, size: 200),
|
||||
|
Loading…
Reference in New Issue
Block a user