Merge pull request #4585 from pangeachat/4578-emotes-on-lemmas-in-activity-description-appear-selectable-on-web

4578 emotes on lemmas in activity description appear selectable on web
This commit is contained in:
ggurdin 2025-11-03 10:11:19 -05:00 committed by GitHub
commit cb997cd0fc
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 184 additions and 174 deletions

View file

@ -77,48 +77,51 @@ class ActivityFinishedStatusMessage extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.center,
children: controller.room.isActivityFinished
? [
if (summary?.isLoading ?? false) ...[
Text(
L10n.of(context).generatingSummary,
style: const TextStyle(
fontStyle: FontStyle.italic,
if (summary?.summary == null) ...[
if (summary?.isLoading ?? false) ...[
Text(
L10n.of(context).generatingSummary,
style: const TextStyle(
fontStyle: FontStyle.italic,
),
),
),
const SizedBox(
height: 36.0,
width: 36.0,
child: CircularProgressIndicator(),
),
] else if (isSubscribed == false)
ErrorIndicator(
message: L10n.of(context)
.subscribeToUnlockActivitySummaries,
onTap: () {
MatrixState.pangeaController.subscriptionController
.showPaywall(context);
},
)
else if (summary?.hasError ?? false) ...[
Row(
mainAxisSize: MainAxisSize.min,
children: [
const Icon(
Icons.school_outlined,
size: 24.0,
),
const SizedBox(width: 8),
Flexible(
child: Text(
L10n.of(context).activitySummaryError,
textAlign: TextAlign.center,
const SizedBox(
height: 36.0,
width: 36.0,
child: CircularProgressIndicator(),
),
] else if (isSubscribed == false)
ErrorIndicator(
message: L10n.of(context)
.subscribeToUnlockActivitySummaries,
onTap: () {
MatrixState
.pangeaController.subscriptionController
.showPaywall(context);
},
)
else if (summary?.hasError ?? false) ...[
Row(
mainAxisSize: MainAxisSize.min,
children: [
const Icon(
Icons.school_outlined,
size: 24.0,
),
),
],
),
TextButton(
onPressed: () => controller.room.fetchSummaries(),
child: Text(L10n.of(context).requestSummaries),
),
const SizedBox(width: 8),
Flexible(
child: Text(
L10n.of(context).activitySummaryError,
textAlign: TextAlign.center,
),
),
],
),
TextButton(
onPressed: () => controller.room.fetchSummaries(),
child: Text(L10n.of(context).requestSummaries),
),
],
],
if (!controller.room.hasArchivedActivity) ...[
Text(

View file

@ -122,146 +122,151 @@ class CourseSettings extends StatelessWidget {
return Column(
spacing: isColumnMode ? 40.0 : 36.0,
mainAxisSize: MainAxisSize.min,
children: controller.course!.topicIds.mapIndexed((index, topicId) {
final topic = controller.course!.loadedTopics[topicId];
if (topic == null) {
return const SizedBox();
}
children: [
...controller.course!.topicIds.mapIndexed((index, topicId) {
final topic = controller.course!.loadedTopics[topicId];
if (topic == null) {
return const SizedBox();
}
final usersInTopic = userTopics[topicId] ?? [];
final activityError = controller.activityErrors[topicId];
final usersInTopic = userTopics[topicId] ?? [];
final activityError = controller.activityErrors[topicId];
final bool locked = topicIndex == null ? false : index > topicIndex;
final disabled =
locked || controller.loadingActivities || activityError != null;
return AbsorbPointer(
absorbing: disabled,
child: Opacity(
opacity: disabled ? 0.5 : 1.0,
child: Column(
spacing: 12.0,
mainAxisSize: MainAxisSize.min,
children: [
LayoutBuilder(
builder: (context, constraints) {
return Row(
spacing: 8.0,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Flexible(
child: Row(
spacing: 4.0,
mainAxisSize: MainAxisSize.min,
children: [
Stack(
children: [
ClipPath(
clipper: PinClipper(),
child: ImageByUrl(
imageUrl: topic.imageUrl,
width: 54.0,
replacement: Container(
final bool locked = topicIndex == null ? false : index > topicIndex;
final disabled =
locked || controller.loadingActivities || activityError != null;
return AbsorbPointer(
absorbing: disabled,
child: Opacity(
opacity: disabled ? 0.5 : 1.0,
child: Column(
spacing: 12.0,
mainAxisSize: MainAxisSize.min,
children: [
LayoutBuilder(
builder: (context, constraints) {
return Row(
spacing: 8.0,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Flexible(
child: Row(
spacing: 4.0,
mainAxisSize: MainAxisSize.min,
children: [
Stack(
children: [
ClipPath(
clipper: PinClipper(),
child: ImageByUrl(
imageUrl: topic.imageUrl,
width: 54.0,
replacement: Container(
width: 54.0,
height: 54.0,
decoration: BoxDecoration(
color: theme.colorScheme.secondary,
),
),
),
),
if (locked)
const Positioned(
bottom: 0,
right: 0,
child: Icon(Icons.lock, size: 24.0),
)
else if (controller.loadingActivities)
const SizedBox(
width: 54.0,
height: 54.0,
decoration: BoxDecoration(
color: theme.colorScheme.secondary,
),
),
),
),
if (locked)
const Positioned(
bottom: 0,
right: 0,
child: Icon(Icons.lock, size: 24.0),
)
else if (controller.loadingActivities)
const SizedBox(
width: 54.0,
height: 54.0,
child:
CircularProgressIndicator.adaptive(),
),
],
),
Flexible(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
topic.title,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: titleFontSize,
),
),
if (topic.location != null)
CourseInfoChip(
icon: Icons.location_on,
text: topic.location!,
fontSize: descFontSize,
iconSize: iconSize,
),
if (constraints.maxWidth < 700.0)
Padding(
padding:
const EdgeInsetsGeometry.symmetric(
vertical: 4.0,
),
child: TopicParticipantList(
room: room,
users: usersInTopic,
avatarSize:
isColumnMode ? 50.0 : 25.0,
overlap: isColumnMode ? 20.0 : 8.0,
),
child: CircularProgressIndicator
.adaptive(),
),
],
),
),
],
),
),
if (constraints.maxWidth >= 700.0)
TopicParticipantList(
room: room,
users: usersInTopic,
avatarSize: isColumnMode ? 50.0 : 25.0,
overlap: isColumnMode ? 20.0 : 8.0,
),
],
);
},
),
if (!locked)
controller.loadingActivities
? ActivityCardPlaceholder(
activityCount: topic.activityIds.length,
)
: activityError != null
? ErrorIndicator(
message: L10n.of(context).oopsSomethingWentWrong,
)
: topic.loadedActivities.isNotEmpty
? SizedBox(
height: isColumnMode ? 290.0 : 210.0,
child: TopicActivitiesList(
room: room,
activities: topic.loadedActivities,
loading: controller.loadingCourseSummary,
hasCompletedActivity:
controller.hasCompletedActivity,
Flexible(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
topic.title,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: titleFontSize,
),
),
if (topic.location != null)
CourseInfoChip(
icon: Icons.location_on,
text: topic.location!,
fontSize: descFontSize,
iconSize: iconSize,
),
if (constraints.maxWidth < 700.0)
Padding(
padding: const EdgeInsetsGeometry
.symmetric(
vertical: 4.0,
),
child: TopicParticipantList(
room: room,
users: usersInTopic,
avatarSize:
isColumnMode ? 50.0 : 25.0,
overlap: isColumnMode ? 20.0 : 8.0,
),
),
],
),
)
: const SizedBox(),
],
),
],
),
),
if (constraints.maxWidth >= 700.0)
TopicParticipantList(
room: room,
users: usersInTopic,
avatarSize: isColumnMode ? 50.0 : 25.0,
overlap: isColumnMode ? 20.0 : 8.0,
),
],
);
},
),
if (!locked)
controller.loadingActivities
? ActivityCardPlaceholder(
activityCount: topic.activityIds.length,
)
: activityError != null
? ErrorIndicator(
message:
L10n.of(context).oopsSomethingWentWrong,
)
: topic.loadedActivities.isNotEmpty
? SizedBox(
height: isColumnMode ? 290.0 : 210.0,
child: TopicActivitiesList(
room: room,
activities: topic.loadedActivities,
loading: controller.loadingCourseSummary,
hasCompletedActivity:
controller.hasCompletedActivity,
),
)
: const SizedBox(),
],
),
),
),
);
}).toList(),
);
}),
const SizedBox(height: 16.0),
],
);
}
}

View file

@ -4,7 +4,7 @@ import 'package:fluffychat/pangea/toolbar/reading_assistance_input_row/lemma_emo
class LemmaEmojiPicker extends StatelessWidget {
final List<String> emojis;
final Function(String) onSelect;
final Function(String)? onSelect;
final bool loading;
final Function(String)? disabled;
@ -36,7 +36,9 @@ class LemmaEmojiPicker extends StatelessWidget {
opacity: isDisabled ? 0.33 : 1,
child: LemmaEmojiChoiceItem(
content: emoji,
onTap: isDisabled ? null : () => onSelect(emoji),
onTap: isDisabled || onSelect == null
? null
: () => onSelect!(emoji),
),
);
}).toList(),

View file

@ -75,7 +75,7 @@ class LemmaReactionPicker extends StatelessWidget {
return LemmaEmojiPicker(
emojis: emojis,
onSelect: (emoji) => setEmoji(emoji, context),
onSelect: event != null ? (emoji) => setEmoji(emoji, context) : null,
disabled: (emoji) => sentReactions.contains(emoji),
loading: loading,
);