Skip to content

Commit

Permalink
fix: tabs lr 0.7.6 (AppFlowy-IO#6899)
Browse files Browse the repository at this point in the history
* fix: tabs improvements launch review

* test: add tests for pin/unpin feature

* fix: failing test + cleanup
  • Loading branch information
Xazin authored Dec 1, 2024
1 parent 603d65a commit 1851721
Show file tree
Hide file tree
Showing 15 changed files with 488 additions and 168 deletions.
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import 'dart:io';

import 'package:appflowy/generated/flowy_svgs.g.dart';
import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/workspace/presentation/home/tabs/flowy_tab.dart';
import 'package:appflowy/workspace/presentation/home/tabs/tabs_manager.dart';
import 'package:appflowy/workspace/presentation/widgets/tab_bar_item.dart';
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/gestures.dart';
Expand Down Expand Up @@ -176,62 +176,159 @@ void main() {
findsNWidgets(3),
);

final firstTabFinder = find.descendant(
of: find.byType(FlowyTab),
matching: find.text(_documentTwoName),
);
final secondTabFinder = find.descendant(
of: find.byType(FlowyTab),
matching: find.text(gettingStarted),
);
final thirdTabFinder = find.descendant(
of: find.byType(FlowyTab),
matching: find.text(_documentName),
);
const firstTab = _documentTwoName;
const secondTab = gettingStarted;
const thirdTab = _documentName;

expect(firstTabFinder, findsOneWidget);
expect(secondTabFinder, findsOneWidget);
expect(thirdTabFinder, findsOneWidget);
expect(tester.isTabAtIndex(firstTab, 0), isTrue);
expect(tester.isTabAtIndex(secondTab, 1), isTrue);
expect(tester.isTabAtIndex(thirdTab, 2), isTrue);

// We expect not to see the pinned svg
expect(find.byFlowySvg(FlowySvgs.pinned_s), findsNothing);
expect(tester.isTabPinned(gettingStarted), isFalse);

// Right click on second tab
await tester.tap(
buttons: kSecondaryButton,
find.descendant(
of: find.byType(FlowyTab),
matching: find.text(gettingStarted),
),
);
await tester.pumpAndSettle();
await tester.openTabMenu(gettingStarted);
expect(find.byType(TabMenu), findsOneWidget);

// Pin second tab
await tester.tap(find.text(LocaleKeys.tabMenu_pinTab.tr()));
await tester.pumpAndSettle();

// We expect to see the pinned svg
expect(find.byFlowySvg(FlowySvgs.pinned_s), findsOneWidget);
expect(tester.isTabPinned(gettingStarted), isTrue);

/// Right click on first tab
await tester.tap(
buttons: kSecondaryButton,
/// Right click on first unpinned tab (second tab)
await tester.openTabMenu(_documentTwoName);

// Close others
await tester.tap(find.text(LocaleKeys.tabMenu_closeOthers.tr()));
await tester.pumpAndSettle();

// We expect to find 2 tabs, the first pinned tab and the second tab
expect(find.byType(FlowyTab), findsNWidgets(2));
expect(tester.isTabAtIndex(gettingStarted, 0), isTrue);
expect(tester.isTabAtIndex(_documentTwoName, 1), isTrue);
});

