Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: space sort & categorization #1323

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion assets/l10n/intl_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -2761,5 +2761,8 @@
"discoverHomeservers": "Discover homeservers",
"whatIsAHomeserver": "What is a homeserver?",
"homeserverDescription": "All your data is stored on the homeserver, just like an email provider. You can choose which homeserver you want to use, while you can still communicate with everyone. Learn more at at https://matrix.org.",
"doesNotSeemToBeAValidHomeserver": "Doesn't seem to be a compatible homeserver. Wrong URL?"
"doesNotSeemToBeAValidHomeserver": "Doesn't seem to be a compatible homeserver. Wrong URL?",
"spaceViewNormal": "Normal",
"spaceViewRoomTop": "Rooms on top",
"spaceViewCategorized": "Categorize"
}
5 changes: 4 additions & 1 deletion assets/l10n/intl_zh.arb
Original file line number Diff line number Diff line change
Expand Up @@ -2803,5 +2803,8 @@
"homeserverDescription": "主服务器上就像电子邮件提供商,你的所有数据都存储在上面。你可以选择你想使用哪个主服务器。在 https://matrix.org 上了解更多信息。",
"@homeserverDescription": {},
"doesNotSeemToBeAValidHomeserver": "似乎不是兼容的主服务器。URL 不正确?",
"@doesNotSeemToBeAValidHomeserver": {}
"@doesNotSeemToBeAValidHomeserver": {},
"spaceViewNormal": "正常",
"spaceViewRoomTop": "聊天室置顶",
"spaceViewCategorized": "分类"
}
5 changes: 4 additions & 1 deletion assets/l10n/intl_zh_Hant.arb
Original file line number Diff line number Diff line change
Expand Up @@ -2763,5 +2763,8 @@
"placeholders": {
"user": {}
}
}
},
"spaceViewNormal": "正常",
"spaceViewRoomTop": "聊天室置頂",
"spaceViewCategorized": "分類"
}
3 changes: 3 additions & 0 deletions lib/config/app_config.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import 'dart:collection';
import 'dart:ui';

