Skip to content

Commit ad93454

Browse files
authored
Merge branch 'main' into 1949-changing-it-feedback
2 parents 80b73c4 + 1b80f12 commit ad93454

29 files changed

+1417
-634
lines changed

assets/l10n/intl_en.arb

+17-2
Original file line numberDiff line numberDiff line change
@@ -4813,5 +4813,20 @@
48134813
"pleaseEnterInt": "Please enter a number",
48144814
"home": "Home",
48154815
"join": "Join",
4816-
"learnByTexting": "Learn by texting"
4817-
}
4816+
"learnByTexting": "Learn by texting",
4817+
"levelSummaryTrigger": "View summary",
4818+
"levelSummaryPopupTitle": "Level {level} Summary",
4819+
"@levelSummaryPopupTitle": {
4820+
"type": "String",
4821+
"placeholders": {
4822+
"level": {
4823+
"type": "int"
4824+
}
4825+
}
4826+
},
4827+
"startChatting": "Start chatting",
4828+
"referFriends": "Refer friends",
4829+
"referFriendDialogTitle": "Invite a friend to your conversation",
4830+
"referFriendDialogDesc": "Do you have a friend who is excited to learn a new language with you? Then copy and send this invitation link to join and start chatting with you today.",
4831+
"youUnlocked": "You've unlocked"
4832+
}

assets/l10n/intl_vi.arb

+10
Original file line numberDiff line numberDiff line change
@@ -3793,5 +3793,15 @@
37933793
"@createASpace": {
37943794
"type": "String",
37953795
"placeholders": {}
3796+
},
3797+
"levelSummaryTrigger": "Đọc báo cáo",
3798+
"levelSummaryPopupTitle": "Tóm tắt cấp {level}",
3799+
"@levelSummaryPopupTitle": {
3800+
"type": "String",
3801+
"placeholders": {
3802+
"level": {
3803+
"type": "int"
3804+
}
3805+
}
37963806
}
37973807
}

lib/config/routes.dart

