From a688e1c38b1feecc9e45fbbd4012c938d0686098 Mon Sep 17 00:00:00 2001 From: WilsonLe Date: Tue, 24 Jun 2025 15:23:20 -0400 Subject: [PATCH 1/2] setup well-known dir for staging --- .github/workflows/main_deploy.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/main_deploy.yaml b/.github/workflows/main_deploy.yaml index d60208739..51dfaa1fe 100644 --- a/.github/workflows/main_deploy.yaml +++ b/.github/workflows/main_deploy.yaml @@ -50,6 +50,11 @@ jobs: cp public/.env public/assets/.env touch public/assets/envs.json echo "$ENV_OVERRIDES" >> public/assets/envs.json + mkdir -p public/.well-known + curl https://app.pangea.chat/.well-known/apple-app-site-association \ + -o public/.well-known/apple-app-site-association + curl https://app.pangea.chat/.well-known/assetlinks.json \ + -o public/.well-known/assetlinks.json - name: Deploy to GitHub Pages uses: peaceiris/actions-gh-pages@v4 with: From f86608bb0a69a45840da0952e86c43a038f8183d Mon Sep 17 00:00:00 2001 From: ggurdin <46800240+ggurdin@users.noreply.github.com> Date: Tue, 24 Jun 2025 16:21:35 -0400 Subject: [PATCH 2/2] Revert "chore: add fake event to show when activity ended" --- lib/pages/chat/chat_event_list.dart | 27 -- lib/pages/chat/events/message.dart | 4 - .../activities/activity_state_event.dart | 333 +++++++++--------- .../events/constants/pangea_event_types.dart | 1 - .../filtered_timeline_extension.dart | 31 +- 5 files changed, 190 insertions(+), 206 deletions(-) diff --git a/lib/pages/chat/chat_event_list.dart b/lib/pages/chat/chat_event_list.dart index 030f81422..948c0578b 100644 --- a/lib/pages/chat/chat_event_list.dart +++ b/lib/pages/chat/chat_event_list.dart @@ -1,7 +1,6 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -import 'package:matrix/matrix.dart'; import 'package:scroll_to_index/scroll_to_index.dart'; import 'package:fluffychat/config/app_config.dart'; @@ -11,9 +10,7 @@ import 'package:fluffychat/pages/chat/events/message.dart'; import 'package:fluffychat/pages/chat/seen_by_row.dart'; import 'package:fluffychat/pages/chat/typing_indicators.dart'; import 'package:fluffychat/pangea/activity_planner/activity_plan_message.dart'; -import 'package:fluffychat/pangea/events/constants/pangea_event_types.dart'; import 'package:fluffychat/pangea/events/extensions/pangea_event_extension.dart'; -import 'package:fluffychat/pangea/extensions/pangea_room_extension.dart'; import 'package:fluffychat/utils/account_config.dart'; import 'package:fluffychat/utils/matrix_sdk_extensions/filtered_timeline_extension.dart'; import 'package:fluffychat/utils/platform_infos.dart'; @@ -43,30 +40,6 @@ class ChatEventList extends StatelessWidget { final horizontalPadding = FluffyThemes.isColumnMode(context) ? 8.0 : 0.0; final events = timeline.events.filterByVisibleInGui(); - // #Pangea - if (timeline.room.activityPlan?.endAt != null && - timeline.room.activityPlan!.endAt!.isBefore(DateTime.now())) { - final eventIndex = events.indexWhere( - (e) => e.originServerTs.isBefore( - timeline.room.activityPlan!.endAt!, - ), - ); - - if (eventIndex != -1) { - events.insert( - eventIndex, - Event( - type: PangeaEventTypes.activityPlanEnd, - eventId: timeline.room.client.generateUniqueTransactionId(), - senderId: timeline.room.client.userID!, - originServerTs: timeline.room.activityPlan!.endAt!, - room: timeline.room, - content: {}, - ), - ); - } - } - // Pangea# final animateInEventIndex = controller.animateInEventIndex; // create a map of eventId --> index to greatly improve performance of diff --git a/lib/pages/chat/events/message.dart b/lib/pages/chat/events/message.dart index 30d787343..0fd7e79bc 100644 --- a/lib/pages/chat/events/message.dart +++ b/lib/pages/chat/events/message.dart @@ -134,10 +134,6 @@ class Message extends StatelessWidget { ? ActivityStateEvent(event: event) : const SizedBox(); } - - if (event.type == PangeaEventTypes.activityPlanEnd) { - return const ActivityFinishedEvent(); - } // Pangea# return StateMessage(event); } diff --git a/lib/pangea/activities/activity_state_event.dart b/lib/pangea/activities/activity_state_event.dart index b59b8c233..1f7a250e5 100644 --- a/lib/pangea/activities/activity_state_event.dart +++ b/lib/pangea/activities/activity_state_event.dart @@ -57,6 +57,11 @@ class ActivityStateEventState extends State { } } + bool get _activityIsOver { + return activityPlan?.endAt != null && + DateTime.now().isAfter(activityPlan!.endAt!); + } + @override Widget build(BuildContext context) { if (activityPlan == null) { @@ -78,151 +83,186 @@ class ActivityStateEventState extends State { spacing: 12.0, children: [ Container( - padding: const EdgeInsets.all(16.0), + padding: EdgeInsets.all(_activityIsOver ? 24.0 : 16.0), decoration: BoxDecoration( color: theme.colorScheme.primaryContainer, borderRadius: BorderRadius.circular(18), ), child: AnimatedSize( duration: FluffyThemes.animationDuration, - child: Text( - activityPlan!.markdown, - style: TextStyle( - color: theme.colorScheme.onPrimaryContainer, - fontSize: - AppConfig.fontSizeFactor * AppConfig.messageFontSize, - ), - ), + child: _activityIsOver + ? Column( + spacing: 12.0, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + L10n.of(context).activityEnded, + style: TextStyle( + color: theme.colorScheme.onPrimaryContainer, + fontSize: 16.0, + ), + ), + CachedNetworkImage( + width: 120.0, + imageUrl: + "${AppConfig.assetsBaseURL}/${ActivityConstants.activityFinishedAsset}", + fit: BoxFit.cover, + placeholder: (context, url) => const Center( + child: CircularProgressIndicator(), + ), + errorWidget: (context, url, error) => + const SizedBox(), + ), + ], + ) + : Text( + activityPlan!.markdown, + style: TextStyle( + color: theme.colorScheme.onPrimaryContainer, + fontSize: AppConfig.fontSizeFactor * + AppConfig.messageFontSize, + ), + ), ), ), AnimatedSize( duration: FluffyThemes.animationDuration, - child: IntrinsicHeight( - child: Row( - spacing: 12.0, - children: [ - Container( - height: imageWidth, - width: imageWidth, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(16), - ), - child: ClipRRect( - borderRadius: BorderRadius.circular(16), - child: activityPlan!.imageURL != null - ? activityPlan!.imageURL!.startsWith("mxc") - ? MxcImage( - uri: Uri.parse( - activityPlan!.imageURL!, - ), - width: imageWidth, - height: imageWidth, - cacheKey: activityPlan!.bookmarkId, - fit: BoxFit.cover, - ) - : CachedNetworkImage( - imageUrl: activityPlan!.imageURL!, - fit: BoxFit.cover, - placeholder: (context, url) => const Center( - child: CircularProgressIndicator(), - ), - errorWidget: ( - context, - url, - error, - ) => - const SizedBox(), - ) - : const SizedBox(), - ), - ), - Expanded( - child: Column( - spacing: 9.0, - mainAxisSize: MainAxisSize.max, + child: _activityIsOver + ? const SizedBox() + : IntrinsicHeight( + child: Row( + spacing: 12.0, children: [ - Expanded( - child: SizedBox.expand( - child: ElevatedButton( - style: ElevatedButton.styleFrom( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(20), - ), - backgroundColor: - theme.colorScheme.primaryContainer, - foregroundColor: - theme.colorScheme.onPrimaryContainer, - ), - onPressed: () async { - final Duration? duration = await showDialog( - context: context, - builder: (context) { - return ActivityDurationPopup( - initialValue: activityPlan?.duration ?? - const Duration(days: 1), - ); - }, - ); - - if (duration == null) return; - - showFutureLoadingDialog( - context: context, - future: () => - widget.event.room.sendActivityPlan( - activityPlan!.copyWith( - endAt: DateTime.now().add(duration), - duration: duration, - ), - ), - ); - }, - child: CountDown( - deadline: activityPlan!.endAt, - iconSize: 20.0, - textSize: 16.0, - ), - ), + Container( + height: imageWidth, + width: imageWidth, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(16), ), - ), // Optional spacing between buttons + child: ClipRRect( + borderRadius: BorderRadius.circular(16), + child: activityPlan!.imageURL != null + ? activityPlan!.imageURL!.startsWith("mxc") + ? MxcImage( + uri: Uri.parse( + activityPlan!.imageURL!, + ), + width: imageWidth, + height: imageWidth, + cacheKey: activityPlan!.bookmarkId, + fit: BoxFit.cover, + ) + : CachedNetworkImage( + imageUrl: activityPlan!.imageURL!, + fit: BoxFit.cover, + placeholder: (context, url) => + const Center( + child: CircularProgressIndicator(), + ), + errorWidget: ( + context, + url, + error, + ) => + const SizedBox(), + ) + : const SizedBox(), + ), + ), Expanded( - child: SizedBox.expand( - child: ElevatedButton( - style: ElevatedButton.styleFrom( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(20), - ), - backgroundColor: theme.colorScheme.error, - foregroundColor: theme.colorScheme.onPrimary, - ), - onPressed: () { - showFutureLoadingDialog( - context: context, - future: () => - widget.event.room.sendActivityPlan( - activityPlan!.copyWith( - endAt: DateTime.now(), - duration: Duration.zero, + child: Column( + spacing: 9.0, + mainAxisSize: MainAxisSize.max, + children: [ + Expanded( + child: SizedBox.expand( + child: ElevatedButton( + style: ElevatedButton.styleFrom( + shape: RoundedRectangleBorder( + borderRadius: + BorderRadius.circular(20), + ), + backgroundColor: + theme.colorScheme.primaryContainer, + foregroundColor: theme + .colorScheme.onPrimaryContainer, + ), + onPressed: () async { + final Duration? duration = + await showDialog( + context: context, + builder: (context) { + return ActivityDurationPopup( + initialValue: + activityPlan?.duration ?? + const Duration(days: 1), + ); + }, + ); + + if (duration == null) return; + + showFutureLoadingDialog( + context: context, + future: () => widget.event.room + .sendActivityPlan( + activityPlan!.copyWith( + endAt: + DateTime.now().add(duration), + duration: duration, + ), + ), + ); + }, + child: CountDown( + deadline: activityPlan!.endAt, + iconSize: 20.0, + textSize: 16.0, + ), + ), + ), + ), // Optional spacing between buttons + Expanded( + child: SizedBox.expand( + child: ElevatedButton( + style: ElevatedButton.styleFrom( + shape: RoundedRectangleBorder( + borderRadius: + BorderRadius.circular(20), + ), + backgroundColor: + theme.colorScheme.error, + foregroundColor: + theme.colorScheme.onPrimary, + ), + onPressed: () { + showFutureLoadingDialog( + context: context, + future: () => widget.event.room + .sendActivityPlan( + activityPlan!.copyWith( + endAt: DateTime.now(), + duration: Duration.zero, + ), + ), + ); + }, + child: Text( + L10n.of(context).endNow, + style: const TextStyle( + fontSize: 24, + fontWeight: FontWeight.bold, + ), ), ), - ); - }, - child: Text( - L10n.of(context).endNow, - style: const TextStyle( - fontSize: 24, - fontWeight: FontWeight.bold, ), ), - ), + ], ), ), ], ), ), - ], - ), - ), ), ], ), @@ -230,50 +270,3 @@ class ActivityStateEventState extends State { ); } } - -class ActivityFinishedEvent extends StatelessWidget { - const ActivityFinishedEvent({super.key}); - - @override - Widget build(BuildContext context) { - final theme = Theme.of(context); - return Center( - child: Container( - constraints: const BoxConstraints( - maxWidth: 400.0, - ), - margin: const EdgeInsets.all(18.0), - child: Container( - padding: const EdgeInsets.all(24.0), - decoration: BoxDecoration( - color: theme.colorScheme.primaryContainer, - borderRadius: BorderRadius.circular(18), - ), - child: Column( - spacing: 12.0, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - L10n.of(context).activityEnded, - style: TextStyle( - color: theme.colorScheme.onPrimaryContainer, - fontSize: 16.0, - ), - ), - CachedNetworkImage( - width: 120.0, - imageUrl: - "${AppConfig.assetsBaseURL}/${ActivityConstants.activityFinishedAsset}", - fit: BoxFit.cover, - placeholder: (context, url) => const Center( - child: CircularProgressIndicator(), - ), - errorWidget: (context, url, error) => const SizedBox(), - ), - ], - ), - ), - ), - ); - } -} diff --git a/lib/pangea/events/constants/pangea_event_types.dart b/lib/pangea/events/constants/pangea_event_types.dart index a385fe97d..fe2a47e18 100644 --- a/lib/pangea/events/constants/pangea_event_types.dart +++ b/lib/pangea/events/constants/pangea_event_types.dart @@ -26,7 +26,6 @@ class PangeaEventTypes { static const capacity = "pangea.capacity"; static const activityPlan = "pangea.activity_plan"; - static const activityPlanEnd = "pangea.activity.end"; static const userAge = "pangea.user_age"; diff --git a/lib/utils/matrix_sdk_extensions/filtered_timeline_extension.dart b/lib/utils/matrix_sdk_extensions/filtered_timeline_extension.dart index d762a4dcc..f074a43f1 100644 --- a/lib/utils/matrix_sdk_extensions/filtered_timeline_extension.dart +++ b/lib/utils/matrix_sdk_extensions/filtered_timeline_extension.dart @@ -5,9 +5,33 @@ import 'package:fluffychat/pangea/events/constants/pangea_event_types.dart'; import '../../config/app_config.dart'; extension VisibleInGuiExtension on List { - List filterByVisibleInGui({String? exceptionEventId}) => where( - (event) => event.isVisibleInGui || event.eventId == exceptionEventId, - ).toList(); + List filterByVisibleInGui({String? exceptionEventId}) { + final visibleEvents = + where((e) => e.isVisibleInGui || e.eventId == exceptionEventId) + .toList(); + + // Hide creation state events: + if (visibleEvents.isNotEmpty && + visibleEvents.last.type == EventTypes.RoomCreate) { + var i = visibleEvents.length - 2; + while (i > 0) { + final event = visibleEvents[i]; + if (!event.isState) break; + if (event.type == EventTypes.Encryption) { + i--; + continue; + } + if (event.type == EventTypes.RoomMember && + event.roomMemberChangeType == RoomMemberChangeType.acceptInvite) { + i--; + continue; + } + visibleEvents.removeAt(i); + i--; + } + } + return visibleEvents; + } } extension IsStateExtension on Event { @@ -65,7 +89,6 @@ extension IsStateExtension on Event { EventTypes.RoomTombstone, EventTypes.CallInvite, PangeaEventTypes.activityPlan, - PangeaEventTypes.activityPlanEnd, }; // Pangea# }