-
-
Notifications
You must be signed in to change notification settings - Fork 21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Chat-ng]: Appflowy Editor editor integration #2332
base: main
Are you sure you want to change the base?
Changes from all commits
69f7e3d
191a8f8
7868d77
01f7315
a16dd7f
6fe1e5a
7bc47fa
f0ab803
9fcf9d8
71fcd4f
16c9256
5679cab
0ef9aa3
0be9f23
3c5a6af
def4f25
29f4ab3
224e62b
01d17e4
4e172c0
cd28e67
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
- Chat-NG now supports Appflowy editor with proper markdown support. Some/Other features might be disabled or limited for now. | ||
Original file line number | Diff line number | Diff line change | ||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,92 @@ | ||||||||||||||||
import 'package:acter/common/providers/room_providers.dart'; | ||||||||||||||||
import 'package:acter/common/widgets/html_editor/models/mention_block_keys.dart'; | ||||||||||||||||
import 'package:acter_avatar/acter_avatar.dart'; | ||||||||||||||||
import 'package:appflowy_editor/appflowy_editor.dart'; | ||||||||||||||||
import 'package:flutter/material.dart'; | ||||||||||||||||
import 'package:flutter_riverpod/flutter_riverpod.dart'; | ||||||||||||||||
|
||||||||||||||||
class MentionBlock extends ConsumerWidget { | ||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The UI component of the inline mentions in editor (of how it should be displayed when triggered) |
||||||||||||||||
const MentionBlock({ | ||||||||||||||||
super.key, | ||||||||||||||||
required this.node, | ||||||||||||||||
required this.index, | ||||||||||||||||
required this.mention, | ||||||||||||||||
required this.userRoomId, | ||||||||||||||||
}); | ||||||||||||||||
|
||||||||||||||||
final Map<String, dynamic> mention; | ||||||||||||||||
final String userRoomId; | ||||||||||||||||
final Node node; | ||||||||||||||||
final int index; | ||||||||||||||||
Comment on lines
+17
to
+20
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. don't we usually keep the list above the constructor? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm, yes. I can change it as I didn't really seem to thought much about it before. |
||||||||||||||||
@override | ||||||||||||||||
Widget build(BuildContext context, WidgetRef ref) { | ||||||||||||||||
Comment on lines
+20
to
+22
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||
final String type = mention[MentionBlockKeys.type]; | ||||||||||||||||
final String displayName = mention[MentionBlockKeys.displayName]; | ||||||||||||||||
final String mentionId = type == 'user' | ||||||||||||||||
? mention[MentionBlockKeys.userId] | ||||||||||||||||
: mention[MentionBlockKeys.roomId]; | ||||||||||||||||
final avatarInfo = type == 'user' | ||||||||||||||||
? ref.watch( | ||||||||||||||||
memberAvatarInfoProvider((roomId: userRoomId, userId: mentionId)), | ||||||||||||||||
) | ||||||||||||||||
: ref.watch(roomAvatarInfoProvider(mentionId)); | ||||||||||||||||
final options = type == 'user' | ||||||||||||||||
? AvatarOptions.DM(avatarInfo, size: 8) | ||||||||||||||||
: AvatarOptions(avatarInfo, size: 16); | ||||||||||||||||
|
||||||||||||||||
return _mentionContent( | ||||||||||||||||
context: context, | ||||||||||||||||
mentionId: mentionId, | ||||||||||||||||
displayName: displayName, | ||||||||||||||||
avatarOptions: options, | ||||||||||||||||
ref: ref, | ||||||||||||||||
); | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
Widget _mentionContent({ | ||||||||||||||||
required BuildContext context, | ||||||||||||||||
required String mentionId, | ||||||||||||||||
required String displayName, | ||||||||||||||||
required WidgetRef ref, | ||||||||||||||||
required AvatarOptions avatarOptions, | ||||||||||||||||
}) { | ||||||||||||||||
final desktopPlatforms = [ | ||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. mouse can also be plugged/connected to phones. don't do a check like that. |
||||||||||||||||
TargetPlatform.linux, | ||||||||||||||||
TargetPlatform.macOS, | ||||||||||||||||
TargetPlatform.windows, | ||||||||||||||||
]; | ||||||||||||||||
final name = displayName.isNotEmpty ? displayName : mentionId; | ||||||||||||||||
final mentionContentWidget = Container( | ||||||||||||||||
padding: const EdgeInsets.symmetric(horizontal: 12), | ||||||||||||||||
decoration: BoxDecoration( | ||||||||||||||||
color: Theme.of(context).unselectedWidgetColor, | ||||||||||||||||
borderRadius: BorderRadius.circular(12), | ||||||||||||||||
), | ||||||||||||||||
child: Row( | ||||||||||||||||
mainAxisSize: MainAxisSize.min, | ||||||||||||||||
children: [ | ||||||||||||||||
ActerAvatar(options: avatarOptions), | ||||||||||||||||
const SizedBox(width: 4), | ||||||||||||||||
Text(name, style: Theme.of(context).textTheme.bodyMedium), | ||||||||||||||||
], | ||||||||||||||||
), | ||||||||||||||||
); | ||||||||||||||||
|
||||||||||||||||
final Widget content = GestureDetector( | ||||||||||||||||
onTap: _handleUserTap, | ||||||||||||||||
behavior: HitTestBehavior.opaque, | ||||||||||||||||
child: desktopPlatforms.contains(Theme.of(context).platform) | ||||||||||||||||
? MouseRegion( | ||||||||||||||||
cursor: SystemMouseCursors.click, | ||||||||||||||||
child: mentionContentWidget, | ||||||||||||||||
) | ||||||||||||||||
: mentionContentWidget, | ||||||||||||||||
); | ||||||||||||||||
|
||||||||||||||||
return content; | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
void _handleUserTap() { | ||||||||||||||||
// Implement user tap action (e.g., show profile, start chat) | ||||||||||||||||
} | ||||||||||||||||
} |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,50 @@ | ||||||||||||||||||||||||
import 'package:acter/common/utils/constants.dart'; | ||||||||||||||||||||||||
import 'package:acter/common/widgets/html_editor/models/mention_type.dart'; | ||||||||||||||||||||||||
import 'package:acter_avatar/acter_avatar.dart'; | ||||||||||||||||||||||||
import 'package:flutter/material.dart'; | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
class MentionItem extends StatelessWidget { | ||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Mention list UI item component which gets displayed as part of mention menu list. |
||||||||||||||||||||||||
const MentionItem({ | ||||||||||||||||||||||||
super.key, | ||||||||||||||||||||||||
required this.mentionId, | ||||||||||||||||||||||||
required this.mentionType, | ||||||||||||||||||||||||
required this.displayName, | ||||||||||||||||||||||||
required this.avatarOptions, | ||||||||||||||||||||||||
required this.isSelected, | ||||||||||||||||||||||||
required this.onTap, | ||||||||||||||||||||||||
}); | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
final String mentionId; | ||||||||||||||||||||||||
final MentionType mentionType; | ||||||||||||||||||||||||
final String displayName; | ||||||||||||||||||||||||
final AvatarOptions avatarOptions; | ||||||||||||||||||||||||
final bool isSelected; | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
final VoidCallback onTap; | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
@override | ||||||||||||||||||||||||
Widget build(BuildContext context) { | ||||||||||||||||||||||||
final isDesktop = desktopPlatforms.contains(Theme.of(context).platform); | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
return Container( | ||||||||||||||||||||||||
height: 60, | ||||||||||||||||||||||||
// selection color is only for desktop with keyboard navigation | ||||||||||||||||||||||||
color: (isSelected && isDesktop) | ||||||||||||||||||||||||
? Theme.of(context).colorScheme.primary | ||||||||||||||||||||||||
: null, | ||||||||||||||||||||||||
Comment on lines
+27
to
+34
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
but then also, how would
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see, good point. I'll change the conditional 👍🏻 ! |
||||||||||||||||||||||||
child: ListTile( | ||||||||||||||||||||||||
dense: true, | ||||||||||||||||||||||||
onTap: onTap, | ||||||||||||||||||||||||
contentPadding: const EdgeInsets.symmetric(horizontal: 12), | ||||||||||||||||||||||||
leading: ActerAvatar(options: avatarOptions), | ||||||||||||||||||||||||
title: Text( | ||||||||||||||||||||||||
displayName.isNotEmpty ? displayName : mentionId, | ||||||||||||||||||||||||
style: Theme.of(context).textTheme.bodyMedium, | ||||||||||||||||||||||||
), | ||||||||||||||||||||||||
subtitle: displayName.isNotEmpty | ||||||||||||||||||||||||
? Text(mentionId, style: Theme.of(context).textTheme.labelMedium) | ||||||||||||||||||||||||
: null, | ||||||||||||||||||||||||
), | ||||||||||||||||||||||||
); | ||||||||||||||||||||||||
} | ||||||||||||||||||||||||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.