+22-7
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import 'package:fluffychat/pangea/activity_planner/activity_planner_page.dart';
3333
import 'package:fluffychat/pangea/activity_suggestions/suggestions_page.dart';
3434
import 'package:fluffychat/pangea/guard/p_vguard.dart';
3535
import 'package:fluffychat/pangea/layouts/bottom_nav_layout.dart';
36+
import 'package:fluffychat/pangea/learning_settings/pages/settings_learning.dart';
3637
import 'package:fluffychat/pangea/login/pages/login_or_signup_view.dart';
3738
import 'package:fluffychat/pangea/login/pages/signup.dart';
3839
import 'package:fluffychat/pangea/login/pages/user_settings.dart';
@@ -492,6 +493,17 @@ abstract class AppRoutes {
492493
],
493494
),
494495
// #Pangea
496+
GoRoute(
497+
path: 'learning',
498+
pageBuilder: (context, state) => defaultPageBuilder(
499+
context,
500+
state,
501+
const SettingsLearning(
502+
isDialog: false,
503+
),
504+
),
505+
redirect: loggedOutRedirect,
506+
),
495507
GoRoute(
496508
path: 'subscription',
497509
pageBuilder: (context, state) => defaultPageBuilder(
@@ -680,11 +692,14 @@ abstract class AppRoutes {
680692
GoRouterState state,
681693
Widget child,
682694
) =>
683-
FluffyThemes.isColumnMode(context)
684-
? noTransitionPageBuilder(context, state, child)
685-
: MaterialPage(
686-
key: state.pageKey,
687-
restorationId: state.pageKey.value,
688-
child: child,
689-
);
695+
// #Pangea
696+
noTransitionPageBuilder(context, state, child);
697+
// FluffyThemes.isColumnMode(context)
698+
// ? noTransitionPageBuilder(context, state, child)
699+
// : MaterialPage(
700+
// key: state.pageKey,
701+
// restorationId: state.pageKey.value,
702+
// child: child,
703+
// );
704+
// Pangea#
690705
}

lib/pages/chat/chat.dart

+33-11
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import 'package:fluffychat/pages/chat_details/chat_details.dart';
3030
import 'package:fluffychat/pangea/analytics_misc/constructs_model.dart';
3131
import 'package:fluffychat/pangea/analytics_misc/level_up.dart';
3232
import 'package:fluffychat/pangea/analytics_misc/put_analytics_controller.dart';
33+
import 'package:fluffychat/pangea/chat/utils/unlocked_morphs_snackbar.dart';
3334
import 'package:fluffychat/pangea/chat/widgets/event_too_large_dialog.dart';
3435
import 'package:fluffychat/pangea/choreographer/controllers/choreographer.dart';
3536
import 'package:fluffychat/pangea/choreographer/enums/edit_type.dart';
@@ -365,18 +366,39 @@ class ChatController extends State<ChatPageWithRoom>
365366

366367
_levelSubscription = pangeaController.getAnalytics.stateStream
367368
.where(
368-
(update) =>
369-
update is Map<String, dynamic> && update['level_up'] != null,
370-
)
369+
(update) =>
370+
update is Map<String, dynamic> &&
371+
(update['level_up'] != null || update['unlocked_constructs'] != null),
372+
)
373+
// .listen(
374+
// (update) => Future.delayed(
375+
// const Duration(milliseconds: 500),
376+
// () => LevelUpUtil.showLevelUpDialog(
377+
// update['level_up'],
378+
// context,
379+
// ),
380+
// ),
381+
// )
371382
.listen(
372-
(update) => Future.delayed(
373-
const Duration(milliseconds: 500),
374-
() => LevelUpUtil.showLevelUpDialog(
375-
update['level_up'],
376-
context,
377-
),
378-
),
379-
);
383+
// remove delay now that GetAnalyticsController._onLevelUp
384+
// is async is should take roughly 500ms to make requests anyway
385+
(update) {
386+
if (update['level_up'] != null) {
387+
LevelUpUtil.showLevelUpDialog(
388+
update['level_up'],
389+
update['analytics_room_id'],
390+
update["construct_summary_state_event_id"],
391+
update['construct_summary'],
392+
context,
393+
);
394+
} else if (update['unlocked_constructs'] != null) {
395+
showUnlockedMorphsSnackbar(
396+
update['unlocked_constructs'],
397+
context,
398+
);
399+
}
400+
},
401+
);
380402
// Pangea#
381403
_tryLoadTimeline();
382404
if (kIsWeb) {

lib/pages/invitation_selection/invitation_selection.dart

+87-74
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,82 @@ class InvitationSelectionController extends State<InvitationSelection> {
3434

3535
String? get roomId => widget.roomId;
3636

37+
// #Pangea
38+
List<User>? get participants {
39+
final room = Matrix.of(context).client.getRoomById(roomId!);
40+
return room?.getParticipants();
41+
}
42+
43+
List<Membership> get _membershipOrder => [
44+
Membership.join,
45+
Membership.invite,
46+
Membership.knock,
47+
Membership.leave,
48+
Membership.ban,
49+
];
50+
51+
String? membershipCopy(Membership? membership) => switch (membership) {
52+
Membership.ban => L10n.of(context).banned,
53+
Membership.invite => L10n.of(context).invited,
54+
Membership.join => null,
55+
Membership.knock => L10n.of(context).knocking,
56+
Membership.leave => L10n.of(context).leftTheChat,
57+
null => null,
58+
};
59+
60+
int _sortUsers(User a, User b) {
61+
// sort yourself to the top
62+
final client = Matrix.of(context).client;
63+
if (a.id == client.userID) return -1;
64+
if (b.id == client.userID) return 1;
65+
66+
// sort the bot to the bottom
67+
if (a.id == BotName.byEnvironment) return 1;
68+
if (b.id == BotName.byEnvironment) return -1;
69+
70+
if (participants != null) {
71+
final participantA = participants!.firstWhereOrNull((u) => u.id == a.id);
72+
final participantB = participants!.firstWhereOrNull((u) => u.id == b.id);
73+
// sort all participants first, with admins first, then moderators, then the rest
74+
if (participantA?.membership == null &&
75+
participantB?.membership != null) {
76+
return 1;
77+
}
78+
if (participantA?.membership != null &&
79+
participantB?.membership == null) {
80+
return -1;
81+
}
82+
if (participantA?.membership != null &&
83+
participantB?.membership != null) {
84+
final aIndex = _membershipOrder.indexOf(participantA!.membership);
85+
final bIndex = _membershipOrder.indexOf(participantB!.membership);
86+
if (aIndex != bIndex) {
87+
return aIndex.compareTo(bIndex);
88+
}
89+
}
90+
}
91+
92+
// finally, sort by displayname
93+
final aName = a.calcDisplayname().toLowerCase();
94+
final bName = b.calcDisplayname().toLowerCase();
95+
return aName.compareTo(bName);
96+
}
97+
// Pangea#
98+
3799
Future<List<User>> getContacts(BuildContext context) async {
38100
final client = Matrix.of(context).client;
39101
final room = client.getRoomById(roomId!)!;
40102

41103
final participants = (room.summary.mJoinedMemberCount ?? 0) > 100
42104
? room.getParticipants()
43-
: await room.requestParticipants();
105+
// #Pangea
106+
// : await room.requestParticipants();
107+
: await room.requestParticipants(
108+
[Membership.join, Membership.invite, Membership.knock],
109+
false,
110+
true,
111+
);
112+
// Pangea#
44113
participants.removeWhere(
45114
(u) => ![Membership.join, Membership.invite].contains(u.membership),
46115
);
@@ -53,16 +122,26 @@ class InvitationSelectionController extends State<InvitationSelection> {
53122
.getParticipants()
54123
.firstWhereOrNull((u) => u.id != client.userID),
55124
)
125+
.where((u) => u != null)
126+
.cast<User>()
56127
// Pangea#
57128
.toList();
58129
// #Pangea
59-
contacts.removeWhere((u) => u == null || u.id != BotName.byEnvironment);
60-
contacts.sort(
61-
(a, b) => a!.calcDisplayname().toLowerCase().compareTo(
62-
b!.calcDisplayname().toLowerCase(),
63-
),
64-
);
65-
return contacts.cast<User>();
130+
final mutuals = client.rooms
131+
.where((r) => r.isSpace)
132+
.map((r) => r.getParticipants())
133+
.expand((element) => element)
134+
.toList();
135+
136+
for (final user in mutuals) {
137+
final index = contacts.indexWhere((u) => u.id == user.id);
138+
if (index == -1) {
139+
contacts.add(user);
140+
}
141+
}
142+
143+
contacts.sort(_sortUsers);
144+
return contacts;
66145
// contacts.sort(
67146
// (a, b) => a.calcDisplayname().toLowerCase().compareTo(
68147
// b.calcDisplayname().toLowerCase(),
@@ -72,72 +151,6 @@ class InvitationSelectionController extends State<InvitationSelection> {
72151
//Pangea#
73152
}
74153

75-
//#Pangea
76-
// // add all students (already local) from spaceParents who aren't already in room to eligibleStudents
77-
// // use room.members to get all users in room
78-
// bool _initialized = false;
79-
// Future<List<User>> eligibleStudents(
80-
// BuildContext context,
81-
// String text,
82-
// ) async {
83-
// if (!_initialized) {
84-
// _initialized = true;
85-
// await requestParentSpaceParticipants();
86-
// }
87-
88-
// final eligibleStudents = <User>[];
89-
// final spaceParents = room?.pangeaSpaceParents;
90-
// if (spaceParents == null) return eligibleStudents;
91-
92-
// final userId = Matrix.of(context).client.userID;
93-
// for (final Room space in spaceParents) {
94-
// eligibleStudents.addAll(
95-
// space.getParticipants().where(
96-
// (spaceUser) =>
97-
// spaceUser.id != BotName.byEnvironment &&
98-
// spaceUser.id != "@support:staging.pangea.chat" &&
99-
// spaceUser.id != userId &&
100-
// (text.isEmpty ||
101-
// (spaceUser.displayName
102-
// ?.toLowerCase()
103-
// .contains(text.toLowerCase()) ??
104-
// false) ||
105-
// spaceUser.id.toLowerCase().contains(text.toLowerCase())),
106-
// ),
107-
// );
108-
// }
109-
// return eligibleStudents;
110-
// }
111-
112-
// Future<SearchUserDirectoryResponse>
113-
// eligibleStudentsAsSearchUserDirectoryResponse(
114-
// BuildContext context,
115-
// String text,
116-
// ) async {
117-
// return SearchUserDirectoryResponse(
118-
// results: (await eligibleStudents(context, text))
119-
// .map(
120-
// (e) => Profile(
121-
// userId: e.id,
122-
// avatarUrl: e.avatarUrl,
123-
// displayName: e.displayName,
124-
// ),
125-
// )
126-
// .toList(),
127-
// limited: false,
128-
// );
129-
// }
130-
131-
// List<User?> studentsInRoom(BuildContext context) =>
132-
// room
133-
// ?.getParticipants()
134-
// .where(
135-
// (u) => [Membership.join, Membership.invite].contains(u.membership),
136-
// )
137-
// .toList() ??
138-
// <User>[];
139-
//Pangea#
140-
141154
void inviteAction(BuildContext context, String id, String displayname) async {
142155
final room = Matrix.of(context).client.getRoomById(roomId!)!;
143156

0 commit comments

Comments
 (0)