Skip to content
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

feat: Support Panes for AppFlowy #3337

Draft
wants to merge 121 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 112 commits
Commits
Show all changes
121 commits
Select commit Hold shift + click to select a range
76bf6cf
feat: added handlers for panes
squidrye Aug 18, 2023
d33456a
feat: added model for panes
squidrye Aug 18, 2023
8ca1baa
feat: added state managers for panes
squidrye Aug 18, 2023
54ea96f
feat: implemented recursive build for homestack panes
squidrye Aug 18, 2023
12175da
feat: added temporary splitRight and splitDown to view menu
squidrye Aug 18, 2023
8cf5b13
Merge branch 'main' of https://github.com/AppFlowy-IO/AppFlowy into f…
squidrye Aug 18, 2023
831b18e
feat: delegated tabs logic to active pane
squidrye Aug 26, 2023
df9c933
refactor: converted panes handler into single service
squidrye Aug 26, 2023
bf8d37f
feat: added panes bloc
squidrye Aug 26, 2023
1ba3c1e
Merge branch 'main' of https://github.com/AppFlowy-IO/AppFlowy into f…
squidrye Aug 26, 2023
f53d66b
refactor: removed comments
squidrye Sep 1, 2023
33868ad
refactor: updated suggestions
squidrye Sep 1, 2023
1afdb26
feat: added resizability and sliding panes setup
squidrye Sep 1, 2023
43bcbf7
Merge branch 'main' of https://github.com/AppFlowy-IO/AppFlowy into f…
squidrye Sep 1, 2023
4ecd37f
refactor: added suggestion
squidrye Sep 1, 2023
6fad07c
feat: flex properties for panes
squidrye Sep 12, 2023
38415d0
Merge branch 'main' of https://github.com/AppFlowy-IO/AppFlowy into f…
squidrye Sep 12, 2023
95994c6
refactor: updated paneId to re-render changes
squidrye Sep 13, 2023
7407fd7
feat: added flex property to panes
squidrye Sep 13, 2023
269e7ea
feat: separated calculations to layout.dart
squidrye Sep 13, 2023
a43c5a5
refactor: restructured code
squidrye Sep 13, 2023
09811ef
refactor: restructured code
squidrye Sep 13, 2023
ca81a1c
feat: wrapped pane in draggable item
squidrye Sep 14, 2023
83447b0
feat: added logic for pane drag-drop
squidrye Sep 14, 2023
c7760c2
refactor: added suggestions
squidrye Sep 14, 2023
45e172e
feat: cover draggable edge cases
squidrye Sep 14, 2023
d1f6870
refactor: remove log statements
squidrye Sep 14, 2023
44d7aac
Merge branch 'main' of https://github.com/AppFlowy-IO/AppFlowy into f…
squidrye Sep 14, 2023
c48519a
refactor: tabs changes
squidrye Sep 14, 2023
dbef2a6
refactor: assign new object for tabs to avoid wrong notifiers
squidrye Sep 16, 2023
1bbc830
refactor: remove unused function
squidrye Sep 16, 2023
13bb289
feat: allow pane splits by pane and view drops
squidrye Sep 16, 2023
406b63e
feat: allow tab reordering
squidrye Sep 16, 2023
f3a4fe3
feat: linked pane, tab and view drag and drops
squidrye Sep 16, 2023
8c1d525
refactor: enable drag on ctrl + drag
squidrye Sep 16, 2023
7a305b0
feat: updated themes for draggable
squidrye Sep 16, 2023
308e9fd
Merge branch 'main' of https://github.com/AppFlowy-IO/AppFlowy into f…
squidrye Sep 16, 2023
a8864c0
refactor: reverted hotkeys for drag
squidrye Sep 19, 2023
89b16e1
feat: handled drag related edge cases
squidrye Sep 19, 2023
9a24160
refactor: removed unnecessary parameters for tab related utils
squidrye Sep 19, 2023
722137c
feat: handled all cases for panes
squidrye Sep 19, 2023
144ecd1
feat: set active pane via mouse region (gesture detector doesn't work)
squidrye Sep 19, 2023
b82a4ae
fix: size controller gets disposed
squidrye Sep 19, 2023
f7e66f4
fix: onPanDown lead to breaking changes
squidrye Sep 20, 2023
d954f1e
fix: removed manual drag offset translation, analysis issues
squidrye Sep 20, 2023
e354fde
refactor: converted resizing to bloc
squidrye Sep 21, 2023
07ae74c
Merge branch 'main' of https://github.com/AppFlowy-IO/AppFlowy into f…
squidrye Sep 21, 2023
3170959
refactor: converted to named params
squidrye Sep 22, 2023
43d914b
refactor: cleanup
squidrye Sep 22, 2023
45566b0
feat: separated drag target for panes
squidrye Sep 22, 2023
72b03dd
feat: added absorbpointer for duplicated views
squidrye Sep 22, 2023
58b0a06
fix: listener called after tabcontroller got disposed
squidrye Sep 22, 2023
42548d9
feat: localization
squidrye Sep 22, 2023
3f5b143
Merge branch 'main' of https://github.com/AppFlowy-IO/AppFlowy into f…
squidrye Sep 28, 2023
1887f27
refactor: scrollbar as per theme
squidrye Sep 29, 2023
3920b31
feat: updated flex calculations
squidrye Sep 29, 2023
d8d46d3
chore: added suggestions
squidrye Sep 29, 2023
ebba765
refactor: removed caching
squidrye Oct 3, 2023
9bce232
refactor: formatting
squidrye Oct 3, 2023
b8e31f3
feat: introduced encodings to keep track of read only views
squidrye Oct 3, 2023
fd3af99
refactor: remove logs
squidrye Oct 3, 2023
3209453
fix: update values after change in pluginList
squidrye Oct 3, 2023
0efa181
feat: working read view overlay logic
squidrye Oct 5, 2023
61ebc53
feat: fixed tab to pane transfers
squidrye Oct 9, 2023
70ed731
refactor: assign new tab to update ui
squidrye Oct 9, 2023
3a78c8c
refactor: minor changes
squidrye Oct 9, 2023
3ae8c9a
feat: fixed read-only views and wrong disposals
squidrye Oct 9, 2023
79ec036
refactor: revert unwatned changes
squidrye Oct 9, 2023
a23553f
feat: enable scrolling for read only views
squidrye Oct 9, 2023
d7069a8
refactor: assign value keys
squidrye Oct 9, 2023
cee145a
Merge branch 'main' of https://github.com/AppFlowy-IO/appflowy into f…
squidrye Oct 9, 2023
a3b3491
refactor: merge changes
squidrye Oct 9, 2023
a58d6c1
fix: analysis issues
squidrye Oct 9, 2023
25fa448
test: added basic tests for panes
squidrye Oct 9, 2023
2a74a67
test: refactored tabs_test
squidrye Oct 9, 2023
93b6b5d
test: added common operations for panes test
squidrye Oct 9, 2023
f5b6e6c
feat: added hover to resizebar
squidrye Oct 9, 2023
3307976
test: added pane overlay test
squidrye Oct 9, 2023
737fb78
fix: tab to tab drags
squidrye Oct 9, 2023
57ed56e
fix: editor does not auto focus readonly views
squidrye Oct 9, 2023
de3df1f
fix: setters
squidrye Oct 10, 2023
e93618a
feat: manually linked scrolling for touchpad scrolls
squidrye Oct 10, 2023
0c208c8
refactor: updated manual scroll linking
squidrye Oct 10, 2023
a6aabe1
fix: scroll controls were disposed
squidrye Oct 10, 2023
1244681
fix: tabs reordering
squidrye Oct 10, 2023
a368172
test: update operations for icon change
squidrye Oct 10, 2023
e4d2b58
fix: changed close icon
squidrye Oct 10, 2023
9fd192f
chore: rename symbol
squidrye Oct 10, 2023
dc1cee9
feat: enable pane drag with left-ctrl
squidrye Oct 10, 2023
b83f29a
chore: remove unused function
squidrye Oct 10, 2023
9ffcf43
refactor: updated feeback widget
squidrye Oct 10, 2023
5c6fd22
feat: render collapse menu for one pane
squidrye Oct 13, 2023
3d469b3
fix: wrong implementation
squidrye Oct 22, 2023
b4a5e84
Merge branch 'main' of https://github.com/AppFlowy-IO/appflowy into f…
squidrye Oct 22, 2023
d67a248
fix: dispose listeners
squidrye Oct 23, 2023
7c214a9
test: updated tests affected by implementation
squidrye Oct 23, 2023
bf48baa
Merge branch 'main' into feat-panes-2312
LucasXu0 Oct 24, 2023
7e6c2f2
feat: updated manual scroll syncs
squidrye Oct 24, 2023
0093e3a
fix: found a bug for splitting usecase
squidrye Oct 24, 2023
b6558b9
refactor: panes layout can be modified to switch between adaptive sizing
squidrye Oct 24, 2023
159dc8a
Merge branch 'feat-panes-2312' of https://github.com/squidrye/AppFlow…
squidrye Oct 24, 2023
3e028b2
chore: revert unwanted changes
squidrye Oct 24, 2023
e7e089e
feat: pinned header
squidrye Oct 25, 2023
29a59d0
fix: analyzer issues
squidrye Oct 25, 2023
a7824d7
fix: analyzer issues
squidrye Oct 25, 2023
31f3994
chore: minor change
squidrye Oct 25, 2023
734d1c5
refactor: converted cubits to blocs
squidrye Oct 26, 2023
5d19198
Merge branch 'main' of https://github.com/AppFlowy-IO/appflowy into f…
squidrye Oct 26, 2023
9d74529
fix: wrong merge
squidrye Oct 26, 2023
b72d4ca
chore: updated handler
squidrye Oct 27, 2023
14176ed
Merge branch 'main' of https://github.com/AppFlowy-IO/appflowy into f…
squidrye Oct 27, 2023
2524c8b
chore: merge refactor
squidrye Oct 27, 2023
ad16902
chore: clean code
Xazin Nov 9, 2023
6c7e917
Merge branch 'main' of https://github.com/AppFlowy-IO/appflowy into f…
squidrye Nov 15, 2023
057e6fe
fix: board popover rebuilds
squidrye Nov 15, 2023
c31c5b9
refactor: undo test changes
squidrye Nov 15, 2023
24b6bf9
chore: cleanup
squidrye Nov 15, 2023
563b362
fix: padding and icon color
squidrye Nov 15, 2023
c152e1e
fix: icon color, padding and banner constraints to width
squidrye Nov 15, 2023
9b5f834
Merge branch 'main' of https://github.com/AppFlowy-IO/AppFlowy into f…
squidrye Mar 3, 2024
f86e293
refactor: adapt to merge changes
squidrye Mar 3, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ void main() {
onHover: () async {
final moreOption = find.byType(CardMoreOption);
await tester.tapButton(moreOption);
await tester.tapButton(moreOption);
Xazin marked this conversation as resolved.
Show resolved Hide resolved
},
);
await tester.tapButtonWithName(LocaleKeys.button_delete.tr());
Expand All @@ -41,6 +42,7 @@ void main() {
onHover: () async {
final moreOption = find.byType(CardMoreOption);
await tester.tapButton(moreOption);
await tester.tapButton(moreOption);
Xazin marked this conversation as resolved.
Show resolved Hide resolved
},
);
await tester.tapButtonWithName(LocaleKeys.button_duplicate.tr());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ void main() {
await tester.dragDropRescheduleCalendarEvent(firstOfThisMonth);

// Make sure that the event has been rescheduled to the new date
final sameDayNextWeek = firstOfThisMonth.add(const Duration(days: 7));
final sameDayNextWeek = firstOfThisMonth.add(const Duration(days: 14));
Xazin marked this conversation as resolved.
Show resolved Hide resolved
tester.assertNumberOfEventsInCalendar(1);
tester.assertNumberOfEventsOnSpecificDay(1, sameDayNextWeek);

Expand Down
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/workspace/presentation/home/panes/flowy_pane.dart';
import 'package:appflowy_backend/protobuf/flowy-folder2/protobuf.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart';

import '../util/util.dart';

const _documentName = 'First Doc';
void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();

group('Panes overlay/read-only views test', () {
testWidgets(
'Opening a new pane of same type marks existing pane as readonly, test assumes read only views are unmodifiable',
(tester) async {
await tester.initializeAppFlowy();
await tester.tapGoButton();

expect(find.byType(FlowyPane), findsOneWidget);

for (int i = 0; i < 2; i++) {
await tester.openViewInNewPane(
gettingStarted,
ViewLayoutPB.Document,
Axis.horizontal,
);
}

expect(find.byType(FlowyPane), findsNWidgets(3));
expect(
find.textContaining(LocaleKeys.readOnlyViewText.tr()),
findsNWidgets(2),
);
});
testWidgets(
'Switching view on writable pane or closing the writable pane, searches for and converts the first found read only pane to writable',
(tester) async {
await tester.initializeAppFlowy();
await tester.tapGoButton();

expect(find.byType(FlowyPane), findsOneWidget);

for (int i = 0; i < 2; i++) {
await tester.openViewInNewPane(
gettingStarted,
ViewLayoutPB.Document,
Axis.horizontal,
);
}
expect(find.byType(FlowyPane), findsNWidgets(3));
expect(
find.textContaining(LocaleKeys.readOnlyViewText.tr()),
findsNWidgets(2),
);

await tester.createNewPageWithName(name: _documentName);

await tester.tap(find.byType(FlowyPane).first);

await tester.openPage(_documentName);

expect(
find.textContaining(LocaleKeys.readOnlyViewText.tr()),
findsNWidgets(1),
);

await tester.tap(find.byType(FlowyPane).last);

await tester.closePaneWithVisibleCloseButton(first: false);

expect(
find.textContaining(LocaleKeys.readOnlyViewText.tr()),
findsNWidgets(0),
);
});
testWidgets(
'opening duplicate view in a new tab of different pane is marked as read only, closing the writable view leads to conversion of readonly view to writable view',
(tester) async {
await tester.initializeAppFlowy();
await tester.tapGoButton();

expect(find.byType(FlowyPane), findsOneWidget);

for (int i = 0; i < 1; i++) {
await tester.openViewInNewPane(
gettingStarted,
ViewLayoutPB.Document,
Axis.horizontal,
);
}
expect(find.byType(FlowyPane), findsNWidgets(2));
expect(
find.textContaining(LocaleKeys.readOnlyViewText.tr()),
findsNWidgets(1),
);
await tester.tap(find.byType(FlowyPane).first);

await tester.createNewPageWithName(name: _documentName);

expect(
find.textContaining(LocaleKeys.readOnlyViewText.tr()),
findsNWidgets(0),
);

await tester.openAppInNewTab(gettingStarted, ViewLayoutPB.Document);

expect(
find.textContaining(LocaleKeys.readOnlyViewText.tr()),
findsNWidgets(1),
);

await tester.tap(find.byType(FlowyPane).last);

await tester.closePaneWithVisibleCloseButton(first: false);

expect(
find.textContaining(LocaleKeys.readOnlyViewText.tr()),
findsNWidgets(0),
);
});
});
}
75 changes: 75 additions & 0 deletions frontend/appflowy_flutter/integration_test/panes/panes_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import 'package:appflowy/workspace/presentation/home/panes/flowy_pane.dart';
import 'package:appflowy_backend/protobuf/flowy-folder2/protobuf.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart';

import '../util/util.dart';

const _documentName = 'First Doc';
const _documentTwoName = 'Second Doc';
void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();

group('Core pane tests', () {
testWidgets('Open AppFlowy and open/navigate/close panes', (tester) async {
await tester.initializeAppFlowy();
await tester.tapGoButton();

expect(find.byType(FlowyPane), findsOneWidget);

await tester.createNewPageWithName(
name: _documentName,
layout: ViewLayoutPB.Document,
);

await tester.createNewPageWithName(
name: _documentTwoName,
layout: ViewLayoutPB.Document,
);

await tester.openViewInNewPane(
gettingStarted,
ViewLayoutPB.Document,
Axis.horizontal,
);

expect(find.byType(FlowyPane), findsNWidgets(2));

await tester.openViewInNewPane(
_documentName,
ViewLayoutPB.Document,
);

expect(find.byType(FlowyPane), findsNWidgets(3));

await tester.tap(
find.descendant(
of: find.byType(FlowyPane),
matching: find.text(gettingStarted),
),
);

await tester.closePaneWithVisibleCloseButton();

expect(find.byType(FlowyPane), findsNWidgets(2));
});

testWidgets('user can open atmost 4 panes', (tester) async {
await tester.initializeAppFlowy();
await tester.tapGoButton();

expect(find.byType(FlowyPane), findsOneWidget);

for (int i = 0; i < 5; i++) {
await tester.openViewInNewPane(
gettingStarted,
ViewLayoutPB.Document,
Axis.horizontal,
);
}

expect(find.byType(FlowyPane), findsNWidgets(4));
});
});
}
16 changes: 11 additions & 5 deletions frontend/appflowy_flutter/integration_test/runner.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,17 @@ import 'database_share_test.dart' as database_share_test;
import 'database_sort_test.dart' as database_sort_test;
import 'database_view_test.dart' as database_view_test;
import 'document/document_test_runner.dart' as document_test_runner;
import 'import_files_test.dart' as import_files_test;
import 'share_markdown_test.dart' as share_markdown_test;
import 'switch_folder_test.dart' as switch_folder_test;
import 'sidebar/sidebar_test_runner.dart' as sidebar_test_runner;
import 'tabs/tabs_test.dart' as tabs_test;
import 'empty_test.dart' as first_test;
import 'hotkeys_test.dart' as hotkeys_test;
import 'import_files_test.dart' as import_files_test;
import 'settings/user_icon_test.dart' as user_icon_test;
import 'settings/user_language_test.dart' as user_language_test;
import 'share_markdown_test.dart' as share_markdown_test;
import 'sidebar/sidebar_test_runner.dart' as sidebar_test_runner;
import 'switch_folder_test.dart' as switch_folder_test;
import 'tabs_test.dart' as tabs_test;
import 'panes/panes_test.dart' as panes_test;
import 'panes/panes_overlay_test.dart' as panes_overlay_test;

