chore: don't lazy load members, account for left memebers when determ… (#3653)
* chore: don't lazy load members, account for left memebers when determining if activity is finished * chore: always show continue button in unfinished activities
This commit is contained in:
parent
0ac33f96fa
commit
867004243f
13 changed files with 176 additions and 205 deletions
|
|
@ -202,11 +202,6 @@ class ChatView extends StatelessWidget {
|
|||
if (scrollUpBannerEventId != null) {
|
||||
appbarBottomHeight += ChatAppBarListTile.fixedHeight;
|
||||
}
|
||||
// #Pangea
|
||||
if (controller.room.isActiveInActivity) {
|
||||
appbarBottomHeight += ChatAppBarListTile.fixedHeight;
|
||||
}
|
||||
// Pangea#
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
// #Pangea
|
||||
|
|
@ -281,9 +276,6 @@ class ChatView extends StatelessWidget {
|
|||
child: Text(L10n.of(context).jump),
|
||||
),
|
||||
),
|
||||
// #Pangea
|
||||
ActivityPinnedMessage(controller),
|
||||
// Pangea#
|
||||
],
|
||||
),
|
||||
),
|
||||
|
|
@ -474,6 +466,7 @@ class ChatView extends StatelessWidget {
|
|||
],
|
||||
),
|
||||
),
|
||||
ActivityPinnedMessage(controller),
|
||||
// Pangea#
|
||||
],
|
||||
),
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import 'package:matrix/matrix.dart';
|
|||
|
||||
import 'package:fluffychat/config/app_config.dart';
|
||||
import 'package:fluffychat/l10n/l10n.dart';
|
||||
import 'package:fluffychat/pangea/activity_planner/activity_room_extension.dart';
|
||||
import 'package:fluffychat/pangea/instructions/instructions_enum.dart';
|
||||
import 'package:fluffychat/pangea/instructions/instructions_inline_tooltip.dart';
|
||||
import 'package:fluffychat/utils/date_time_extension.dart';
|
||||
|
|
@ -66,6 +67,9 @@ class RoomCreationStateEventState extends State<RoomCreationStateEvent> {
|
|||
// child: ConstrainedBox(
|
||||
child: Column(
|
||||
children: [
|
||||
// https://github.com/pangeachat/client/issues/3639
|
||||
if (widget.event.room.isActiveInActivity)
|
||||
const SizedBox(height: 60.0),
|
||||
ConstrainedBox(
|
||||
// Pangea#
|
||||
constraints: const BoxConstraints(maxWidth: 256),
|
||||
|
|
|
|||
|
|
@ -38,6 +38,10 @@ class ActivityFinishedStatusMessageState
|
|||
void initState() {
|
||||
super.initState();
|
||||
_setDefaultHighlightedRole();
|
||||
|
||||
if (widget.room.activityIsFinished && widget.room.activitySummary == null) {
|
||||
widget.room.fetchSummaries();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
|||
|
|
@ -73,111 +73,119 @@ class ActivityPinnedMessageState extends State<ActivityPinnedMessage> {
|
|||
final theme = Theme.of(context);
|
||||
final isColumnMode = FluffyThemes.isColumnMode(context);
|
||||
|
||||
return Column(
|
||||
children: [
|
||||
AnimatedContainer(
|
||||
duration: FluffyThemes.animationDuration,
|
||||
decoration: BoxDecoration(
|
||||
color: _showDropdown
|
||||
? theme.colorScheme.surfaceContainerHighest
|
||||
: theme.colorScheme.surface,
|
||||
),
|
||||
child: ChatAppBarListTile(
|
||||
title: "🎯 ${room.activityPlan!.learningObjective}",
|
||||
leading: const SizedBox(width: 18.0),
|
||||
trailing: Padding(
|
||||
padding: const EdgeInsets.only(right: 12.0),
|
||||
child: ElevatedButton(
|
||||
onPressed: _showDropdown ? null : () => _setShowDropdown(true),
|
||||
style: ElevatedButton.styleFrom(
|
||||
minimumSize: Size.zero,
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 12.0,
|
||||
vertical: 4.0,
|
||||
return Positioned(
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: _showDropdown ? 0 : null,
|
||||
child: Column(
|
||||
children: [
|
||||
AnimatedContainer(
|
||||
duration: FluffyThemes.animationDuration,
|
||||
decoration: BoxDecoration(
|
||||
color: _showDropdown
|
||||
? theme.colorScheme.surfaceContainerHighest
|
||||
: theme.colorScheme.surface,
|
||||
),
|
||||
child: ChatAppBarListTile(
|
||||
title: "🎯 ${room.activityPlan!.learningObjective}",
|
||||
leading: const SizedBox(width: 18.0),
|
||||
trailing: Padding(
|
||||
padding: const EdgeInsets.only(right: 12.0),
|
||||
child: ElevatedButton(
|
||||
onPressed:
|
||||
_showDropdown ? null : () => _setShowDropdown(true),
|
||||
style: ElevatedButton.styleFrom(
|
||||
minimumSize: Size.zero,
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 12.0,
|
||||
vertical: 4.0,
|
||||
),
|
||||
backgroundColor: AppConfig.yellowDark,
|
||||
foregroundColor: theme.colorScheme.surface,
|
||||
disabledBackgroundColor:
|
||||
AppConfig.yellowDark.withAlpha(100),
|
||||
disabledForegroundColor:
|
||||
theme.colorScheme.surface.withAlpha(100),
|
||||
),
|
||||
backgroundColor: AppConfig.yellowDark,
|
||||
foregroundColor: theme.colorScheme.surface,
|
||||
disabledBackgroundColor: AppConfig.yellowDark.withAlpha(100),
|
||||
disabledForegroundColor:
|
||||
theme.colorScheme.surface.withAlpha(100),
|
||||
),
|
||||
child: Text(
|
||||
L10n.of(context).endActivityTitle,
|
||||
style: const TextStyle(
|
||||
fontSize: 16.0,
|
||||
fontWeight: FontWeight.w900,
|
||||
child: Text(
|
||||
L10n.of(context).endActivityTitle,
|
||||
style: const TextStyle(
|
||||
fontSize: 16.0,
|
||||
fontWeight: FontWeight.w900,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
onTap: _scrollToActivity,
|
||||
),
|
||||
onTap: _scrollToActivity,
|
||||
),
|
||||
),
|
||||
AnimatedSize(
|
||||
duration: FluffyThemes.animationDuration,
|
||||
curve: Curves.easeInOut,
|
||||
child: ClipRect(
|
||||
child: _showDropdown
|
||||
? Container(
|
||||
decoration: BoxDecoration(
|
||||
color: theme.colorScheme.surfaceContainerHighest,
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 12.0,
|
||||
vertical: 16.0,
|
||||
),
|
||||
child: Column(
|
||||
spacing: 12.0,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
L10n.of(context).endActivityDesc,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: isColumnMode ? 16.0 : 12.0,
|
||||
),
|
||||
),
|
||||
CachedNetworkImage(
|
||||
imageUrl:
|
||||
"${AppConfig.assetsBaseURL}/${ActivitySuggestionsConstants.endActivityAssetPath}",
|
||||
width: isColumnMode ? 240.0 : 120.0,
|
||||
),
|
||||
ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 12.0,
|
||||
vertical: 8.0,
|
||||
AnimatedSize(
|
||||
duration: FluffyThemes.animationDuration,
|
||||
curve: Curves.easeInOut,
|
||||
child: ClipRect(
|
||||
child: _showDropdown
|
||||
? Container(
|
||||
decoration: BoxDecoration(
|
||||
color: theme.colorScheme.surfaceContainerHighest,
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 12.0,
|
||||
vertical: 16.0,
|
||||
),
|
||||
child: Column(
|
||||
spacing: 12.0,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
L10n.of(context).endActivityDesc,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: isColumnMode ? 16.0 : 12.0,
|
||||
),
|
||||
foregroundColor: theme.colorScheme.onSecondary,
|
||||
backgroundColor: theme.colorScheme.secondary,
|
||||
),
|
||||
onPressed: _finishActivity,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
L10n.of(context).endActivityTitle,
|
||||
style: TextStyle(
|
||||
fontSize: isColumnMode ? 16.0 : 12.0,
|
||||
),
|
||||
CachedNetworkImage(
|
||||
imageUrl:
|
||||
"${AppConfig.assetsBaseURL}/${ActivitySuggestionsConstants.endActivityAssetPath}",
|
||||
width: isColumnMode ? 240.0 : 120.0,
|
||||
),
|
||||
ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 12.0,
|
||||
vertical: 8.0,
|
||||
),
|
||||
],
|
||||
foregroundColor: theme.colorScheme.onSecondary,
|
||||
backgroundColor: theme.colorScheme.secondary,
|
||||
),
|
||||
onPressed: _finishActivity,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
L10n.of(context).endActivityTitle,
|
||||
style: TextStyle(
|
||||
fontSize: isColumnMode ? 16.0 : 12.0,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
: const SizedBox.shrink(),
|
||||
),
|
||||
),
|
||||
if (_showDropdown)
|
||||
Expanded(
|
||||
child: GestureDetector(
|
||||
onTap: () => _setShowDropdown(false),
|
||||
child: Container(color: Colors.black.withAlpha(100)),
|
||||
],
|
||||
),
|
||||
)
|
||||
: const SizedBox.shrink(),
|
||||
),
|
||||
),
|
||||
],
|
||||
if (_showDropdown)
|
||||
Expanded(
|
||||
child: GestureDetector(
|
||||
onTap: () => _setShowDropdown(false),
|
||||
child: Container(color: Colors.black.withAlpha(100)),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import 'dart:math';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/activity_planner/activity_plan_model.dart';
|
||||
|
|
@ -262,7 +263,17 @@ extension ActivityRoomExtension on Room {
|
|||
activityRole(client.userID!)?.isFinished ?? false;
|
||||
|
||||
bool get activityIsFinished {
|
||||
return activityRoles.isNotEmpty && activityRoles.every((r) => r.isFinished);
|
||||
return activityRoles.isNotEmpty &&
|
||||
activityRoles.every((r) {
|
||||
if (r.isFinished) return true;
|
||||
|
||||
// if the user is in the chat (not null && membership is join),
|
||||
// then the activity is not finished for them
|
||||
final user = getParticipants().firstWhereOrNull(
|
||||
(u) => u.id == r.userId,
|
||||
);
|
||||
return user == null || user.membership != Membership.join;
|
||||
});
|
||||
}
|
||||
|
||||
int? get numberOfParticipants {
|
||||
|
|
|
|||
|
|
@ -31,19 +31,22 @@ class ActivityUnfinishedStatusMessageState
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final unassignedRoles = widget.room.remainingRoles;
|
||||
debugPrint("HELLO. remainingRoles: ${widget.room.remainingRoles}");
|
||||
|
||||
final theme = Theme.of(context);
|
||||
final isColumnMode = FluffyThemes.isColumnMode(context);
|
||||
|
||||
final remainingRoles = widget.room.remainingRoles;
|
||||
final completed = widget.room.hasCompletedActivity;
|
||||
|
||||
return Column(
|
||||
children: [
|
||||
if (!widget.room.hasCompletedActivity) ...[
|
||||
if (unassignedRoles > 0)
|
||||
if (!completed) ...[
|
||||
if (remainingRoles > 0)
|
||||
Wrap(
|
||||
spacing: 12.0,
|
||||
runSpacing: 12.0,
|
||||
children: List.generate(unassignedRoles, (index) {
|
||||
children: List.generate(remainingRoles, (index) {
|
||||
return ActivityParticipantIndicator(
|
||||
selected: _selectedRole == index,
|
||||
onTap: () => _selectRole(index),
|
||||
|
|
@ -52,7 +55,7 @@ class ActivityUnfinishedStatusMessageState
|
|||
),
|
||||
const SizedBox(height: 16.0),
|
||||
Text(
|
||||
unassignedRoles > 0
|
||||
remainingRoles > 0
|
||||
? L10n.of(context).unjoinedActivityMessage
|
||||
: L10n.of(context).fullActivityMessage,
|
||||
textAlign: TextAlign.center,
|
||||
|
|
@ -62,45 +65,44 @@ class ActivityUnfinishedStatusMessageState
|
|||
),
|
||||
const SizedBox(height: 16.0),
|
||||
],
|
||||
if (unassignedRoles > 0)
|
||||
ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 12.0,
|
||||
vertical: 8.0,
|
||||
),
|
||||
foregroundColor: theme.colorScheme.onPrimaryContainer,
|
||||
backgroundColor: theme.colorScheme.primaryContainer,
|
||||
),
|
||||
onPressed: widget.room.hasCompletedActivity
|
||||
? () {
|
||||
showFutureLoadingDialog(
|
||||
context: context,
|
||||
future: widget.room.continueActivity,
|
||||
);
|
||||
}
|
||||
: _selectedRole != null
|
||||
? () {
|
||||
showFutureLoadingDialog(
|
||||
context: context,
|
||||
future: widget.room.startActivity,
|
||||
);
|
||||
}
|
||||
: null,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
widget.room.hasCompletedActivity
|
||||
? L10n.of(context).continueText
|
||||
: L10n.of(context).confirmRole,
|
||||
style: TextStyle(
|
||||
fontSize: isColumnMode ? 16.0 : 12.0,
|
||||
),
|
||||
),
|
||||
],
|
||||
ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 12.0,
|
||||
vertical: 8.0,
|
||||
),
|
||||
foregroundColor: theme.colorScheme.onPrimaryContainer,
|
||||
backgroundColor: theme.colorScheme.primaryContainer,
|
||||
),
|
||||
onPressed: completed
|
||||
? () {
|
||||
showFutureLoadingDialog(
|
||||
context: context,
|
||||
future: widget.room.continueActivity,
|
||||
);
|
||||
}
|
||||
: _selectedRole != null
|
||||
? () {
|
||||
showFutureLoadingDialog(
|
||||
context: context,
|
||||
future: widget.room.startActivity,
|
||||
);
|
||||
}
|
||||
: null,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
completed
|
||||
? L10n.of(context).continueText
|
||||
: L10n.of(context).confirmRole,
|
||||
style: TextStyle(
|
||||
fontSize: isColumnMode ? 16.0 : 12.0,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -108,17 +108,6 @@ extension AnalyticsClientExtension on Client {
|
|||
}
|
||||
}
|
||||
|
||||
Future<void> loadAnalyticsRequests() async {
|
||||
if (prevBatch == null) await onSync.stream.first;
|
||||
if (userID == null || userID == BotName.byEnvironment) return;
|
||||
|
||||
for (final analyticsRoom in allMyAnalyticsRooms) {
|
||||
if (!isLogged()) return;
|
||||
analyticsRoom.requestParticipants([Membership.knock], false, true);
|
||||
analyticsRoom.postLoad();
|
||||
}
|
||||
}
|
||||
|
||||
/// Space admins join analytics rooms in spaces via the space hierarchy,
|
||||
/// so other members of the space need to add their analytics rooms to the space.
|
||||
Future<void> addAnalyticsRoomsToSpaces() async {
|
||||
|
|
|
|||
|
|
@ -78,7 +78,6 @@ class GetAnalyticsController extends BaseController {
|
|||
await GetStorage.init("analytics_storage");
|
||||
_client.updateAnalyticsRoomJoinRules();
|
||||
_client.addAnalyticsRoomsToSpaces();
|
||||
_client.loadAnalyticsRequests();
|
||||
|
||||
_analyticsUpdateSubscription ??= _pangeaController
|
||||
.putAnalytics.analyticsUpdateStream.stream
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ class PangeaInvitationSelectionController
|
|||
extends State<PangeaInvitationSelection> {
|
||||
TextEditingController controller = TextEditingController();
|
||||
|
||||
bool loading = true;
|
||||
bool loading = false;
|
||||
|
||||
List<Profile> foundProfiles = [];
|
||||
Timer? coolDown;
|
||||
|
|
@ -103,34 +103,6 @@ class PangeaInvitationSelectionController
|
|||
searchUser(context, '');
|
||||
}
|
||||
|
||||
_room?.requestParticipants(
|
||||
[
|
||||
Membership.join,
|
||||
Membership.invite,
|
||||
Membership.knock,
|
||||
],
|
||||
false,
|
||||
true,
|
||||
).then((_) {
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
loading = false;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
spaceParent?.requestParticipants(
|
||||
[
|
||||
Membership.join,
|
||||
Membership.invite,
|
||||
Membership.knock,
|
||||
],
|
||||
false,
|
||||
true,
|
||||
).then((_) {
|
||||
if (mounted) setState(() {});
|
||||
});
|
||||
|
||||
controller.addListener(() {
|
||||
setState(() {});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -230,12 +230,6 @@ class SpaceAnalyticsState extends State<SpaceAnalytics> {
|
|||
}
|
||||
|
||||
Future<void> _loadProfiles() async {
|
||||
await room?.requestParticipants(
|
||||
[Membership.join],
|
||||
false,
|
||||
true,
|
||||
);
|
||||
|
||||
final futures = _availableUsers.map((u) async {
|
||||
final resp = await MatrixState.pangeaController.userController
|
||||
.getPublicProfile(u.id);
|
||||
|
|
|
|||
|
|
@ -51,12 +51,6 @@ class LoadParticipantsUtilState extends State<LoadParticipantsUtil> {
|
|||
error = null;
|
||||
});
|
||||
|
||||
await widget.space.requestParticipants(
|
||||
[Membership.join, Membership.invite, Membership.knock],
|
||||
false,
|
||||
true,
|
||||
);
|
||||
|
||||
await _cacheLevels();
|
||||
} catch (err, s) {
|
||||
error = err.toString();
|
||||
|
|
|
|||
|
|
@ -48,11 +48,12 @@ class KnockingUsersIndicatorState extends State<KnockingUsersIndicator> {
|
|||
super.dispose();
|
||||
}
|
||||
|
||||
Future<void> _setKnockingUsers({bool loadParticipants = false}) async {
|
||||
_knockingUsers = loadParticipants
|
||||
? await widget.room.requestParticipants([Membership.knock])
|
||||
: widget.room.getParticipants([Membership.knock]);
|
||||
if (mounted) setState(() {});
|
||||
void _setKnockingUsers() {
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_knockingUsers = widget.room.getParticipants([Membership.knock]);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
|||
|
|
@ -129,12 +129,13 @@ abstract class ClientManager {
|
|||
// #Pangea
|
||||
// The things in this list will be loaded in the first sync, without having
|
||||
// to postLoad to confirm that these state events are completely loaded
|
||||
EventTypes.RoomPowerLevels,
|
||||
EventTypes.RoomJoinRules,
|
||||
EventTypes.RoomMember,
|
||||
PangeaEventTypes.rules,
|
||||
PangeaEventTypes.botOptions,
|
||||
PangeaEventTypes.capacity,
|
||||
EventTypes.RoomPowerLevels,
|
||||
PangeaEventTypes.userSetLemmaInfo,
|
||||
EventTypes.RoomJoinRules,
|
||||
PangeaEventTypes.activityPlan,
|
||||
PangeaEventTypes.activityRole,
|
||||
PangeaEventTypes.activitySummary,
|
||||
|
|
@ -161,7 +162,6 @@ abstract class ClientManager {
|
|||
// #Pangea
|
||||
syncFilter: Filter(
|
||||
room: RoomFilter(
|
||||
state: StateFilter(lazyLoadMembers: true),
|
||||
timeline: StateFilter(
|
||||
notTypes: [
|
||||
PangeaEventTypes.construct,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue