chore: replace some instruction popups with inline tooltips (#2452)
This commit is contained in:
parent
0ab43aa7f1
commit
3abfffd227
6 changed files with 78 additions and 163 deletions
|
|
@ -46,7 +46,6 @@ import 'package:fluffychat/pangea/events/models/pangea_token_model.dart';
|
|||
import 'package:fluffychat/pangea/events/models/representation_content_model.dart';
|
||||
import 'package:fluffychat/pangea/events/models/tokens_event_content_model.dart';
|
||||
import 'package:fluffychat/pangea/extensions/pangea_room_extension.dart';
|
||||
import 'package:fluffychat/pangea/instructions/empty_chat_popup.dart';
|
||||
import 'package:fluffychat/pangea/instructions/instructions_enum.dart';
|
||||
import 'package:fluffychat/pangea/learning_settings/widgets/p_language_dialog.dart';
|
||||
import 'package:fluffychat/pangea/toolbar/enums/message_mode_enum.dart';
|
||||
|
|
@ -1923,13 +1922,6 @@ class ChatController extends State<ChatPageWithRoom>
|
|||
final theme = Theme.of(context);
|
||||
return Row(
|
||||
children: [
|
||||
// #Pangea
|
||||
EmptyChatPopup(
|
||||
room: room,
|
||||
transformTargetId:
|
||||
choreographer.inputLayerLinkAndKey.transformTargetId,
|
||||
),
|
||||
// Pangea#
|
||||
Expanded(
|
||||
child: ChatView(this),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -12,8 +12,6 @@ import 'package:fluffychat/pages/chat/typing_indicators.dart';
|
|||
import 'package:fluffychat/pages/user_bottom_sheet/user_bottom_sheet.dart';
|
||||
import 'package:fluffychat/pangea/activity_planner/activity_plan_message.dart';
|
||||
import 'package:fluffychat/pangea/events/extensions/pangea_event_extension.dart';
|
||||
import 'package:fluffychat/pangea/instructions/instructions_enum.dart';
|
||||
import 'package:fluffychat/pangea/instructions/instructions_show_popup.dart';
|
||||
import 'package:fluffychat/utils/account_config.dart';
|
||||
import 'package:fluffychat/utils/adaptive_bottom_sheet.dart';
|
||||
import 'package:fluffychat/utils/matrix_sdk_extensions/filtered_timeline_extension.dart';
|
||||
|
|
@ -59,24 +57,6 @@ class ChatEventList extends StatelessWidget {
|
|||
final hasWallpaper =
|
||||
controller.room.client.applicationAccountConfig.wallpaperUrl != null;
|
||||
|
||||
// #Pangea
|
||||
// after the chat event list mounts, if the user hasn't yet seen this instruction
|
||||
// card, attach it on top of the first shown message
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
final msgEvents = events
|
||||
.where(
|
||||
(event) => event.type == EventTypes.Message,
|
||||
)
|
||||
.toList();
|
||||
if (msgEvents.isEmpty) return;
|
||||
instructionsShowPopup(
|
||||
context,
|
||||
InstructionsEnum.clickMessage,
|
||||
msgEvents[0].eventId,
|
||||
);
|
||||
});
|
||||
// Pangea#
|
||||
|
||||
return SelectionArea(
|
||||
child: ListView.custom(
|
||||
padding: EdgeInsets.only(
|
||||
|
|
|
|||
|
|
@ -1,17 +1,57 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
||||
import 'package:fluffychat/config/app_config.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';
|
||||
import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_locals.dart';
|
||||
import 'package:fluffychat/widgets/avatar.dart';
|
||||
|
||||
class RoomCreationStateEvent extends StatelessWidget {
|
||||
// #Pangea
|
||||
// class RoomCreationStateEvent extends StatelessWidget {
|
||||
class RoomCreationStateEvent extends StatefulWidget {
|
||||
// Pangea#
|
||||
final Event event;
|
||||
const RoomCreationStateEvent({required this.event, super.key});
|
||||
|
||||
// #Pangea
|
||||
@override
|
||||
State<RoomCreationStateEvent> createState() => RoomCreationStateEventState();
|
||||
}
|
||||
|
||||
class RoomCreationStateEventState extends State<RoomCreationStateEvent> {
|
||||
Event get event => widget.event;
|
||||
StreamSubscription? _memberSubscription;
|
||||
|
||||
int get _members =>
|
||||
(event.room.summary.mJoinedMemberCount ?? 0) +
|
||||
(event.room.summary.mInvitedMemberCount ?? 0);
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_memberSubscription = event.room.client.onRoomState.stream.where(
|
||||
(u) {
|
||||
return u.roomId == event.room.id &&
|
||||
u.state.type == EventTypes.RoomMember;
|
||||
},
|
||||
).listen((_) {
|
||||
if (_members > 1) setState(() {});
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_memberSubscription?.cancel();
|
||||
super.dispose();
|
||||
}
|
||||
// Pangea#
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final l10n = L10n.of(context);
|
||||
|
|
@ -46,6 +86,26 @@ class RoomCreationStateEvent extends StatelessWidget {
|
|||
'${event.originServerTs.localizedTime(context)} | ${l10n.countParticipants((event.room.summary.mJoinedMemberCount ?? 1) + (event.room.summary.mInvitedMemberCount ?? 0))}',
|
||||
style: theme.textTheme.labelSmall,
|
||||
),
|
||||
// #Pangea
|
||||
InstructionsInlineTooltip(
|
||||
instructionsEnum: InstructionsEnum.clickMessage,
|
||||
padding: const EdgeInsets.only(
|
||||
left: 16.0,
|
||||
right: 16.0,
|
||||
top: 16.0,
|
||||
),
|
||||
onClose: () => setState(() {}),
|
||||
),
|
||||
if (_members <= 1 && InstructionsEnum.clickMessage.isToggledOff)
|
||||
const InstructionsInlineTooltip(
|
||||
instructionsEnum: InstructionsEnum.emptyChatWarning,
|
||||
padding: EdgeInsets.only(
|
||||
left: 16.0,
|
||||
right: 16.0,
|
||||
top: 16.0,
|
||||
),
|
||||
),
|
||||
// Pangea#
|
||||
],
|
||||
),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -1,61 +1,9 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/common/controllers/pangea_controller.dart';
|
||||
import 'package:fluffychat/pangea/instructions/instructions_enum.dart';
|
||||
import 'package:fluffychat/pangea/instructions/instructions_show_popup.dart';
|
||||
import 'package:fluffychat/widgets/matrix.dart';
|
||||
import '../../bot/widgets/bot_face_svg.dart';
|
||||
import '../controllers/choreographer.dart';
|
||||
import '../controllers/it_controller.dart';
|
||||
|
||||
class ITCloseButton extends StatelessWidget {
|
||||
const ITCloseButton({
|
||||
super.key,
|
||||
required this.choreographer,
|
||||
});
|
||||
|
||||
final Choreographer choreographer;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return IconButton(
|
||||
icon: const Icon(Icons.close_outlined),
|
||||
onPressed: () {
|
||||
if (choreographer.itController.isEditingSourceText) {
|
||||
choreographer.itController.setIsEditingSourceText(false);
|
||||
} else {
|
||||
choreographer.itController.closeIT();
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class ITBotButton extends StatelessWidget {
|
||||
const ITBotButton({super.key, required this.choreographer});
|
||||
|
||||
final Choreographer choreographer;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
instructionsShowPopup(
|
||||
context,
|
||||
InstructionsEnum.itInstructions,
|
||||
choreographer.itBotTransformTargetKey,
|
||||
);
|
||||
|
||||
return IconButton(
|
||||
icon: const BotFace(width: 40.0, expression: BotExpression.idle),
|
||||
onPressed: () => instructionsShowPopup(
|
||||
context,
|
||||
InstructionsEnum.itInstructions,
|
||||
choreographer.itBotTransformTargetKey,
|
||||
showToggle: false,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class ITRestartButton extends StatelessWidget {
|
||||
ITRestartButton({
|
||||
super.key,
|
||||
|
|
|
|||
|
|
@ -1,69 +0,0 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/instructions/instructions_enum.dart';
|
||||
import 'package:fluffychat/pangea/instructions/instructions_show_popup.dart';
|
||||
import 'package:fluffychat/widgets/matrix.dart';
|
||||
|
||||
class EmptyChatPopup extends StatefulWidget {
|
||||
const EmptyChatPopup({
|
||||
super.key,
|
||||
required this.room,
|
||||
required this.transformTargetId,
|
||||
});
|
||||
|
||||
final Room room;
|
||||
final String transformTargetId;
|
||||
|
||||
@override
|
||||
State<EmptyChatPopup> createState() => EmptyChatPopupState();
|
||||
}
|
||||
|
||||
class EmptyChatPopupState extends State<EmptyChatPopup> {
|
||||
StreamSubscription? _memberSubscription;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
if ((widget.room.summary.mJoinedMemberCount ?? 0) +
|
||||
(widget.room.summary.mInvitedMemberCount ?? 0) ==
|
||||
1) {
|
||||
WidgetsBinding.instance.addPostFrameCallback(
|
||||
(_) => instructionsShowPopup(
|
||||
context,
|
||||
InstructionsEnum.emptyChatWarning,
|
||||
widget.transformTargetId,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
_memberSubscription = widget.room.client.onRoomState.stream.where(
|
||||
(u) {
|
||||
return u.roomId == widget.room.id &&
|
||||
u.state.type == EventTypes.RoomMember;
|
||||
},
|
||||
).listen((event) {
|
||||
final members = (widget.room.summary.mJoinedMemberCount ?? 0) +
|
||||
(widget.room.summary.mInvitedMemberCount ?? 0);
|
||||
if (members > 1) {
|
||||
MatrixState.pAnyState.closeOverlay(
|
||||
InstructionsEnum.emptyChatWarning.toString(),
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_memberSubscription?.cancel();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
}
|
||||
|
|
@ -10,14 +10,16 @@ class InstructionsInlineTooltip extends StatefulWidget {
|
|||
final InstructionsEnum instructionsEnum;
|
||||
final bool bold;
|
||||
final bool animate;
|
||||
final double padding;
|
||||
final EdgeInsets? padding;
|
||||
final VoidCallback? onClose;
|
||||
|
||||
const InstructionsInlineTooltip({
|
||||
super.key,
|
||||
required this.instructionsEnum,
|
||||
this.bold = false,
|
||||
this.animate = true,
|
||||
this.padding = 0.0,
|
||||
this.padding,
|
||||
this.onClose,
|
||||
});
|
||||
|
||||
@override
|
||||
|
|
@ -45,7 +47,7 @@ class InstructionsInlineTooltipState extends State<InstructionsInlineTooltip>
|
|||
setToggled();
|
||||
}
|
||||
|
||||
void setToggled() {
|
||||
Future<void> setToggled() async {
|
||||
_isToggledOff = widget.instructionsEnum.isToggledOff;
|
||||
|
||||
if (widget.animate) {
|
||||
|
|
@ -61,10 +63,12 @@ class InstructionsInlineTooltipState extends State<InstructionsInlineTooltip>
|
|||
);
|
||||
|
||||
// Start in correct state
|
||||
if (!_isToggledOff) _controller!.forward();
|
||||
if (!_isToggledOff) {
|
||||
await _controller!.forward();
|
||||
}
|
||||
}
|
||||
|
||||
setState(() {});
|
||||
if (mounted) setState(() {});
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
@ -73,14 +77,14 @@ class InstructionsInlineTooltipState extends State<InstructionsInlineTooltip>
|
|||
super.dispose();
|
||||
}
|
||||
|
||||
void _closeTooltip() {
|
||||
Future<void> _closeTooltip() async {
|
||||
widget.instructionsEnum.setToggledOff(true);
|
||||
setState(() {
|
||||
_isToggledOff = true;
|
||||
if (widget.animate) {
|
||||
_controller?.reverse();
|
||||
}
|
||||
});
|
||||
setState(() => _isToggledOff = true);
|
||||
|
||||
if (widget.animate) {
|
||||
await _controller?.reverse();
|
||||
}
|
||||
widget.onClose?.call();
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
@ -98,7 +102,7 @@ class InstructionsInlineTooltipState extends State<InstructionsInlineTooltip>
|
|||
|
||||
Widget _buildTooltipContent(BuildContext context) {
|
||||
return Padding(
|
||||
padding: EdgeInsets.all(widget.padding),
|
||||
padding: widget.padding ?? const EdgeInsets.all(0),
|
||||
child: DecoratedBox(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(AppConfig.borderRadius),
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue