Skip to content

Commit 56f8762

Browse files
committed
Merge branch 'main' into feat/notification
2 parents 5111bc9 + b3b13e5 commit 56f8762

34 files changed

Lines changed: 1121 additions & 247 deletions

File tree

frontend/Makefile.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ CARGO_MAKE_EXTEND_WORKSPACE_MAKEFILE = true
2626
CARGO_MAKE_CRATE_FS_NAME = "dart_ffi"
2727
CARGO_MAKE_CRATE_NAME = "dart-ffi"
2828
LIB_NAME = "dart_ffi"
29-
APPFLOWY_VERSION = "0.8.7"
29+
APPFLOWY_VERSION = "0.8.8"
3030
FLUTTER_DESKTOP_FEATURES = "dart"
3131
PRODUCT_NAME = "AppFlowy"
3232
MACOSX_DEPLOYMENT_TARGET = "11.0"

frontend/appflowy_flutter/integration_test/desktop/uncategorized/emoji_shortcut_test.dart

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import 'dart:io';
22

3+
import 'package:appflowy/plugins/emoji/emoji_handler.dart';
34
import 'package:appflowy/workspace/presentation/settings/widgets/emoji_picker/emoji_picker.dart';
45
import 'package:appflowy_editor/appflowy_editor.dart';
56
import 'package:appflowy_editor/src/editor/editor_component/service/editor.dart';
7+
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
68
import 'package:flutter/services.dart';
79
import 'package:flutter_test/flutter_test.dart';
810
import 'package:integration_test/integration_test.dart';
@@ -39,4 +41,114 @@ void main() {
3941
expect(find.byType(EmojiSelectionMenu), findsOneWidget);
4042
});
4143
});
44+
45+
group('insert emoji by colon', () {
46+
Future<void> createNewDocumentAndShowEmojiList(WidgetTester tester) async {
47+
await tester.initializeAppFlowy();
48+
await tester.tapAnonymousSignInButton();
49+
await tester.createNewPageWithNameUnderParent();
50+
await tester.editor.tapLineOfEditorAt(0);
51+
await tester.ime.insertText(':');
52+
await tester.pumpAndSettle(Duration(seconds: 1));
53+
}
54+
55+
testWidgets('insert with click', (tester) async {
56+
await createNewDocumentAndShowEmojiList(tester);
57+
58+
/// emoji list is showing
59+
final emojiHandler = find.byType(EmojiHandler);
60+
expect(emojiHandler, findsOneWidget);
61+
final emojiButtons =
62+
find.descendant(of: emojiHandler, matching: find.byType(FlowyButton));
63+
final firstTextFinder = find.descendant(
64+
of: emojiButtons.first,
65+
matching: find.byType(FlowyText),
66+
);
67+
final emojiText =
68+
(firstTextFinder.evaluate().first.widget as FlowyText).text;
69+
70+
/// click first emoji item
71+
await tester.tapButton(emojiButtons.first);
72+
final firstNode =
73+
tester.editor.getCurrentEditorState().getNodeAtPath([0])!;
74+
75+
/// except the emoji is in document
76+
expect(emojiText.contains(firstNode.delta!.toPlainText()), true);
77+
});
78+
79+
testWidgets('insert with arrow and enter', (tester) async {
80+
await createNewDocumentAndShowEmojiList(tester);
81+
82+
/// emoji list is showing
83+
final emojiHandler = find.byType(EmojiHandler);
84+
expect(emojiHandler, findsOneWidget);
85+
final emojiButtons =
86+
find.descendant(of: emojiHandler, matching: find.byType(FlowyButton));
87+
88+
/// tap arrow down and arrow up
89+
await tester.simulateKeyEvent(LogicalKeyboardKey.arrowUp);
90+
await tester.simulateKeyEvent(LogicalKeyboardKey.arrowDown);
91+
92+
final firstTextFinder = find.descendant(
93+
of: emojiButtons.first,
94+
matching: find.byType(FlowyText),
95+
);
96+
final emojiText =
97+
(firstTextFinder.evaluate().first.widget as FlowyText).text;
98+
99+
/// tap enter
100+
await tester.simulateKeyEvent(LogicalKeyboardKey.enter);
101+
final firstNode =
102+
tester.editor.getCurrentEditorState().getNodeAtPath([0])!;
103+
104+
/// except the emoji is in document
105+
expect(emojiText.contains(firstNode.delta!.toPlainText()), true);
106+
});
107+
108+
testWidgets('insert with searching', (tester) async {
109+
await createNewDocumentAndShowEmojiList(tester);
110+
111+
/// search for `smiling eyes`, IME is not working, use keyboard input
112+
final searchText = [
113+
LogicalKeyboardKey.keyS,
114+
LogicalKeyboardKey.keyM,
115+
LogicalKeyboardKey.keyI,
116+
LogicalKeyboardKey.keyL,
117+
LogicalKeyboardKey.keyI,
118+
LogicalKeyboardKey.keyN,
119+
LogicalKeyboardKey.keyG,
120+
LogicalKeyboardKey.space,
121+
LogicalKeyboardKey.keyE,
122+
LogicalKeyboardKey.keyY,
123+
LogicalKeyboardKey.keyE,
124+
LogicalKeyboardKey.keyS,
125+
];
126+
127+
for (final key in searchText) {
128+
await tester.simulateKeyEvent(key);
129+
}
130+
131+
/// tap enter
132+
await tester.simulateKeyEvent(LogicalKeyboardKey.enter);
133+
final firstNode =
134+
tester.editor.getCurrentEditorState().getNodeAtPath([0])!;
135+
136+
/// except the emoji is in document
137+
expect(firstNode.delta!.toPlainText().contains('😄'), true);
138+
});
139+
140+
testWidgets('start searching with sapce', (tester) async {
141+
await createNewDocumentAndShowEmojiList(tester);
142+
143+
/// emoji list is showing
144+
final emojiHandler = find.byType(EmojiHandler);
145+
expect(emojiHandler, findsOneWidget);
146+
147+
/// input space
148+
await tester.simulateKeyEvent(LogicalKeyboardKey.space);
149+
150+
/// emoji list is dismissed
151+
expect(emojiHandler, findsNothing);
152+
});
153+
});
42154
}

frontend/appflowy_flutter/integration_test/desktop/uncategorized/uncategorized_test_runner_1.dart

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ void main() {
1313
hotkeys_test.main();
1414
emoji_shortcut_test.main();
1515
hotkeys_test.main();
16-
emoji_shortcut_test.main();
1716
share_markdown_test.main();
1817
import_files_test.main();
1918
zoom_in_out_test.main();

frontend/appflowy_flutter/lib/ai/service/ai_input_control.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ class AIModelStateNotifier {
1414
: _isDesktop = UniversalPlatform.isDesktop,
1515
_localAIListener =
1616
UniversalPlatform.isDesktop ? LocalAIStateListener() : null,
17-
_aiModelSwitchListener = AIModelSwitchListener(chatId: objectId);
17+
_aiModelSwitchListener = AIModelSwitchListener(objectId: objectId);
1818

1919
final String objectId;
2020
final bool _isDesktop;

frontend/appflowy_flutter/lib/mobile/presentation/home/mobile_home_setting_page.dart

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,6 @@ class _MobileHomeSettingPageState extends State<MobileHomeSettingPage> {
100100
key: ValueKey(currentWorkspaceId),
101101
userProfile: userProfile,
102102
workspaceId: currentWorkspaceId,
103-
currentWorkspaceMemberRole: state.currentWorkspace?.role,
104103
),
105104
const SupportSettingGroup(),
106105
const AboutSettingGroup(),

frontend/appflowy_flutter/lib/mobile/presentation/setting/ai/ai_settings_group.dart

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@ import 'package:appflowy/mobile/presentation/setting/widgets/mobile_setting_item
55
import 'package:appflowy/mobile/presentation/widgets/flowy_option_tile.dart';
66
import 'package:appflowy/workspace/application/settings/ai/settings_ai_bloc.dart';
77
import 'package:appflowy_backend/protobuf/flowy-user/user_profile.pb.dart';
8-
import 'package:appflowy_backend/protobuf/flowy-user/workspace.pbenum.dart';
9-
import 'package:collection/collection.dart';
108
import 'package:easy_localization/easy_localization.dart';
119
import 'package:flowy_infra_ui/style_widget/text.dart';
1210
import 'package:flutter/material.dart';
@@ -18,12 +16,10 @@ class AiSettingsGroup extends StatelessWidget {
1816
super.key,
1917
required this.userProfile,
2018
required this.workspaceId,
21-
this.currentWorkspaceMemberRole,
2219
});
2320

2421
final UserProfilePB userProfile;
2522
final String workspaceId;
26-
final AFRolePB? currentWorkspaceMemberRole;
2723

2824
@override
2925
Widget build(BuildContext context) {
@@ -32,7 +28,6 @@ class AiSettingsGroup extends StatelessWidget {
3228
create: (context) => SettingsAIBloc(
3329
userProfile,
3430
workspaceId,
35-
currentWorkspaceMemberRole,
3631
)..add(const SettingsAIEvent.started()),
3732
child: BlocBuilder<SettingsAIBloc, SettingsAIState>(
3833
builder: (context, state) {
@@ -48,7 +43,7 @@ class AiSettingsGroup extends StatelessWidget {
4843
children: [
4944
Flexible(
5045
child: FlowyText(
51-
state.selectedAIModel,
46+
state.availableModels?.selectedModel.name ?? "",
5247
color: theme.colorScheme.onSurface,
5348
overflow: TextOverflow.ellipsis,
5449
),
@@ -84,16 +79,19 @@ class AiSettingsGroup extends StatelessWidget {
8479
title: LocaleKeys.settings_aiPage_keys_llmModelType.tr(),
8580
builder: (_) {
8681
return Column(
87-
children: availableModels
88-
.mapIndexed(
89-
(index, model) => FlowyOptionTile.checkbox(
90-
text: model.name,
91-
showTopBorder: index == 0,
92-
isSelected: state.selectedAIModel == model.name,
82+
children: (availableModels?.models ?? [])
83+
.asMap()
84+
.entries
85+
.map(
86+
(entry) => FlowyOptionTile.checkbox(
87+
text: entry.value.name,
88+
showTopBorder: entry.key == 0,
89+
isSelected:
90+
availableModels?.selectedModel.name == entry.value.name,
9391
onTap: () {
9492
context
9593
.read<SettingsAIBloc>()
96-
.add(SettingsAIEvent.selectModel(model.name));
94+
.add(SettingsAIEvent.selectModel(entry.value));
9795
context.pop();
9896
},
9997
),

frontend/appflowy_flutter/lib/plugins/ai_chat/application/ai_model_switch_listener.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,14 @@ import 'package:appflowy_result/appflowy_result.dart';
1212
typedef OnUpdateSelectedModel = void Function(AIModelPB model);
1313

1414
class AIModelSwitchListener {
15-
AIModelSwitchListener({required this.chatId}) {
16-
_parser = ChatNotificationParser(id: chatId, callback: _callback);
15+
AIModelSwitchListener({required this.objectId}) {
16+
_parser = ChatNotificationParser(id: objectId, callback: _callback);
1717
_subscription = RustStreamReceiver.listen(
1818
(observable) => _parser?.parse(observable),
1919
);
2020
}
2121

22-
final String chatId;
22+
final String objectId;
2323
StreamSubscription<SubscribeObject>? _subscription;
2424
ChatNotificationParser? _parser;
2525

frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/actions/block_action_option_cubit.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -469,7 +469,7 @@ class BlockActionOptionCubit extends Cubit<BlockActionOptionState> {
469469
blockComponentDelta: newDelta.toJson(),
470470
},
471471
children: [
472-
...node.children,
472+
...node.children.map((e) => e.deepCopy()),
473473
...insertedNodes.map((e) => e.deepCopy()),
474474
],
475475
);

frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/ai/ai_writer_block_component.dart

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ class _OverlayContentState extends State<OverlayContent> {
226226
final showSuggestedActionsWithin =
227227
showSuggestedActions && markdownText.isNotEmpty;
228228

229-
final darkBorderColor = Theme.of(context).isLightMode
229+
final borderColor = Theme.of(context).isLightMode
230230
? Color(0x1F1F2329)
231231
: Color(0xFF505469);
232232

@@ -241,7 +241,7 @@ class _OverlayContentState extends State<OverlayContent> {
241241
context,
242242
color: Theme.of(context).colorScheme.surface,
243243
borderRadius: BorderRadius.all(Radius.circular(8.0)),
244-
borderColor: darkBorderColor,
244+
borderColor: borderColor,
245245
),
246246
child: SuggestionActionBar(
247247
currentCommand: command,
@@ -257,7 +257,7 @@ class _OverlayContentState extends State<OverlayContent> {
257257
decoration: _getModalDecoration(
258258
context,
259259
color: null,
260-
borderColor: darkBorderColor,
260+
borderColor: borderColor,
261261
borderRadius: BorderRadius.all(Radius.circular(12.0)),
262262
),
263263
constraints: BoxConstraints(maxHeight: 400),
@@ -341,13 +341,9 @@ class _OverlayContentState extends State<OverlayContent> {
341341
strokeAlign: BorderSide.strokeAlignOutside,
342342
),
343343
borderRadius: borderRadius,
344-
boxShadow: const [
345-
BoxShadow(
346-
offset: Offset(0, 4),
347-
blurRadius: 20,
348-
color: Color(0x1A1F2329),
349-
),
350-
],
344+
boxShadow: Theme.of(context).isLightMode
345+
? ShadowConstants.lightSmall
346+
: ShadowConstants.darkSmall,
351347
);
352348
}
353349

frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/ai/operations/ai_writer_cubit.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -519,7 +519,7 @@ class AiWriterCubit extends Cubit<AiWriterState> {
519519
editorState,
520520
aiWriterNode!,
521521
);
522-
_textRobot.start(position: position);
522+
_textRobot.start(position: position, previousSelection: selection);
523523
records.add(
524524
AiWriterRecord.user(
525525
content: prompt,

0 commit comments

Comments
 (0)