feat: improve space UX (#5549)

* fix: scroll bar hover color

* chore: replace board icon

* chore: remove close button in upgrade menu

* chore: add translation

* feat: switch to the next space by shortcut

* chore: replace space lock icon

* chore: remove arrow icon in change icon button

* feat: only show other favorites header if the other two is empty

* fix: create new page in current space

* feat: create a new page in a newly created space by default

* chore: update translations

* feat: open the first page after switching space by default

* chore: replace board icon

* fix: open the first page(non-space) after switching workspace

* chore: revert more icon

* chore: revert editor version
This commit is contained in:
Lucas.Xu 2024-06-17 16:23:17 +08:00 committed by GitHub
parent 49683e6079
commit 70a7b856a2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
28 changed files with 343 additions and 182 deletions

View File

@ -1,7 +1,7 @@
import 'package:appflowy/generated/flowy_svgs.g.dart';
import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/mobile/presentation/bottom_sheet/bottom_sheet.dart';
import 'package:appflowy/mobile/presentation/home/shared/mobile_view_card.dart';
import 'package:appflowy/mobile/presentation/home/shared/mobile_page_card.dart';
import 'package:appflowy/mobile/presentation/page_item/mobile_slide_action_button.dart';
import 'package:appflowy/workspace/application/favorite/favorite_bloc.dart';
import 'package:appflowy/workspace/application/recent/recent_views_bloc.dart';
@ -23,7 +23,7 @@ enum MobilePaneActionType {
MobileSlideActionButton actionButton(
BuildContext context, {
MobileViewCardType? cardType,
MobilePageCardType? cardType,
FolderSpaceType? spaceType,
}) {
switch (this) {
@ -133,13 +133,13 @@ enum MobilePaneActionType {
List<MobileViewItemBottomSheetBodyAction> _buildActions(
ViewPB view, {
MobileViewCardType? cardType,
MobilePageCardType? cardType,
}) {
final isFavorite = view.isFavorite;
if (cardType != null) {
switch (cardType) {
case MobileViewCardType.recent:
case MobilePageCardType.recent:
return [
isFavorite
? MobileViewItemBottomSheetBodyAction.removeFromFavorites
@ -150,7 +150,7 @@ enum MobilePaneActionType {
MobileViewItemBottomSheetBodyAction.divider,
MobileViewItemBottomSheetBodyAction.removeFromRecent,
];
case MobileViewCardType.favorite:
case MobilePageCardType.favorite:
return [
isFavorite
? MobileViewItemBottomSheetBodyAction.removeFromFavorites
@ -179,7 +179,7 @@ ActionPane buildEndActionPane(
BuildContext context,
List<MobilePaneActionType> actions, {
bool needSpace = true,
MobileViewCardType? cardType,
MobilePageCardType? cardType,
FolderSpaceType? spaceType,
}) {
return ActionPane(

View File

@ -1,6 +1,6 @@
import 'package:appflowy/mobile/application/mobile_router.dart';
import 'package:appflowy/mobile/presentation/home/shared/empty_placeholder.dart';
import 'package:appflowy/mobile/presentation/home/shared/mobile_view_card.dart';
import 'package:appflowy/mobile/presentation/home/shared/mobile_page_card.dart';
import 'package:appflowy/util/theme_extension.dart';
import 'package:appflowy/workspace/application/favorite/favorite_bloc.dart';
import 'package:appflowy/workspace/application/menu/sidebar_sections_bloc.dart';
@ -69,7 +69,7 @@ class _MobileFavoriteSpaceState extends State<MobileFavoriteSpace>
if (favoriteState.views.isEmpty) {
return const EmptySpacePlaceholder(
type: MobileViewCardType.favorite,
type: MobilePageCardType.favorite,
);
}
@ -117,11 +117,11 @@ class _FavoriteViews extends StatelessWidget {
),
),
),
child: MobileViewCard(
child: MobileViewPage(
key: ValueKey(view.item.id),
view: view.item,
timestamp: view.timestamp,
type: MobileViewCardType.favorite,
type: MobilePageCardType.favorite,
),
);
},

View File

@ -42,8 +42,8 @@ class MobileFolders extends StatelessWidget {
create: (_) => FavoriteBloc()..add(const FavoriteEvent.initial()),
),
BlocProvider(
create: (_) =>
SpaceBloc()..add(SpaceEvent.initial(user, workspaceId)),
create: (_) => SpaceBloc()
..add(SpaceEvent.initial(user, workspaceId, openFirstPage: false)),
),
],
child: BlocListener<UserWorkspaceBloc, UserWorkspaceState>(

View File

@ -1,5 +1,5 @@
import 'package:appflowy/mobile/presentation/home/shared/empty_placeholder.dart';
import 'package:appflowy/mobile/presentation/home/shared/mobile_view_card.dart';
import 'package:appflowy/mobile/presentation/home/shared/mobile_page_card.dart';
import 'package:appflowy/util/theme_extension.dart';
import 'package:appflowy/workspace/application/recent/prelude.dart';
import 'package:appflowy/workspace/presentation/home/home_sizes.dart';
@ -37,7 +37,7 @@ class _MobileRecentSpaceState extends State<MobileRecentSpace>
if (recentViews.isEmpty) {
return const Center(
child: EmptySpacePlaceholder(type: MobileViewCardType.recent),
child: EmptySpacePlaceholder(type: MobilePageCardType.recent),
);
}
@ -89,11 +89,11 @@ class _RecentViews extends StatelessWidget {
),
),
),
child: MobileViewCard(
child: MobileViewPage(
key: ValueKey(sectionView.item.id),
view: sectionView.item,
timestamp: sectionView.timestamp,
type: MobileViewCardType.recent,
type: MobilePageCardType.recent,
),
);
},

View File

@ -1,6 +1,6 @@
import 'package:appflowy/generated/flowy_svgs.g.dart';
import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/mobile/presentation/home/shared/mobile_view_card.dart';
import 'package:appflowy/mobile/presentation/home/shared/mobile_page_card.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
import 'package:flutter/material.dart';
@ -8,7 +8,7 @@ import 'package:flutter/material.dart';
class EmptySpacePlaceholder extends StatelessWidget {
const EmptySpacePlaceholder({super.key, required this.type});
final MobileViewCardType type;
final MobilePageCardType type;
@override
Widget build(BuildContext context) {
@ -42,14 +42,14 @@ class EmptySpacePlaceholder extends StatelessWidget {
}
String get _emptyPageText => switch (type) {
MobileViewCardType.recent => LocaleKeys.sideBar_emptyRecent.tr(),
MobileViewCardType.favorite => LocaleKeys.sideBar_emptyFavorite.tr(),
MobilePageCardType.recent => LocaleKeys.sideBar_emptyRecent.tr(),
MobilePageCardType.favorite => LocaleKeys.sideBar_emptyFavorite.tr(),
};
String get _emptyPageSubText => switch (type) {
MobileViewCardType.recent =>
MobilePageCardType.recent =>
LocaleKeys.sideBar_emptyRecentDescription.tr(),
MobileViewCardType.favorite =>
MobilePageCardType.favorite =>
LocaleKeys.sideBar_emptyFavoriteDescription.tr(),
};
}

View File

@ -29,18 +29,18 @@ import 'package:provider/provider.dart';
import 'package:string_validator/string_validator.dart';
import 'package:time/time.dart';
enum MobileViewCardType {
enum MobilePageCardType {
recent,
favorite;
String get lastOperationHintText => switch (this) {
MobileViewCardType.recent => LocaleKeys.sideBar_lastViewed.tr(),
MobileViewCardType.favorite => LocaleKeys.sideBar_favoriteAt.tr(),
MobilePageCardType.recent => LocaleKeys.sideBar_lastViewed.tr(),
MobilePageCardType.favorite => LocaleKeys.sideBar_favoriteAt.tr(),
};
}
class MobileViewCard extends StatelessWidget {
const MobileViewCard({
class MobileViewPage extends StatelessWidget {
const MobileViewPage({
super.key,
required this.view,
this.timestamp,
@ -49,7 +49,7 @@ class MobileViewCard extends StatelessWidget {
final ViewPB view;
final Int64? timestamp;
final MobileViewCardType type;
final MobilePageCardType type;
@override
Widget build(BuildContext context) {

View File

@ -42,10 +42,6 @@ class _MobileSpaceState extends State<MobileSpace> {
SpaceEvent.createPage(
name: LocaleKeys.menuAppHeader_defaultNewPageName.tr(),
index: 0,
viewSection: currentSpace.spacePermission ==
SpacePermission.publicToAll
? ViewSectionPB.Public
: ViewSectionPB.Private,
),
);
context.read<SpaceBloc>().add(

View File

@ -58,8 +58,6 @@ class EditorStyleCustomizer {
DefaultAppearanceSettings.getDefaultSelectionColor(context),
defaultTextDirection: appearance.defaultTextDirection,
textStyleConfiguration: TextStyleConfiguration(
// applyHeightToFirstAscent: true,
// applyHeightToLastDescent: true,
text: baseTextStyle(fontFamily).copyWith(
fontSize: fontSize,
color: afThemeExtension.onBackground,

View File

@ -76,7 +76,7 @@ class DesktopAppearance extends BaseAppearance {
scrollbarTheme: ScrollbarThemeData(
thumbColor: WidgetStateProperty.resolveWith((states) {
if (states.any(scrollbarInteractiveStates.contains)) {
return theme.shader7;
return theme.shader3;
}
return theme.shader5;
}),
@ -102,6 +102,7 @@ class DesktopAppearance extends BaseAppearance {
indicatorColor: theme.main1,
cardColor: theme.input,
colorScheme: colorScheme,
extensions: [
AFThemeExtension(
warning: theme.yellow,

View File

@ -3,6 +3,7 @@ import 'dart:convert';
import 'package:appflowy/core/config/kv.dart';
import 'package:appflowy/core/config/kv_keys.dart';
import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/startup/startup.dart';
import 'package:appflowy/user/application/user_service.dart';
import 'package:appflowy/workspace/application/view/view_ext.dart';
@ -16,6 +17,7 @@ import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart';
import 'package:appflowy_result/appflowy_result.dart';
import 'package:collection/collection.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:protobuf/protobuf.dart';
@ -60,7 +62,7 @@ class SpaceBloc extends Bloc<SpaceEvent, SpaceState> {
on<SpaceEvent>(
(event, emit) async {
await event.when(
initial: (userProfile, workspaceId) async {
initial: (userProfile, workspaceId, openFirstPage) async {
_initial(userProfile, workspaceId);
final (spaces, publicViews, privateViews) = await _getSpaces();
@ -84,8 +86,20 @@ class SpaceBloc extends Bloc<SpaceEvent, SpaceState> {
if (shouldShowUpgradeDialog) {
add(const SpaceEvent.migrate());
}
if (openFirstPage) {
if (currentSpace != null) {
add(SpaceEvent.open(currentSpace));
}
}
},
create: (name, icon, iconColor, permission) async {
create: (
name,
icon,
iconColor,
permission,
createNewPageByDefault,
) async {
final space = await _createSpace(
name: name,
icon: icon,
@ -93,8 +107,22 @@ class SpaceBloc extends Bloc<SpaceEvent, SpaceState> {
permission: permission,
);
if (space != null) {
emit(state.copyWith(spaces: [...state.spaces, space]));
emit(
state.copyWith(
spaces: [...state.spaces, space],
currentSpace: space,
),
);
add(SpaceEvent.open(space));
if (createNewPageByDefault) {
add(
SpaceEvent.createPage(
name: LocaleKeys.menuAppHeader_defaultNewPageName.tr(),
index: 0,
),
);
}
}
},
delete: (space) async {
@ -160,12 +188,28 @@ class SpaceBloc extends Bloc<SpaceEvent, SpaceState> {
await _openSpace(space);
final isExpanded = await _getSpaceExpandStatus(space);
emit(state.copyWith(currentSpace: space, isExpanded: isExpanded));
// open the first page by default
if (space.childViews.isNotEmpty) {
final firstPage = space.childViews.first;
emit(
state.copyWith(
lastCreatedPage: firstPage,
),
);
} else {
emit(
state.copyWith(
lastCreatedPage: ViewPB(),
),
);
}
},
expand: (space, isExpanded) async {
await _setSpaceExpandStatus(space, isExpanded);
emit(state.copyWith(isExpanded: isExpanded));
},
createPage: (name, section, index) async {
createPage: (name, index) async {
final parentViewId = state.currentSpace?.id;
if (parentViewId == null) {
return;
@ -209,12 +253,33 @@ class SpaceBloc extends Bloc<SpaceEvent, SpaceState> {
reset: (userProfile, workspaceId) async {
_reset(userProfile, workspaceId);
add(SpaceEvent.initial(userProfile, workspaceId));
add(
SpaceEvent.initial(
userProfile,
workspaceId,
openFirstPage: true,
),
);
},
migrate: () async {
final result = await migrate();
emit(state.copyWith(shouldShowUpgradeDialog: !result));
},
switchToNextSpace: () async {
final spaces = state.spaces;
if (spaces.isEmpty) {
return;
}
final currentSpace = state.currentSpace;
if (currentSpace == null) {
return;
}
final currentIndex = spaces.indexOf(currentSpace);
final nextIndex = (currentIndex + 1) % spaces.length;
final nextSpace = spaces[nextIndex];
add(SpaceEvent.open(nextSpace));
},
);
},
);
@ -410,7 +475,7 @@ class SpaceBloc extends Bloc<SpaceEvent, SpaceState> {
// only migrate the public space if there are any public views
if (publicViews.isNotEmpty) {
final publicSpace = await _createSpace(
name: 'General',
name: 'Shared',
icon: builtInSpaceIcons.first,
iconColor: builtInSpaceColors.first,
permission: SpacePermission.publicToAll,
@ -487,13 +552,15 @@ class SpaceBloc extends Bloc<SpaceEvent, SpaceState> {
class SpaceEvent with _$SpaceEvent {
const factory SpaceEvent.initial(
UserProfilePB userProfile,
String workspaceId,
) = _Initial;
String workspaceId, {
required bool openFirstPage,
}) = _Initial;
const factory SpaceEvent.create({
required String name,
required String icon,
required String iconColor,
required SpacePermission permission,
required bool createNewPageByDefault,
}) = _Create;
const factory SpaceEvent.rename(ViewPB space, String name) = _Rename;
const factory SpaceEvent.changeIcon(String icon, String iconColor) =
@ -508,7 +575,6 @@ class SpaceEvent with _$SpaceEvent {
const factory SpaceEvent.expand(ViewPB space, bool isExpanded) = _Expand;
const factory SpaceEvent.createPage({
required String name,
required ViewSectionPB viewSection,
int? index,
}) = _CreatePage;
const factory SpaceEvent.delete(ViewPB? space) = _Delete;
@ -518,6 +584,7 @@ class SpaceEvent with _$SpaceEvent {
String workspaceId,
) = _Reset;
const factory SpaceEvent.migrate() = _Migrate;
const factory SpaceEvent.switchToNextSpace() = _SwitchToNextSpace;
}
@freezed

View File

@ -1,7 +1,5 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:appflowy/startup/startup.dart';
import 'package:appflowy/startup/tasks/app_window_size_manager.dart';
import 'package:appflowy/workspace/application/home/home_setting_bloc.dart';
@ -11,12 +9,15 @@ import 'package:appflowy/workspace/application/tabs/tabs_bloc.dart';
import 'package:appflowy/workspace/presentation/home/menu/sidebar/shared/sidebar_setting.dart';
import 'package:appflowy_backend/log.dart';
import 'package:appflowy_backend/protobuf/flowy-user/user_profile.pb.dart';
import 'package:flutter/material.dart';
import 'package:hotkey_manager/hotkey_manager.dart';
import 'package:provider/provider.dart';
import 'package:scaled_app/scaled_app.dart';
typedef KeyDownHandler = void Function(HotKey hotKey);
ValueNotifier<int> switchToTheNextSpace = ValueNotifier(0);
/// Helper class that utilizes the global [HotKeyManager] to easily
/// add a [HotKey] with different handlers.
///
@ -163,6 +164,16 @@ class _HomeHotKeysState extends State<HomeHotKeys> {
keyDownHandler: (_) => _scaleToSize(1),
),
// Switch to the next space
HotKeyItem(
hotKey: HotKey(
KeyCode.keyO,
modifiers: [Platform.isMacOS ? KeyModifier.meta : KeyModifier.control],
scope: HotKeyScope.inapp,
),
keyDownHandler: (_) => switchToTheNextSpace.value++,
),
// Open settings dialog
openSettingsHotKey(context, widget.userProfile),
];

View File

@ -62,6 +62,21 @@ class FavoriteMenu extends StatelessWidget {
}
Widget _buildViews(BuildContext context, FavoriteMenuState state) {
final today = _buildGroups(
context,
state.todayViews,
LocaleKeys.sideBar_today.tr(),
);
final thisWeek = _buildGroups(
context,
state.thisWeekViews,
LocaleKeys.sideBar_thisWeek.tr(),
);
final others = _buildGroups(
context,
state.otherViews,
LocaleKeys.sideBar_others.tr(),
);
return Container(
width: minWidth - 2 * _kHorizontalPadding,
constraints: const BoxConstraints(
@ -72,21 +87,26 @@ class FavoriteMenu extends StatelessWidget {
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
..._buildGroups(
context,
state.todayViews,
LocaleKeys.sideBar_today.tr(),
),
..._buildGroups(
context,
state.thisWeekViews,
LocaleKeys.sideBar_thisWeek.tr(),
),
..._buildGroups(
context,
state.otherViews,
LocaleKeys.sideBar_others.tr(),
),
if (today.isNotEmpty) ...[
...today,
const VSpace(8),
const Divider(height: 1),
const VSpace(8),
],
if (thisWeek.isNotEmpty) ...[
...thisWeek,
const VSpace(8),
const Divider(height: 1),
const VSpace(8),
],
...others.isNotEmpty && (today.isNotEmpty || thisWeek.isNotEmpty)
? others
: _buildGroups(
context,
state.otherViews,
LocaleKeys.sideBar_others.tr(),
showHeader: false,
),
],
),
),
@ -96,23 +116,23 @@ class FavoriteMenu extends StatelessWidget {
List<Widget> _buildGroups(
BuildContext context,
List<ViewPB> views,
String title,
) {
String title, {
bool showHeader = true,
}) {
return [
if (views.isNotEmpty) ...[
SizedBox(
height: 24,
child: FlowyText(
title,
fontSize: 12.0,
color: Theme.of(context).hintColor,
if (showHeader)
SizedBox(
height: 24,
child: FlowyText(
title,
fontSize: 12.0,
color: Theme.of(context).hintColor,
),
),
),
const VSpace(2),
_buildGroupedViews(context, views),
const VSpace(8),
const Divider(height: 1),
const VSpace(8),
],
];
}

View File

@ -1,6 +1,7 @@
import 'package:appflowy/generated/flowy_svgs.g.dart';
import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/workspace/application/menu/sidebar_sections_bloc.dart';
import 'package:appflowy/workspace/application/sidebar/space/space_bloc.dart';
import 'package:appflowy/workspace/application/user/user_workspace_bloc.dart';
import 'package:appflowy/workspace/presentation/home/home_sizes.dart';
import 'package:appflowy/workspace/presentation/home/menu/sidebar/shared/rename_view_dialog.dart';
@ -48,13 +49,23 @@ class SidebarNewPageButton extends StatelessWidget {
context.read<UserWorkspaceBloc>().state.isCollabWorkspaceOn
? ViewSectionPB.Private
: ViewSectionPB.Public;
context.read<SidebarSectionsBloc>().add(
SidebarSectionsEvent.createRootViewInSection(
name: viewName,
viewSection: section,
index: 0,
),
);
final spaceState = context.read<SpaceBloc>().state;
if (spaceState.spaces.isNotEmpty) {
context.read<SpaceBloc>().add(
SpaceEvent.createPage(
name: viewName,
index: 0,
),
);
} else {
context.read<SidebarSectionsBloc>().add(
SidebarSectionsEvent.createRootViewInSection(
name: viewName,
viewSection: section,
index: 0,
),
);
}
}
},
);

View File

@ -2,6 +2,7 @@ import 'dart:async';
import 'package:appflowy/generated/flowy_svgs.g.dart';
import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/plugins/blank/blank.dart';
import 'package:appflowy/shared/feature_flags.dart';
import 'package:appflowy/startup/startup.dart';
import 'package:appflowy/workspace/application/action_navigation/action_navigation_bloc.dart';
@ -116,6 +117,7 @@ class HomeSideBar extends StatelessWidget {
userProfile,
state.currentWorkspace?.workspaceId ??
workspaceSetting.workspaceId,
openFirstPage: false,
),
),
),
@ -134,11 +136,23 @@ class HomeSideBar extends StatelessWidget {
BlocListener<SpaceBloc, SpaceState>(
listenWhen: (p, c) =>
p.lastCreatedPage?.id != c.lastCreatedPage?.id,
listener: (context, state) => context.read<TabsBloc>().add(
TabsEvent.openPlugin(
plugin: state.lastCreatedPage!.plugin(),
),
),
listener: (context, state) {
final page = state.lastCreatedPage;
if (page == null || page.id.isEmpty) {
// open the blank page
context.read<TabsBloc>().add(
TabsEvent.openPlugin(
plugin: BlankPagePlugin(),
),
);
} else {
context.read<TabsBloc>().add(
TabsEvent.openPlugin(
plugin: state.lastCreatedPage!.plugin(),
),
);
}
},
),
BlocListener<ActionNavigationBloc, ActionNavigationState>(
listenWhen: (_, curr) => curr.action != null,
@ -151,23 +165,27 @@ class HomeSideBar extends StatelessWidget {
if (actionType == UserWorkspaceActionType.create ||
actionType == UserWorkspaceActionType.delete ||
actionType == UserWorkspaceActionType.open) {
context.read<SidebarSectionsBloc>().add(
SidebarSectionsEvent.reload(
userProfile,
state.currentWorkspace?.workspaceId ??
workspaceSetting.workspaceId,
),
);
if (context.read<SpaceBloc>().state.spaces.isEmpty) {
context.read<SidebarSectionsBloc>().add(
SidebarSectionsEvent.reload(
userProfile,
state.currentWorkspace?.workspaceId ??
workspaceSetting.workspaceId,
),
);
} else {
context.read<SpaceBloc>().add(
SpaceEvent.reset(
userProfile,
state.currentWorkspace?.workspaceId ??
workspaceSetting.workspaceId,
),
);
}
context
.read<FavoriteBloc>()
.add(const FavoriteEvent.fetchFavorites());
context.read<SpaceBloc>().add(
SpaceEvent.reset(
userProfile,
state.currentWorkspace?.workspaceId ??
workspaceSetting.workspaceId,
),
);
}
},
),

View File

@ -50,7 +50,13 @@ class _CreateSpacePopupState extends State<CreateSpacePopup> {
),
),
const VSpace(8.0),
_SpaceNameTextField(onChanged: (value) => spaceName = value),
_SpaceNameTextField(
onChanged: (value) => spaceName = value,
onSubmitted: (value) {
spaceName = value;
_createSpace();
},
),
const VSpace(20.0),
SpacePermissionSwitch(
onPermissionChanged: (value) => spacePermission = value,
@ -59,29 +65,36 @@ class _CreateSpacePopupState extends State<CreateSpacePopup> {
SpaceCancelOrConfirmButton(
confirmButtonName: LocaleKeys.button_create.tr(),
onCancel: () => Navigator.of(context).pop(),
onConfirm: () {
context.read<SpaceBloc>().add(
SpaceEvent.create(
name: spaceName,
icon: spaceIcon,
iconColor: spaceIconColor,
permission: spacePermission,
),
);
Navigator.of(context).pop();
},
onConfirm: () => _createSpace(),
),
],
),
);
}
void _createSpace() {
context.read<SpaceBloc>().add(
SpaceEvent.create(
name: spaceName,
icon: spaceIcon,
iconColor: spaceIconColor,
permission: spacePermission,
createNewPageByDefault: true,
),
);
Navigator.of(context).pop();
}
}
class _SpaceNameTextField extends StatelessWidget {
const _SpaceNameTextField({required this.onChanged});
const _SpaceNameTextField({
required this.onChanged,
required this.onSubmitted,
});
final void Function(String name) onChanged;
final void Function(String name) onSubmitted;
@override
Widget build(BuildContext context) {
@ -98,8 +111,9 @@ class _SpaceNameTextField extends StatelessWidget {
SizedBox(
height: 40,
child: FlowyTextField(
text: LocaleKeys.space_defaultSpaceName.tr(),
hintText: LocaleKeys.space_spaceName.tr(),
onChanged: onChanged,
onSubmitted: onSubmitted,
),
),
],

View File

@ -199,7 +199,7 @@ class SpaceCancelOrConfirmButton extends StatelessWidget {
radius: BorderRadius.circular(8),
text: FlowyText.regular(
confirmButtonName,
color: Theme.of(context).colorScheme.onPrimary,
color: Colors.white,
),
onTap: onConfirm,
),

View File

@ -7,6 +7,7 @@ import 'package:appflowy/workspace/application/tabs/tabs_bloc.dart';
import 'package:appflowy/workspace/application/view/view_bloc.dart';
import 'package:appflowy/workspace/application/view/view_ext.dart';
import 'package:appflowy/workspace/presentation/home/home_sizes.dart';
import 'package:appflowy/workspace/presentation/home/hotkeys.dart';
import 'package:appflowy/workspace/presentation/home/menu/menu_shared_state.dart';
import 'package:appflowy/workspace/presentation/home/menu/sidebar/favorites/favorite_folder.dart';
import 'package:appflowy/workspace/presentation/home/menu/sidebar/shared/rename_view_dialog.dart';
@ -79,6 +80,18 @@ class _SpaceState extends State<_Space> {
final PropertyValueNotifier<bool> isExpandedNotifier =
PropertyValueNotifier(false);
@override
void initState() {
super.initState();
switchToTheNextSpace.addListener(_switchToNextSpace);
}
@override
void dispose() {
switchToTheNextSpace.removeListener(_switchToNextSpace);
super.dispose();
}
@override
Widget build(BuildContext context) {
return BlocBuilder<SpaceBloc, SpaceState>(
@ -142,10 +155,6 @@ class _SpaceState extends State<_Space> {
SpaceEvent.createPage(
name: viewName,
index: 0,
viewSection:
space.spacePermission == SpacePermission.publicToAll
? ViewSectionPB.Public
: ViewSectionPB.Private,
),
);
@ -154,6 +163,10 @@ class _SpaceState extends State<_Space> {
},
);
}
void _switchToNextSpace() {
context.read<SpaceBloc>().add(const SpaceEvent.switchToNextSpace());
}
}
class _Pages extends StatelessWidget {

View File

@ -1,5 +1,8 @@
import 'dart:io';
import 'package:appflowy/generated/flowy_svgs.g.dart';
import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/util/theme_extension.dart';
import 'package:appflowy/workspace/application/sidebar/space/space_bloc.dart';
import 'package:appflowy/workspace/presentation/home/home_sizes.dart';
import 'package:appflowy/workspace/presentation/home/menu/sidebar/space/manage_space_popup.dart';
@ -13,6 +16,7 @@ import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
import 'package:appflowy_popover/appflowy_popover.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
import 'package:flowy_infra_ui/widget/flowy_tooltip.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
@ -70,7 +74,6 @@ class _SidebarSpaceHeaderState extends State<SidebarSpaceHeader> {
height: HomeSizes.workspaceSectionHeight,
child: FlowyButton(
margin: const EdgeInsets.only(left: 6.0, right: 4.0),
// rightIcon: _buildRightIcon(),
iconPadding: 10.0,
text: _buildChild(),
rightIcon: const HSpace(60.0),
@ -88,30 +91,50 @@ class _SidebarSpaceHeaderState extends State<SidebarSpaceHeader> {
}
Widget _buildChild() {
return Row(
final color = Theme.of(context).isLightMode ? Colors.white : Colors.black;
final textSpan = TextSpan(
children: [
SpaceIcon(
dimension: 20,
space: widget.space,
cornerRadius: 6.0,
TextSpan(
text: '${LocaleKeys.space_quicklySwitch.tr()}\n',
style:
Theme.of(context).tooltipTheme.textStyle!.copyWith(color: color),
),
const HSpace(10),
Flexible(
child: FlowyText.medium(
widget.space.name,
lineHeight: 1.15,
fontSize: 14.0,
overflow: TextOverflow.ellipsis,
),
),
const HSpace(4.0),
FlowySvg(
widget.isExpanded
? FlowySvgs.workspace_drop_down_menu_show_s
: FlowySvgs.workspace_drop_down_menu_hide_s,
TextSpan(
text: Platform.isMacOS ? '⌘+O' : 'Ctrl+O',
style: Theme.of(context)
.tooltipTheme
.textStyle!
.copyWith(color: Theme.of(context).hintColor),
),
],
);
return FlowyTooltip(
richMessage: textSpan,
child: Row(
children: [
SpaceIcon(
dimension: 20,
space: widget.space,
cornerRadius: 6.0,
),
const HSpace(10),
Flexible(
child: FlowyText.medium(
widget.space.name,
lineHeight: 1.15,
fontSize: 14.0,
overflow: TextOverflow.ellipsis,
),
),
const HSpace(4.0),
FlowySvg(
widget.isExpanded
? FlowySvgs.workspace_drop_down_menu_show_s
: FlowySvgs.workspace_drop_down_menu_hide_s,
),
],
),
);
}
Widget _buildRightIcon() {

View File

@ -55,7 +55,6 @@ extension ViewMoreActionTypeExtension on SpaceMoreActionType {
Widget get rightIcon {
switch (this) {
case SpaceMoreActionType.changeIcon:
return const FlowySvg(FlowySvgs.view_item_right_arrow_s);
case SpaceMoreActionType.rename:
case SpaceMoreActionType.collapseAllPages:
case SpaceMoreActionType.divider:

View File

@ -1,5 +1,6 @@
import 'package:appflowy/generated/flowy_svgs.g.dart';
import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/util/theme_extension.dart';
import 'package:appflowy/workspace/application/sidebar/space/space_bloc.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
@ -22,7 +23,9 @@ class _SpaceMigrationState extends State<SpaceMigration> {
padding: const EdgeInsets.all(12),
clipBehavior: Clip.antiAlias,
decoration: ShapeDecoration(
color: const Color(0x66F5EAFF),
color: Theme.of(context).isLightMode
? const Color(0x66F5EAFF)
: const Color(0x1AFFFFFF),
shape: RoundedRectangleBorder(
side: const BorderSide(
strokeAlign: BorderSide.strokeAlignOutside,
@ -129,13 +132,6 @@ class _MigrationTitle extends StatelessWidget {
lineHeight: 1.2,
),
),
GestureDetector(
onTap: onClose,
child: const Padding(
padding: EdgeInsets.only(top: 3.0),
child: FlowySvg(FlowySvgs.upgrade_close_s),
),
),
],
);
}

View File

@ -82,7 +82,6 @@ extension ViewMoreActionTypeExtension on ViewMoreActionType {
switch (this) {
case ViewMoreActionType.changeIcon:
case ViewMoreActionType.moveTo:
return const FlowySvg(FlowySvgs.view_item_right_arrow_s);
case ViewMoreActionType.favorite:
case ViewMoreActionType.unFavorite:
case ViewMoreActionType.duplicate:

View File

@ -53,8 +53,8 @@ packages:
dependency: "direct main"
description:
path: "."
ref: d73e8893d1f1b06566ebed5868698be75c6b7f93
resolved-ref: d73e8893d1f1b06566ebed5868698be75c6b7f93
ref: b5da6e4
resolved-ref: b5da6e4afcb832ca74f588d7007824b02b5d51de
url: "https://github.com/AppFlowy-IO/appflowy-editor.git"
source: git
version: "2.5.1"

View File

@ -186,7 +186,7 @@ dependency_overrides:
appflowy_editor:
git:
url: https://github.com/AppFlowy-IO/appflowy-editor.git
ref: "d73e8893d1f1b06566ebed5868698be75c6b7f93"
ref: "b5da6e4"
sheet:
git:

View File

@ -1,5 +1,4 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.89999 13.8666L5.89999 3.36531L5.89999 2.1333H3.59999C2.49542 2.1333 1.59999 3.02874 1.59999 4.1333L1.59999 11.8666C1.59999 12.9712 2.49542 13.8666 3.59999 13.8666H5.89999Z" stroke="#171717" stroke-width="1.1" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M5.89999 2.1333V12.6346V13.8666H10.2V12.6346V2.1333H5.89999Z" stroke="#171717" stroke-width="1.1" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M10.2 2.1333V12.6346V13.8666H12.5C13.6046 13.8666 14.5 12.9712 14.5 11.8666V4.1333C14.5 3.02873 13.6046 2.1333 12.5 2.1333H10.2Z" stroke="#171717" stroke-width="1.1" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M6.89922 12.9772V3.0232C6.89922 2.0782 6.50769 1.7002 5.53498 1.7002H3.06345C2.09075 1.7002 1.69922 2.0782 1.69922 3.0232V12.9772C1.69922 13.9222 2.09075 14.3002 3.06345 14.3002H5.53498C6.50769 14.3002 6.89922 13.9222 6.89922 12.9772Z" stroke="#171717" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M14.2996 8.78519V3.0652C14.2996 2.0902 13.9081 1.7002 12.9354 1.7002H10.4638C9.49114 1.7002 9.09961 2.0902 9.09961 3.0652V8.78519C9.09961 9.76019 9.49114 10.1502 10.4638 10.1502H12.9354C13.9081 10.1502 14.2996 9.76019 14.2996 8.78519Z" stroke="#171717" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 753 B

After

Width:  |  Height:  |  Size: 725 B

View File

@ -1,7 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<g opacity="0.6">
<path d="M4.23516 7.99941C4.23516 8.60693 3.74267 9.09941 3.13516 9.09941C2.52764 9.09941 2.03516 8.60693 2.03516 7.99941C2.03516 7.3919 2.52764 6.89941 3.13516 6.89941C3.74267 6.89941 4.23516 7.3919 4.23516 7.99941Z" fill="#171717"/>
<path d="M9.10234 7.99941C9.10234 8.60693 8.60986 9.09941 8.00234 9.09941C7.39483 9.09941 6.90234 8.60693 6.90234 7.99941C6.90234 7.3919 7.39483 6.89941 8.00234 6.89941C8.60986 6.89941 9.10234 7.3919 9.10234 7.99941Z" fill="#171717"/>
<path d="M13.9695 7.99941C13.9695 8.60693 13.477 9.09941 12.8695 9.09941C12.262 9.09941 11.7695 8.60693 11.7695 7.99941C11.7695 7.3919 12.262 6.89941 12.8695 6.89941C13.477 6.89941 13.9695 7.3919 13.9695 7.99941Z" fill="#171717"/>
</g>
</svg>
<path d="M9.39568 7.6963L6.91032 5.56599C6.65085 5.34358 6.25 5.52795 6.25 5.86969L6.25 10.1303C6.25 10.4721 6.65085 10.6564 6.91032 10.434L9.39568 8.3037C9.58192 8.14406 9.58192 7.85594 9.39568 7.6963Z" fill="#333333"/>
</svg>

Before

Width:  |  Height:  |  Size: 851 B

After

Width:  |  Height:  |  Size: 331 B

View File

@ -1,3 +1,3 @@
<svg width="8" height="10" viewBox="0 0 8 10" fill="none" xmlns="http://www.w3.org/2000/svg">
<path opacity="0.5" d="M6.7881 4.14174V3.56457C6.7881 2.82926 6.7881 0.599609 4 0.599609C1.2119 0.599609 1.2119 2.82926 1.2119 3.56457V4.14174C0.304836 4.35522 0 4.97984 0 6.33186V7.12252C0 8.86196 0.505579 9.39961 2.14127 9.39961H5.85873C7.49442 9.39961 8 8.86196 8 7.12252V6.33186C8 4.97984 7.69516 4.35522 6.7881 4.14174ZM4 7.59692C3.54647 7.59692 3.18217 7.20949 3.18217 6.72719C3.18217 6.24489 3.54647 5.85746 4 5.85746C4.45353 5.85746 4.81782 6.24489 4.81782 6.72719C4.81782 7.20949 4.45353 7.59692 4 7.59692ZM5.67286 4.05477H2.32714V3.56457C2.32714 2.41021 2.5948 1.78559 4 1.78559C5.4052 1.78559 5.67286 2.41021 5.67286 3.56457V4.05477Z" fill="#171717"/>
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
<path opacity="0.4" fill-rule="evenodd" clip-rule="evenodd" d="M8.78714 4.75039V4.16515C8.78714 3.42984 8.6 1.25 5.99904 1.25C3.3 1.25 3.21094 3.42984 3.21094 4.16515V4.75039L3.38817 4.73529L3.2119 4.75123C2.30484 4.99873 2 5.7229 2 7.29041V8.20709C2 10.2238 2.50558 10.9996 4.14127 10.9996H7.85873C9.49442 10.9996 10 10.2238 10 8.20709V7.29041C10 5.7229 9.69516 4.99873 8.7881 4.75123L8.64331 4.73813L8.78714 4.75039ZM4.32618 4.16515V4.65048L7.6719 4.65039V4.16515C7.6719 3.0108 7.3 2.3002 5.99904 2.3002C4.65 2.3002 4.32618 3.0108 4.32618 4.16515ZM6.00078 8.95078C6.66352 8.95078 7.20078 8.41352 7.20078 7.75078C7.20078 7.08804 6.66352 6.55078 6.00078 6.55078C5.33804 6.55078 4.80078 7.08804 4.80078 7.75078C4.80078 8.41352 5.33804 8.95078 6.00078 8.95078Z" fill="#171717"/>
</svg>

Before

Width:  |  Height:  |  Size: 764 B

After

Width:  |  Height:  |  Size: 880 B

View File

@ -1,5 +1,4 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M4.16484 3.1001H8.96484L8.96484 15.1001C8.96484 15.6524 8.51713 16.1001 7.96484 16.1001H4.16484C3.33642 16.1001 2.66484 15.4285 2.66484 14.6001L2.66484 4.6001C2.66484 3.77167 3.33642 3.1001 4.16484 3.1001Z" stroke="#49CD57" stroke-width="1.58" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M15.2648 3.1001H8.96484V19.4001C8.96484 20.2285 9.63642 20.9001 10.4648 20.9001H13.7648C14.5933 20.9001 15.2648 20.2285 15.2648 19.4001V3.1001Z" stroke="#49CD57" stroke-width="1.58" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M20.0656 12.6001H16.2656C15.7133 12.6001 15.2656 12.1524 15.2656 11.6001V3.1001H20.0656C20.8941 3.1001 21.5656 3.77167 21.5656 4.6001V11.1001C21.5656 11.9285 20.8941 12.6001 20.0656 12.6001Z" stroke="#49CD57" stroke-width="1.58" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M10.2023 19.4658V4.53479C10.2023 3.11729 9.61505 2.55029 8.15599 2.55029H4.4487C2.98964 2.55029 2.40234 3.11729 2.40234 4.53479V19.4658C2.40234 20.8833 2.98964 21.4503 4.4487 21.4503H8.15599C9.61505 21.4503 10.2023 20.8833 10.2023 19.4658Z" stroke="#49CD57" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M21.6008 13.1778V4.59779C21.6008 3.13529 21.0135 2.55029 19.5544 2.55029H15.8471C14.3881 2.55029 13.8008 3.13529 13.8008 4.59779V13.1778C13.8008 14.6403 14.3881 15.2253 15.8471 15.2253H19.5544C21.0135 15.2253 21.6008 14.6403 21.6008 13.1778Z" stroke="#49CD57" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 932 B

After

Width:  |  Height:  |  Size: 775 B

View File

@ -260,7 +260,7 @@
"recent": "Recent",
"today": "Today",
"thisWeek": "This week",
"others": "Others",
"others": "Other favorites",
"justNow": "just now",
"minutesAgo": "{count} minutes ago",
"lastViewed": "Last viewed",
@ -1891,16 +1891,16 @@
"clearSearchTooltip": "Clear search field"
},
"space": {
"delete": "Delete space",
"deleteConfirmation": "Are you sure you want to delete this space?",
"deleteConfirmationDescription": "This action cannot be undone, and will remove the pages and data in this space.",
"rename": "Rename space",
"delete": "Delete",
"deleteConfirmation": "Delete: {Space Name}",
"deleteConfirmationDescription": "All pages within this Space will be deleted and moved to Trash.",
"rename": "Rename Space",
"changeIcon": "Change icon",
"manage": "Manage space",
"addNewSpace": "Add new space",
"manage": "Manage Space",
"addNewSpace": "Create Space",
"collapseAllSubPages": "Collapse all subpages",
"createNewSpace": "Create new space",
"createSpaceDescription": "Separate your tabs for life, work, project and more",
"createNewSpace": "Create a new space",
"createSpaceDescription": "Create multiple public and private spaces to better organize your work.",
"spaceName": "Space name",
"permission": "Permission",
"publicPermission": "Public",
@ -1910,14 +1910,15 @@
"spaceIconBackground": "Background color",
"spaceIcon": "Icon",
"dangerZone": "Danger Zone",
"unableToDeleteLastSpace": "Cannot delete the last space",
"unableToDeleteSpaceNotCreatedByYou": "Cannot delete a space created by others",
"enableSpacesForYourWorkspace": "Enable spaces for your workspace",
"unableToDeleteLastSpace": "Unable to delete the last Space",
"unableToDeleteSpaceNotCreatedByYou": "Unable to delete Spaces created by others",
"enableSpacesForYourWorkspace": "Enable Spaces for your workspace",
"title": "Spaces",
"defaultSpaceName": "General",
"upgradeSpaceTitle": "Enable Spaces for your workspace",
"upgradeSpaceDescription": "Create multiple public and private spaces to better organize your work.",
"upgrade": "Upgrade",
"upgradeYourSpace": "Upgrade your space"
"upgradeSpaceTitle": "Enable Spaces",
"upgradeSpaceDescription": "Create multiple public and private Spaces to better organize your workspace.",
"upgrade": "Update",
"upgradeYourSpace": "Create multiple Spaces",
"quicklySwitch": "Quickly switch to the next space"
}
}
}