testWidgets('pin/unpin tabs proper order', (tester) async {
await tester.initializeAppFlowy();
await tester.tapAnonymousSignInButton();

expect(
find.descendant(
of: find.byType(FlowyTab),
matching: find.text(_documentTwoName),
of: find.byType(TabsManager),
matching: find.byType(TabBar),
),
findsNothing,
);

await tester.createNewPageWithNameUnderParent(name: _documentName);
await tester.createNewPageWithNameUnderParent(name: _documentTwoName);

// Open second menu item in a new tab
await tester.openAppInNewTab(gettingStarted, ViewLayoutPB.Document);

// Open third menu item in a new tab
await tester.openAppInNewTab(_documentName, ViewLayoutPB.Document);

expect(
find.descendant(
of: find.byType(TabsManager),
matching: find.byType(FlowyTab),
),
findsNWidgets(3),
);

const firstTabName = _documentTwoName;
const secondTabName = gettingStarted;
const thirdTabName = _documentName;

// Expect correct order
expect(tester.isTabAtIndex(firstTabName, 0), isTrue);
expect(tester.isTabAtIndex(secondTabName, 1), isTrue);
expect(tester.isTabAtIndex(thirdTabName, 2), isTrue);

// Pin second tab
await tester.openTabMenu(secondTabName);
await tester.tap(find.text(LocaleKeys.tabMenu_pinTab.tr()));
await tester.pumpAndSettle();

// Close others than first tab
await tester.tap(find.text(LocaleKeys.tabMenu_closeOthers.tr()));
expect(tester.isTabPinned(secondTabName), isTrue);

// Expect correct order
expect(tester.isTabAtIndex(secondTabName, 0), isTrue);
expect(tester.isTabAtIndex(firstTabName, 1), isTrue);
expect(tester.isTabAtIndex(thirdTabName, 2), isTrue);

// Pin new second tab (first tab)
await tester.openTabMenu(firstTabName);
await tester.tap(find.text(LocaleKeys.tabMenu_pinTab.tr()));
await tester.pumpAndSettle();

// We expect to find 2 tabs, the first tab and the pinned second tab
expect(firstTabFinder, findsOneWidget);
expect(secondTabFinder, findsOneWidget);
expect(thirdTabFinder, findsNothing);
expect(tester.isTabPinned(firstTabName), isTrue);
expect(tester.isTabPinned(secondTabName), isTrue);
expect(tester.isTabPinned(thirdTabName), isFalse);

expect(tester.isTabAtIndex(secondTabName, 0), isTrue);
expect(tester.isTabAtIndex(firstTabName, 1), isTrue);
expect(tester.isTabAtIndex(thirdTabName, 2), isTrue);

// Unpin second tab
await tester.openTabMenu(secondTabName);
await tester.tap(find.text(LocaleKeys.tabMenu_unpinTab.tr()));
await tester.pumpAndSettle();

expect(tester.isTabPinned(firstTabName), isTrue);
expect(tester.isTabPinned(secondTabName), isFalse);
expect(tester.isTabPinned(thirdTabName), isFalse);

expect(tester.isTabAtIndex(firstTabName, 0), isTrue);
expect(tester.isTabAtIndex(secondTabName, 1), isTrue);
expect(tester.isTabAtIndex(thirdTabName, 2), isTrue);
});
});
}

extension _TabsTester on WidgetTester {
bool isTabPinned(String tabName) {
final tabFinder = find.ancestor(
of: find.byWidgetPredicate(
(w) => w is ViewTabBarItem && w.view.name == tabName,
),
matching: find.byType(FlowyTab),
);

final FlowyTab tabWidget = widget(tabFinder);
return tabWidget.pageManager.isPinned;
}

bool isTabAtIndex(String tabName, int index) {
final tabFinder = find.ancestor(
of: find.byWidgetPredicate(
(w) => w is ViewTabBarItem && w.view.name == tabName,
),
matching: find.byType(FlowyTab),
);

final pluginId = (widget(tabFinder) as FlowyTab).pageManager.plugin.id;

final pluginIds = find
.byType(FlowyTab)
.evaluate()
.map((e) => (e.widget as FlowyTab).pageManager.plugin.id);

return pluginIds.elementAt(index) == pluginId;
}

Future<void> openTabMenu(String tabName) async {
await tap(
buttons: kSecondaryButton,
find.ancestor(
of: find.byWidgetPredicate(
(w) => w is ViewTabBarItem && w.view.name == tabName,
),
matching: find.byType(FlowyTab),
),
);
await pumpAndSettle();
}
}
7 changes: 6 additions & 1 deletion frontend/appflowy_flutter/lib/plugins/ai_chat/chat.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import 'package:appflowy/generated/flowy_svgs.g.dart';
import 'package:appflowy/plugins/ai_chat/chat_page.dart';
import 'package:appflowy/plugins/util.dart';
import 'package:appflowy/startup/plugin/plugin.dart';
import 'package:appflowy/workspace/application/view/view_ext.dart';
import 'package:appflowy/workspace/application/view_info/view_info_bloc.dart';
import 'package:appflowy/workspace/presentation/home/home_stack.dart';
import 'package:appflowy/workspace/presentation/widgets/tab_bar_item.dart';
Expand Down Expand Up @@ -85,12 +86,16 @@ class AIChatPagePluginWidgetBuilder extends PluginWidgetBuilder
final ViewPluginNotifier notifier;
int? deletedViewIndex;

@override
String? get viewName => notifier.view.nameOrDefault;

@override
Widget get leftBarItem =>
ViewTitleBar(key: ValueKey(notifier.view.id), view: notifier.view);

@override
Widget tabBarItem(String pluginId) => ViewTabBarItem(view: notifier.view);
Widget tabBarItem(String pluginId, [bool shortForm = false]) =>
ViewTabBarItem(view: notifier.view, shortForm: shortForm);