import 'package:matrix/matrix.dart';
Expand Down Expand Up @@ -54,6 +55,8 @@ abstract class AppConfig {
static bool? sendOnEnter;
static bool showPresences = true;
static bool experimentalVoip = false;
static Map<String, int> spaceViewOptions = {};
static Set<String> collapsedSpace = HashSet();
static const bool hideTypingUsernames = false;
static const bool hideAllStateEvents = false;
static const String inviteLinkPrefix = 'https://matrix.to/#/';
Expand Down
2 changes: 2 additions & 0 deletions lib/config/setting_keys.dart
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,6 @@ abstract class SettingKeys {
'chat.fluffy.display_chat_details_column';
static const String noEncryptionWarningShown =
'chat.fluffy.no_encryption_warning_shown';
static const String spaceViewOptions = 'chat.fluffy.space_view_options';
static const String collapsedSpace = 'chat.fluffy.collapsed_space';
}
208 changes: 208 additions & 0 deletions lib/pages/chat_list/chat_list_space_item.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
import 'package:flutter/material.dart';

import 'package:adaptive_dialog/adaptive_dialog.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:future_loading_dialog/future_loading_dialog.dart';
import 'package:matrix/matrix.dart';

import 'package:fluffychat/pages/chat_list/chat_list_item.dart';
import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_locals.dart';
import 'package:fluffychat/widgets/hover_builder.dart';
import '../../config/themes.dart';
import '../../widgets/avatar.dart';

class ChatListSpaceItem extends StatelessWidget {
final Room room;
final List<Room> rooms;
final String? activeChat;

final void Function(BuildContext context)? onLongPress;
final void Function(Room room, BuildContext context)? onLongPressDeep;
final void Function()? onForget;
final void Function(Room room) onTapDeep;
final void Function(bool expanded)? onExpansionChanged;
final String? filter;
final bool defaultExpanded;

const ChatListSpaceItem(
this.room,
this.rooms, {
required this.activeChat,
required this.onTapDeep,
this.onLongPress,
this.onLongPressDeep,
this.onForget,
this.onExpansionChanged,
this.filter,
this.defaultExpanded = true,
super.key,
});

Future<void> archiveAction(BuildContext context) async {
{
if ([Membership.leave, Membership.ban].contains(room.membership)) {
await showFutureLoadingDialog(
context: context,
future: () => room.forget(),
);
return;
}
final confirmed = await showOkCancelAlertDialog(
useRootNavigator: false,
context: context,
title: L10n.of(context)!.areYouSure,
okLabel: L10n.of(context)!.yes,
cancelLabel: L10n.of(context)!.no,
message: L10n.of(context)!.archiveRoomDescription,
);
if (confirmed == OkCancelResult.cancel) return;
await showFutureLoadingDialog(
context: context,
future: () => room.leave(),
);
return;
}
}

@override
Widget build(BuildContext context) {
final activeChat = this.activeChat == room.id;

final theme = Theme.of(context);

final isMuted = room.pushRuleState != PushRuleState.notify;
final directChatMatrixId = room.directChatMatrixID;
final hasNotifications = room.notificationCount > 0;
final backgroundColor =
activeChat ? theme.colorScheme.secondaryContainer : null;
final displayname = room.getLocalizedDisplayname(
MatrixLocals(L10n.of(context)!),
);
final filter = this.filter;
if (filter != null && !displayname.toLowerCase().contains(filter)) {
return const SizedBox.shrink();
}

return Padding(
padding: const EdgeInsets.symmetric(
horizontal: 8,
vertical: 1,
),
child: Material(
shape: Border(
top: BorderSide(
color: theme.dividerColor,
width: 1,
),
bottom: BorderSide(
color: theme.dividerColor,
width: 1,
),
),
clipBehavior: Clip.hardEdge,
color: backgroundColor,
child: HoverBuilder(
builder: (context, listTileHovered) => GestureDetector(
onLongPress: () => onLongPress?.call(context),
child: ExpansionTile(
initiallyExpanded: defaultExpanded,
visualDensity: const VisualDensity(vertical: -0.5),
leading: HoverBuilder(
builder: (context, hovered) => AnimatedScale(
duration: FluffyThemes.animationDuration,
curve: FluffyThemes.animationCurve,
scale: hovered ? 1.1 : 1.0,
child: SizedBox(
width: Avatar.defaultSize * 0.5,
height: Avatar.defaultSize * 0.5,
child: Stack(
children: [
Positioned(
bottom: 0,
right: 0,
child: Avatar(
border: null,
borderRadius: null,
mxContent: room.avatar,
size: Avatar.defaultSize * 0.5,
name: displayname,
presenceUserId: directChatMatrixId,
presenceBackgroundColor: backgroundColor,
onTap: () => onLongPress?.call(context),
),
),
],
),
),
),
),
title: Row(
children: <Widget>[
Expanded(
child: Text(
displayname,
maxLines: 1,
overflow: TextOverflow.ellipsis,
softWrap: false,
style: const TextStyle(
fontWeight: FontWeight.bold, fontSize: 12),
),
),
if (isMuted)
const Padding(
padding: EdgeInsets.only(left: 4.0),
child: Icon(
Icons.notifications_off_outlined,
size: 16,
),
),
if (room.isFavourite ||
room.membership == Membership.invite)
Padding(
padding: EdgeInsets.only(
right: hasNotifications ? 4.0 : 0.0,
),
child: Icon(
Icons.push_pin,
size: 16,
color: theme.colorScheme.primary,
),
),
],
),
onExpansionChanged: onExpansionChanged,
trailing: onForget == null
? null
: IconButton(
icon: const Icon(Icons.delete_outlined),
onPressed: onForget,
),
children: [
/*CustomScrollView(
slivers: [*/
ListView.builder(
shrinkWrap: true,
itemCount: rooms.length,
itemBuilder: (context, i) {
final room = rooms[i];
return ChatListItem(
room,
filter: filter,
onTap: () => onTapDeep(room),
onLongPress: (context) => onLongPressDeep?.call(
room,
context,
),
activeChat: this.activeChat == room.id,
);
},
),
/*],
),*/
],
),
)),
),
);
}
}
Loading