/// The main task runner for all integration tests in AppFlowy.
///
Expand Down Expand Up @@ -68,6 +70,10 @@ void main() {
// Tabs
tabs_test.main();

//Panes
panes_test.main();
panes_overlay_test.main();

// Others
hotkeys_test.main();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart';

import 'util/base.dart';
import 'util/common_operations.dart';
import 'util/expectation.dart';
import 'util/keyboard.dart';
import '../util/base.dart';
import '../util/common_operations.dart';
import '../util/expectation.dart';
import '../util/keyboard.dart';

const _documentName = 'First Doc';
const _documentTwoName = 'Second Doc';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,17 @@ extension CommonOperations on WidgetTester {
await tapButtonWithName(ViewMoreActionType.openInNewTab.name);
}

/// Tap the Split Right button
Future<void> tapSplitRightButton() async {
await tapPageOptionButton();
await tapButtonWithName(ViewMoreActionType.splitRight.name);
}

Future<void> tapSplitDownButton() async {
await tapPageOptionButton();
await tapButtonWithName(ViewMoreActionType.splitDown.name);
}

/// Rename the page.
Future<void> renamePage(String name) async {
await tapRenamePageButton();
Expand Down Expand Up @@ -428,11 +439,38 @@ extension CommonOperations on WidgetTester {
}

// tap the button with [FlowySvgData]
Future<void> tapButtonWithFlowySvgData(FlowySvgData svg) async {
Future<void> tapButtonWithFlowySvgData(
FlowySvgData svg, [
bool first = true,
]) async {
final button = find.byWidgetPredicate(
(widget) => widget is FlowySvg && widget.svg.path == svg.path,
);
await tapButton(button);
first ? await tapButton(button.first) : await tapButton(button.last);
}

Future<void> openViewInNewPane(
String name,
ViewLayoutPB layout, [
Axis axis = Axis.vertical,
]) async {
await hoverOnPageName(
name,
onHover: () async {
if (axis == Axis.vertical) {
await tapSplitRightButton();
} else {
await tapSplitDownButton();
}
await pumpAndSettle();
},
);
}

Future<void> closePaneWithVisibleCloseButton({
bool first = true,
}) async {
await tapButtonWithFlowySvgData(FlowySvgs.close_s, first);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ class DocumentPluginWidgetBuilder extends PluginWidgetBuilder
builder: (_, state) {
return DocumentPage(
view: view,
readOnlyStatus: notifier.readOnlyStatus,
onDeleted: () => context?.onDeleted(view, deletedViewIndex),
key: ValueKey(view.id),
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,12 @@ class DocumentPage extends StatefulWidget {
super.key,
required this.onDeleted,
required this.view,
required this.readOnlyStatus,
});

final VoidCallback onDeleted;
final ViewPB view;
final bool readOnlyStatus;

@override
State<DocumentPage> createState() => _DocumentPageState();
Expand Down Expand Up @@ -107,6 +109,7 @@ class _DocumentPageState extends State<DocumentPage> {

Widget _buildEditorPage(BuildContext context, DocumentState state) {
final appflowyEditorPage = AppFlowyEditorPage(
autoFocus: !widget.readOnlyStatus,
editorState: editorState!,
styleCustomizer: EditorStyleCustomizer(
context: context,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import 'package:appflowy/plugins/document/presentation/editor_plugins/plugins.dart';
import 'package:appflowy/startup/plugin/plugin.dart';
import 'package:appflowy/startup/startup.dart';
import 'package:appflowy/workspace/application/tabs/tabs_bloc.dart';
import 'package:appflowy/workspace/application/panes/panes_bloc/panes_bloc.dart';
import 'package:appflowy/workspace/application/view/view_service.dart';
import 'package:appflowy/workspace/presentation/widgets/pop_up_action.dart';
import 'package:appflowy_backend/protobuf/flowy-error/errors.pbserver.dart';
Expand Down Expand Up @@ -155,12 +155,8 @@
onSelected: (action, controller) async {
switch (action.inner) {
case _ActionType.viewDatabase:
getIt<TabsBloc>().add(
TabsEvent.openPlugin(
plugin: viewPB.plugin(),
view: viewPB,
),
);
getIt<PanesBloc>()
.add(OpenTabInActivePane(plugin: viewPB.plugin()));

Check warning on line 159 in frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/base/built_in_page_widget.dart

View check run for this annotation

Codecov / codecov/patch

frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/base/built_in_page_widget.dart#L158-L159

Added lines #L158 - L159 were not covered by tests
break;
case _ActionType.delete:
final transaction = widget.editorState.transaction;
Expand Down
Loading
Loading