diff --git a/lib/pages/chat_list/chat_list_view.dart b/lib/pages/chat_list/chat_list_view.dart index 4391e83b0..510c6c46d 100644 --- a/lib/pages/chat_list/chat_list_view.dart +++ b/lib/pages/chat_list/chat_list_view.dart @@ -30,9 +30,14 @@ class ChatListView extends StatelessWidget { final selectMode = controller.selectMode; return PopScope( canPop: controller.selectMode == SelectMode.normal && - !controller.isSearchMode, + !controller.isSearchMode && + controller.activeSpaceId == null, onPopInvoked: (pop) { if (pop) return; + if (controller.activeSpaceId != null) { + controller.clearActiveSpace(); + return; + } final selMode = controller.selectMode; if (controller.isSearchMode) { controller.cancelSearch(); diff --git a/lib/pages/chat_list/space_view.dart b/lib/pages/chat_list/space_view.dart index 3a7fdcad0..3401aa1f1 100644 --- a/lib/pages/chat_list/space_view.dart +++ b/lib/pages/chat_list/space_view.dart @@ -165,315 +165,310 @@ class _SpaceViewState extends State { final room = Matrix.of(context).client.getRoomById(widget.spaceId); final displayname = room?.getLocalizedDisplayname() ?? L10n.of(context)!.nothingFound; - return PopScope( - canPop: false, - onPopInvoked: (_) => widget.onBack(), - child: Scaffold( - appBar: AppBar( - leading: Center( - child: CloseButton( - onPressed: widget.onBack, - ), + return Scaffold( + appBar: AppBar( + leading: Center( + child: CloseButton( + onPressed: widget.onBack, ), - titleSpacing: 0, - title: ListTile( - contentPadding: EdgeInsets.zero, - leading: Avatar( - mxContent: room?.avatar, - name: displayname, - borderRadius: BorderRadius.circular(AppConfig.borderRadius / 2), - ), - title: Text( - displayname, - maxLines: 1, - overflow: TextOverflow.ellipsis, - ), - subtitle: room == null - ? null - : Text( - L10n.of(context)!.countChatsAndCountParticipants( - room.spaceChildren.length, - room.summary.mJoinedMemberCount ?? 1, - ), - maxLines: 1, - overflow: TextOverflow.ellipsis, - ), + ), + titleSpacing: 0, + title: ListTile( + contentPadding: EdgeInsets.zero, + leading: Avatar( + mxContent: room?.avatar, + name: displayname, + borderRadius: BorderRadius.circular(AppConfig.borderRadius / 2), + ), + title: Text( + displayname, + maxLines: 1, + overflow: TextOverflow.ellipsis, ), - actions: [ - PopupMenuButton( - onSelected: _onSpaceAction, - itemBuilder: (context) => [ - PopupMenuItem( - value: SpaceActions.settings, - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - const Icon(Icons.settings_outlined), - const SizedBox(width: 12), - Text(L10n.of(context)!.settings), - ], + subtitle: room == null + ? null + : Text( + L10n.of(context)!.countChatsAndCountParticipants( + room.spaceChildren.length, + room.summary.mJoinedMemberCount ?? 1, ), + maxLines: 1, + overflow: TextOverflow.ellipsis, ), - PopupMenuItem( - value: SpaceActions.invite, - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - const Icon(Icons.person_add_outlined), - const SizedBox(width: 12), - Text(L10n.of(context)!.invite), - ], - ), + ), + actions: [ + PopupMenuButton( + onSelected: _onSpaceAction, + itemBuilder: (context) => [ + PopupMenuItem( + value: SpaceActions.settings, + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + const Icon(Icons.settings_outlined), + const SizedBox(width: 12), + Text(L10n.of(context)!.settings), + ], ), - PopupMenuItem( - value: SpaceActions.leave, - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - const Icon(Icons.delete_outlined), - const SizedBox(width: 12), - Text(L10n.of(context)!.leave), - ], - ), + ), + PopupMenuItem( + value: SpaceActions.invite, + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + const Icon(Icons.person_add_outlined), + const SizedBox(width: 12), + Text(L10n.of(context)!.invite), + ], ), - ], - ), - ], - ), - body: room == null - ? const Center( - child: Icon( - Icons.search_outlined, - size: 80, + ), + PopupMenuItem( + value: SpaceActions.leave, + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + const Icon(Icons.delete_outlined), + const SizedBox(width: 12), + Text(L10n.of(context)!.leave), + ], ), - ) - : StreamBuilder( - stream: room.client.onSync.stream - .where((s) => s.hasRoomUpdate) - .rateLimit(const Duration(seconds: 1)), - builder: (context, snapshot) { - final childrenIds = room.spaceChildren - .map((c) => c.roomId) - .whereType() - .toSet(); + ), + ], + ), + ], + ), + body: room == null + ? const Center( + child: Icon( + Icons.search_outlined, + size: 80, + ), + ) + : StreamBuilder( + stream: room.client.onSync.stream + .where((s) => s.hasRoomUpdate) + .rateLimit(const Duration(seconds: 1)), + builder: (context, snapshot) { + final childrenIds = room.spaceChildren + .map((c) => c.roomId) + .whereType() + .toSet(); - final joinedRooms = room.client.rooms - .where((room) => childrenIds.remove(room.id)) - .toList(); + final joinedRooms = room.client.rooms + .where((room) => childrenIds.remove(room.id)) + .toList(); - final joinedParents = room.spaceParents - .map((parent) { - final roomId = parent.roomId; - if (roomId == null) return null; - return room.client.getRoomById(roomId); - }) - .whereType() - .toList(); - final filter = _filterController.text.trim().toLowerCase(); - return CustomScrollView( - slivers: [ - SliverAppBar( - floating: true, - toolbarHeight: 72, - scrolledUnderElevation: 0, - backgroundColor: Colors.transparent, - automaticallyImplyLeading: false, - title: TextField( - controller: _filterController, - onChanged: (_) => setState(() {}), - textInputAction: TextInputAction.search, - decoration: InputDecoration( - fillColor: Theme.of(context) + final joinedParents = room.spaceParents + .map((parent) { + final roomId = parent.roomId; + if (roomId == null) return null; + return room.client.getRoomById(roomId); + }) + .whereType() + .toList(); + final filter = _filterController.text.trim().toLowerCase(); + return CustomScrollView( + slivers: [ + SliverAppBar( + floating: true, + toolbarHeight: 72, + scrolledUnderElevation: 0, + backgroundColor: Colors.transparent, + automaticallyImplyLeading: false, + title: TextField( + controller: _filterController, + onChanged: (_) => setState(() {}), + textInputAction: TextInputAction.search, + decoration: InputDecoration( + fillColor: + Theme.of(context).colorScheme.secondaryContainer, + border: OutlineInputBorder( + borderSide: BorderSide.none, + borderRadius: BorderRadius.circular(99), + ), + contentPadding: EdgeInsets.zero, + hintText: L10n.of(context)!.search, + hintStyle: TextStyle( + color: Theme.of(context) .colorScheme - .secondaryContainer, - border: OutlineInputBorder( - borderSide: BorderSide.none, - borderRadius: BorderRadius.circular(99), - ), - contentPadding: EdgeInsets.zero, - hintText: L10n.of(context)!.search, - hintStyle: TextStyle( + .onPrimaryContainer, + fontWeight: FontWeight.normal, + ), + floatingLabelBehavior: FloatingLabelBehavior.never, + prefixIcon: IconButton( + onPressed: () {}, + icon: Icon( + Icons.search_outlined, color: Theme.of(context) .colorScheme .onPrimaryContainer, - fontWeight: FontWeight.normal, - ), - floatingLabelBehavior: FloatingLabelBehavior.never, - prefixIcon: IconButton( - onPressed: () {}, - icon: Icon( - Icons.search_outlined, - color: Theme.of(context) - .colorScheme - .onPrimaryContainer, - ), ), ), ), ), - SliverList.builder( - itemCount: joinedParents.length, - itemBuilder: (context, i) { - final displayname = - joinedParents[i].getLocalizedDisplayname(); - return Padding( - padding: const EdgeInsets.symmetric( - horizontal: 8, - vertical: 1, - ), - child: Material( - borderRadius: - BorderRadius.circular(AppConfig.borderRadius), - clipBehavior: Clip.hardEdge, - child: ListTile( - minVerticalPadding: 0, - leading: Icon( - Icons.adaptive.arrow_back_outlined, - size: 16, - ), - title: Row( - children: [ - Avatar( - mxContent: joinedParents[i].avatar, - name: displayname, - size: Avatar.defaultSize / 2, - borderRadius: BorderRadius.circular( - AppConfig.borderRadius / 4, - ), + ), + SliverList.builder( + itemCount: joinedParents.length, + itemBuilder: (context, i) { + final displayname = + joinedParents[i].getLocalizedDisplayname(); + return Padding( + padding: const EdgeInsets.symmetric( + horizontal: 8, + vertical: 1, + ), + child: Material( + borderRadius: + BorderRadius.circular(AppConfig.borderRadius), + clipBehavior: Clip.hardEdge, + child: ListTile( + minVerticalPadding: 0, + leading: Icon( + Icons.adaptive.arrow_back_outlined, + size: 16, + ), + title: Row( + children: [ + Avatar( + mxContent: joinedParents[i].avatar, + name: displayname, + size: Avatar.defaultSize / 2, + borderRadius: BorderRadius.circular( + AppConfig.borderRadius / 4, ), - const SizedBox(width: 8), - Expanded(child: Text(displayname)), - ], - ), - onTap: () => - widget.toParentSpace(joinedParents[i].id), + ), + const SizedBox(width: 8), + Expanded(child: Text(displayname)), + ], ), + onTap: () => + widget.toParentSpace(joinedParents[i].id), ), + ), + ); + }, + ), + SliverList.builder( + itemCount: joinedRooms.length + 1, + itemBuilder: (context, i) { + if (i == 0) { + return SearchTitle( + title: L10n.of(context)!.joinedChats, + icon: const Icon(Icons.chat_outlined), ); - }, - ), - SliverList.builder( - itemCount: joinedRooms.length + 1, - itemBuilder: (context, i) { - if (i == 0) { - return SearchTitle( - title: L10n.of(context)!.joinedChats, - icon: const Icon(Icons.chat_outlined), - ); - } - i--; - final room = joinedRooms[i]; - return ChatListItem( + } + i--; + final room = joinedRooms[i]; + return ChatListItem( + room, + filter: filter, + onTap: () => widget.onChatTab(room), + onLongPress: (context) => widget.onChatContext( room, - filter: filter, - onTap: () => widget.onChatTab(room), - onLongPress: (context) => widget.onChatContext( - room, - context, - ), - activeChat: widget.activeChat == room.id, + context, + ), + activeChat: widget.activeChat == room.id, + ); + }, + ), + SliverList.builder( + itemCount: _discoveredChildren.length + 2, + itemBuilder: (context, i) { + if (i == 0) { + return SearchTitle( + title: L10n.of(context)!.discover, + icon: const Icon(Icons.explore_outlined), ); - }, - ), - SliverList.builder( - itemCount: _discoveredChildren.length + 2, - itemBuilder: (context, i) { - if (i == 0) { - return SearchTitle( - title: L10n.of(context)!.discover, - icon: const Icon(Icons.explore_outlined), - ); - } - i--; - if (i == _discoveredChildren.length) { - if (_noMoreRooms) { - return Padding( - padding: const EdgeInsets.all(12.0), - child: Center( - child: Text( - L10n.of(context)!.noMoreChatsFound, - style: const TextStyle(fontSize: 13), - ), - ), - ); - } + } + i--; + if (i == _discoveredChildren.length) { + if (_noMoreRooms) { return Padding( - padding: const EdgeInsets.symmetric( - horizontal: 12.0, - vertical: 2.0, - ), - child: TextButton( - onPressed: _isLoading ? null : _loadHierarchy, - child: _isLoading - ? LinearProgressIndicator( - borderRadius: BorderRadius.circular( - AppConfig.borderRadius, - ), - ) - : Text(L10n.of(context)!.loadMore), + padding: const EdgeInsets.all(12.0), + child: Center( + child: Text( + L10n.of(context)!.noMoreChatsFound, + style: const TextStyle(fontSize: 13), + ), ), ); } - final item = _discoveredChildren[i]; - final displayname = item.name ?? - item.canonicalAlias ?? - L10n.of(context)!.emptyChat; - if (!displayname.toLowerCase().contains(filter)) { - return const SizedBox.shrink(); - } return Padding( padding: const EdgeInsets.symmetric( - horizontal: 8, - vertical: 1, + horizontal: 12.0, + vertical: 2.0, ), - child: Material( - borderRadius: - BorderRadius.circular(AppConfig.borderRadius), - clipBehavior: Clip.hardEdge, - child: ListTile( - onTap: () => _joinChildRoom(item), - leading: Avatar( - mxContent: item.avatarUrl, - name: displayname, - borderRadius: item.roomType == 'm.space' - ? BorderRadius.circular( - AppConfig.borderRadius / 2, - ) - : null, - ), - title: Row( - children: [ - Expanded( - child: Text( - displayname, - maxLines: 1, - overflow: TextOverflow.ellipsis, + child: TextButton( + onPressed: _isLoading ? null : _loadHierarchy, + child: _isLoading + ? LinearProgressIndicator( + borderRadius: BorderRadius.circular( + AppConfig.borderRadius, ), + ) + : Text(L10n.of(context)!.loadMore), + ), + ); + } + final item = _discoveredChildren[i]; + final displayname = item.name ?? + item.canonicalAlias ?? + L10n.of(context)!.emptyChat; + if (!displayname.toLowerCase().contains(filter)) { + return const SizedBox.shrink(); + } + return Padding( + padding: const EdgeInsets.symmetric( + horizontal: 8, + vertical: 1, + ), + child: Material( + borderRadius: + BorderRadius.circular(AppConfig.borderRadius), + clipBehavior: Clip.hardEdge, + child: ListTile( + onTap: () => _joinChildRoom(item), + leading: Avatar( + mxContent: item.avatarUrl, + name: displayname, + borderRadius: item.roomType == 'm.space' + ? BorderRadius.circular( + AppConfig.borderRadius / 2, + ) + : null, + ), + title: Row( + children: [ + Expanded( + child: Text( + displayname, + maxLines: 1, + overflow: TextOverflow.ellipsis, ), - const SizedBox(width: 8), - const Icon( - Icons.add_circle_outline_outlined, + ), + const SizedBox(width: 8), + const Icon( + Icons.add_circle_outline_outlined, + ), + ], + ), + subtitle: Text( + item.topic ?? + L10n.of(context)!.countParticipants( + item.numJoinedMembers, ), - ], - ), - subtitle: Text( - item.topic ?? - L10n.of(context)!.countParticipants( - item.numJoinedMembers, - ), - maxLines: 1, - overflow: TextOverflow.ellipsis, - ), + maxLines: 1, + overflow: TextOverflow.ellipsis, ), ), - ); - }, - ), - ], - ); - }, - ), - ), + ), + ); + }, + ), + ], + ); + }, + ), ); } }