@override
Widget buildWidget({
Expand Down
5 changes: 4 additions & 1 deletion frontend/appflowy_flutter/lib/plugins/blank/blank.dart
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,14 @@ class BlankPagePlugin extends Plugin {

class BlankPagePluginWidgetBuilder extends PluginWidgetBuilder
with NavigationItem {
@override
String? get viewName => LocaleKeys.blankPageTitle.tr();

@override
Widget get leftBarItem => FlowyText.medium(LocaleKeys.blankPageTitle.tr());

@override
Widget tabBarItem(String pluginId) => leftBarItem;
Widget tabBarItem(String pluginId, [bool shortForm = false]) => leftBarItem;

@override
Widget buildWidget({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -257,12 +257,16 @@ class DatabasePluginWidgetBuilder extends PluginWidgetBuilder {
///
final String? initialRowId;

@override
String? get viewName => notifier.view.nameOrDefault;

@override
Widget get leftBarItem =>
ViewTitleBar(key: ValueKey(notifier.view.id), view: notifier.view);

@override
Widget tabBarItem(String pluginId) => ViewTabBarItem(view: notifier.view);
Widget tabBarItem(String pluginId, [bool shortForm = false]) =>
ViewTabBarItem(view: notifier.view, shortForm: shortForm);

@override
Widget buildWidget({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'package:appflowy/generated/flowy_svgs.g.dart';
import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/plugins/document/application/document_appearance_cubit.dart';
import 'package:appflowy/startup/plugin/plugin.dart';
import 'package:appflowy/workspace/application/view/view_ext.dart';
import 'package:appflowy/workspace/presentation/home/home_stack.dart';
import 'package:appflowy_backend/protobuf/flowy-folder/protobuf.dart';
import 'package:appflowy_editor/appflowy_editor.dart';
Expand Down Expand Up @@ -97,6 +98,9 @@ class DatabaseDocumentPluginWidgetBuilder extends PluginWidgetBuilder
final String documentId;
final Selection? initialSelection;

@override
String? get viewName => view.nameOrDefault;

@override
EdgeInsets get contentPadding => EdgeInsets.zero;

Expand All @@ -123,7 +127,8 @@ class DatabaseDocumentPluginWidgetBuilder extends PluginWidgetBuilder
ViewTitleBarWithRow(view: view, databaseId: databaseId, rowId: rowId);

@override
Widget tabBarItem(String pluginId) => const SizedBox.shrink();
Widget tabBarItem(String pluginId, [bool shortForm = false]) =>
const SizedBox.shrink();

@override
Widget? get rightBarItem => const SizedBox.shrink();
Expand Down
7 changes: 6 additions & 1 deletion frontend/appflowy_flutter/lib/plugins/document/document.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import 'package:appflowy/plugins/shared/share/share_button.dart';
import 'package:appflowy/plugins/util.dart';
import 'package:appflowy/shared/feature_flags.dart';
import 'package:appflowy/startup/plugin/plugin.dart';
import 'package:appflowy/workspace/application/view/view_ext.dart';
import 'package:appflowy/workspace/application/view_info/view_info_bloc.dart';
import 'package:appflowy/workspace/presentation/home/home_stack.dart';
import 'package:appflowy/workspace/presentation/widgets/favorite_button.dart';
Expand Down Expand Up @@ -145,11 +146,15 @@ class DocumentPluginWidgetBuilder extends PluginWidgetBuilder
);
}

@override
String? get viewName => notifier.view.nameOrDefault;

@override
Widget get leftBarItem => ViewTitleBar(key: ValueKey(view.id), view: view);

@override
Widget tabBarItem(String pluginId) => ViewTabBarItem(view: notifier.view);
Widget tabBarItem(String pluginId, [bool shortForm = false]) =>
ViewTabBarItem(view: notifier.view, shortForm: shortForm);

@override
Widget? get rightBarItem {
Expand Down
9 changes: 5 additions & 4 deletions frontend/appflowy_flutter/lib/plugins/trash/trash.dart
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,14 @@ class TrashPlugin extends Plugin {
}

class TrashPluginDisplay extends PluginWidgetBuilder {
@override
String? get viewName => LocaleKeys.trash_text.tr();

@override
Widget get leftBarItem => FlowyText.medium(LocaleKeys.trash_text.tr());

@override
Widget tabBarItem(String pluginId) => leftBarItem;
Widget tabBarItem(String pluginId, [bool shortForm = false]) => leftBarItem;

@override
Widget? get rightBarItem => null;
Expand All @@ -68,9 +71,7 @@ class TrashPluginDisplay extends PluginWidgetBuilder {
required bool shrinkWrap,
Map<String, dynamic>? data,
}) =>
const TrashPage(
key: ValueKey('TrashPage'),
);
const TrashPage(key: ValueKey('TrashPage'));

@override
List<NavigationItem> get navigationItems => [this];
Expand Down
Loading

0 comments on commit 1851721

Please sign in to comment.