chore: merge release/0.6.1

This commit is contained in:
Lucas.Xu 2024-06-21 11:24:38 +08:00
parent 7586a0ed48
commit e73b310076
18 changed files with 169 additions and 129 deletions

View File

@ -26,7 +26,7 @@ CARGO_MAKE_EXTEND_WORKSPACE_MAKEFILE = true
CARGO_MAKE_CRATE_FS_NAME = "dart_ffi"
CARGO_MAKE_CRATE_NAME = "dart-ffi"
LIB_NAME = "dart_ffi"
APPFLOWY_VERSION = "0.6.0"
APPFLOWY_VERSION = "0.6.1"
FLUTTER_DESKTOP_FEATURES = "dart"
PRODUCT_NAME = "AppFlowy"
MACOSX_DEPLOYMENT_TARGET = "11.0"

View File

@ -4,6 +4,7 @@ import 'package:appflowy/mobile/presentation/bottom_sheet/bottom_sheet.dart';
import 'package:appflowy/mobile/presentation/home/space/mobile_space_header.dart';
import 'package:appflowy/mobile/presentation/home/space/mobile_space_menu.dart';
import 'package:appflowy/mobile/presentation/page_item/mobile_view_item.dart';
import 'package:appflowy/mobile/presentation/presentation.dart';
import 'package:appflowy/workspace/application/sidebar/folder/folder_bloc.dart';
import 'package:appflowy/workspace/application/sidebar/space/space_bloc.dart';
import 'package:appflowy/workspace/application/view/view_bloc.dart';
@ -22,6 +23,18 @@ class MobileSpace extends StatefulWidget {
}
class _MobileSpaceState extends State<MobileSpace> {
@override
void initState() {
super.initState();
createNewPageNotifier.addListener(_createNewPage);
}
@override
void dispose() {
createNewPageNotifier.removeListener(_createNewPage);
super.dispose();
}
@override
Widget build(BuildContext context) {
return BlocBuilder<SpaceBloc, SpaceState>(
@ -81,6 +94,14 @@ class _MobileSpaceState extends State<MobileSpace> {
},
);
}
void _createNewPage() {
context.read<SpaceBloc>().add(
SpaceEvent.createPage(
name: LocaleKeys.menuAppHeader_defaultNewPageName.tr(),
),
);
}
}
class _Pages extends StatelessWidget {

View File

@ -1,18 +1,15 @@
import 'dart:ui';
import 'package:appflowy/generated/flowy_svgs.g.dart';
import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/mobile/application/mobile_router.dart';
import 'package:appflowy/mobile/presentation/bottom_sheet/bottom_sheet.dart';
import 'package:appflowy/util/theme_extension.dart';
import 'package:appflowy/workspace/application/workspace/workspace_service.dart';
import 'package:appflowy_backend/dispatch/dispatch.dart';
import 'package:appflowy_backend/log.dart';
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:appflowy_editor/appflowy_editor.dart';
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
final PropertyValueNotifier<ViewLayoutPB?> createNewPageNotifier =
PropertyValueNotifier(null);
const _homeLabel = 'home';
const _addLabel = 'add';
const _notificationLabel = 'notification';
@ -93,7 +90,7 @@ class MobileBottomNavigationBar extends StatelessWidget {
void _onTap(BuildContext context, int bottomBarIndex) {
if (_items[bottomBarIndex].label == _addLabel) {
// show an add dialog
_showCreatePageBottomSheet(context);
createNewPageNotifier.value = ViewLayoutPB.Document;
return;
}
// When navigating to a new branch, it's recommended to use the goBranch
@ -108,40 +105,4 @@ class MobileBottomNavigationBar extends StatelessWidget {
initialLocation: bottomBarIndex == navigationShell.currentIndex,
);
}
void _showCreatePageBottomSheet(BuildContext context) {
showMobileBottomSheet(
context,
showHeader: true,
title: LocaleKeys.sideBar_addAPage.tr(),
showDragHandle: true,
showCloseButton: true,
useRootNavigator: true,
builder: (sheetContext) {
return AddNewPageWidgetBottomSheet(
view: ViewPB(),
onAction: (layout) async {
Navigator.of(sheetContext).pop();
final currentWorkspaceId =
await FolderEventReadCurrentWorkspace().send();
await currentWorkspaceId.fold((s) async {
final workspaceService = WorkspaceService(workspaceId: s.id);
final result = await workspaceService.createView(
name: LocaleKeys.menuAppHeader_defaultNewPageName.tr(),
viewSection: ViewSectionPB.Private,
layout: layout,
);
result.fold((s) {
context.pushView(s);
}, (e) {
Log.error('Failed to create new page: $e');
});
}, (e) {
Log.error('Failed to read current workspace: $e');
});
},
);
},
);
}
}

View File

@ -73,8 +73,7 @@ class _AppFlowyMobileToolbarState extends State<AppFlowyMobileToolbar> {
ValueListenableBuilder(
valueListenable: isKeyboardShow,
builder: (context, isKeyboardShow, __) {
return AnimatedContainer(
duration: const Duration(milliseconds: 110),
return SizedBox(
// only adding padding when the keyboard is triggered by editor
height: isKeyboardShow && widget.editorState.selection != null
? widget.toolbarHeight
@ -383,37 +382,26 @@ class _MobileToolbarState extends State<_MobileToolbar>
return ValueListenableBuilder(
valueListenable: cachedKeyboardHeight,
builder: (_, height, ___) {
var paddingHeight = height;
if (Platform.isAndroid) {
// use the viewInsets to get the keyboard height on Android
paddingHeight = MediaQuery.of(context).viewInsets.bottom;
// if the padding height is 0 and the keyboard height is not 0,
// use the keyboard height
if (paddingHeight == 0 && height != 0) {
paddingHeight = height + MediaQuery.of(context).viewPadding.bottom;
}
}
debugPrint('Keyboard height: $paddingHeight');
return AnimatedContainer(
duration: const Duration(microseconds: 110),
height: paddingHeight,
child: ValueListenableBuilder(
valueListenable: showMenuNotifier,
builder: (_, showingMenu, __) {
return AnimatedContainer(
duration: const Duration(microseconds: 110),
height: height,
child: (showingMenu && selectedMenuIndex != null)
? widget.toolbarItems[selectedMenuIndex!].menuBuilder?.call(
context,
widget.editorState,
this,
) ??
const SizedBox.shrink()
: const SizedBox.shrink(),
);
},
),
return ValueListenableBuilder(
valueListenable: showMenuNotifier,
builder: (_, showingMenu, __) {
var paddingHeight = height;
if (Platform.isAndroid) {
paddingHeight =
height + MediaQuery.of(context).viewPadding.bottom;
}
return SizedBox(
height: paddingHeight,
child: (showingMenu && selectedMenuIndex != null)
? widget.toolbarItems[selectedMenuIndex!].menuBuilder?.call(
context,
widget.editorState,
this,
) ??
const SizedBox.shrink()
: const SizedBox.shrink(),
);
},
);
},
);

View File

@ -19,6 +19,7 @@ import 'package:appflowy_editor/appflowy_editor.dart' hide Log;
import 'package:appflowy_result/appflowy_result.dart';
import 'package:collection/collection.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra/uuid.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:protobuf/protobuf.dart';
@ -257,6 +258,10 @@ class SpaceBloc extends Bloc<SpaceEvent, SpaceState> {
);
},
reset: (userProfile, workspaceId) async {
if (workspaceId == _workspaceId) {
return;
}
_reset(userProfile, workspaceId);
add(
@ -321,6 +326,7 @@ class SpaceBloc extends Bloc<SpaceEvent, SpaceState> {
required String icon,
required String iconColor,
required SpacePermission permission,
String? viewId,
}) async {
final section = switch (permission) {
SpacePermission.publicToAll => ViewSectionPB.Public,
@ -331,6 +337,7 @@ class SpaceBloc extends Bloc<SpaceEvent, SpaceState> {
name: name,
viewSection: section,
setAsCurrent: false,
viewId: viewId,
);
return await result.fold((space) async {
Log.info('Space created: $space');
@ -476,56 +483,82 @@ class SpaceBloc extends Bloc<SpaceEvent, SpaceState> {
if (members.items.length == 1 || isOwner) {
// create a new public space and a new private space
// move all the views in the workspace to the new public/private space
final publicViews =
await _workspaceService.getPublicViews().getOrThrow();
// only migrate the public space if there are any public views
if (publicViews.isNotEmpty) {
final publicSpace = await _createSpace(
name: 'Shared',
icon: builtInSpaceIcons.first,
iconColor: builtInSpaceColors.first,
permission: SpacePermission.publicToAll,
);
if (publicSpace != null) {
for (final view in publicViews.reversed) {
if (view.isSpace) {
continue;
}
await ViewBackendService.moveViewV2(
viewId: view.id,
newParentId: publicSpace.id,
prevViewId: view.parentViewId,
);
}
}
}
}
// create a new private space
final privateViews =
await _workspaceService.getPrivateViews().getOrThrow();
// only migrate the private space if there are any private views
if (privateViews.isNotEmpty) {
final privateSpace = await _createSpace(
name: 'Private',
icon: builtInSpaceIcons.last,
iconColor: builtInSpaceColors.last,
permission: SpacePermission.private,
var publicViews = await _workspaceService.getPublicViews().getOrThrow();
final containsPublicSpace = publicViews.any(
(e) => e.isSpace && e.spacePermission == SpacePermission.publicToAll,
);
if (privateSpace != null) {
for (final view in privateViews.reversed) {
publicViews = publicViews.where((e) => !e.isSpace).toList();
// if there is already a public space, don't migrate the public space
// only migrate the public space if there are any public views
if (publicViews.isEmpty || containsPublicSpace) {
return true;
}
final viewId = fixedUuid(user.id.toInt(), UuidType.publicSpace);
final publicSpace = await _createSpace(
name: 'Shared',
icon: builtInSpaceIcons.first,
iconColor: builtInSpaceColors.first,
permission: SpacePermission.publicToAll,
viewId: viewId,
);
Log.info('migrating: created a new public space: ${publicSpace?.id}');
if (publicSpace != null) {
for (final view in publicViews.reversed) {
if (view.isSpace) {
continue;
}
await ViewBackendService.moveViewV2(
viewId: view.id,
newParentId: privateSpace.id,
prevViewId: view.parentViewId,
newParentId: publicSpace.id,
prevViewId: null,
);
Log.info(
'migrating: migrate ${view.name}(${view.id}) to public space(${publicSpace.id})',
);
}
}
}
// create a new private space
final viewId = fixedUuid(user.id.toInt(), UuidType.privateSpace);
var privateViews = await _workspaceService.getPrivateViews().getOrThrow();
// if there is already a private space, don't migrate the private space
final containsPrivateSpace = privateViews.any(
(e) => e.isSpace && e.spacePermission == SpacePermission.private,
);
privateViews = privateViews.where((e) => !e.isSpace).toList();
if (privateViews.isEmpty || containsPrivateSpace) {
return true;
}
// only migrate the private space if there are any private views
final privateSpace = await _createSpace(
name: 'Private',
icon: builtInSpaceIcons.last,
iconColor: builtInSpaceColors.last,
permission: SpacePermission.private,
viewId: viewId,
);
Log.info('migrating: created a new private space: ${privateSpace?.id}');
if (privateSpace != null) {
for (final view in privateViews.reversed) {
if (view.isSpace) {
continue;
}
await ViewBackendService.moveViewV2(
viewId: view.id,
newParentId: privateSpace.id,
prevViewId: null,
);
Log.info(
'migrating: migrate ${view.name}(${view.id}) to private space(${privateSpace.id})',
);
}
}
return true;
} catch (e) {
Log.error('migrate space error: $e');
@ -538,14 +571,16 @@ class SpaceBloc extends Bloc<SpaceEvent, SpaceState> {
required List<ViewPB> publicViews,
required List<ViewPB> privateViews,
}) async {
final publicSpaces =
spaces.where((e) => e.spacePermission == SpacePermission.publicToAll);
final publicSpaces = spaces.where(
(e) => e.spacePermission == SpacePermission.publicToAll,
);
if (publicSpaces.isEmpty && publicViews.isNotEmpty) {
return true;
}
final privateSpaces =
spaces.where((e) => e.spacePermission == SpacePermission.private);
final privateSpaces = spaces.where(
(e) => e.spacePermission == SpacePermission.private,
);
if (privateSpaces.isEmpty && privateViews.isNotEmpty) {
return true;
}

View File

@ -38,6 +38,7 @@ class ViewBackendService {
/// If the index is null, the view will be added to the end of the list.
int? index,
ViewSectionPB? section,
final String? viewId,
}) {
final payload = CreateViewPayloadPB.create()
..parentViewId = parentViewId
@ -63,6 +64,10 @@ class ViewBackendService {
payload.section = section;
}
if (viewId != null) {
payload.viewId = viewId;
}
return FolderEventCreateView(payload).send();
}

View File

@ -18,6 +18,7 @@ class WorkspaceService {
int? index,
ViewLayoutPB? layout,
bool? setAsCurrent,
String? viewId,
}) {
final payload = CreateViewPayloadPB.create()
..parentViewId = workspaceId
@ -37,6 +38,10 @@ class WorkspaceService {
payload.setAsCurrent = setAsCurrent;
}
if (viewId != null) {
payload.viewId = viewId;
}
return FolderEventCreateView(payload).send();
}

View File

@ -1,5 +1,19 @@
import 'package:uuid/data.dart';
import 'package:uuid/rng.dart';
import 'package:uuid/uuid.dart';
const _uuid = Uuid();
String uuid() {
return const Uuid().v4();
return _uuid.v4();
}
String fixedUuid(int seed, UuidType type) {
return _uuid.v4(config: V4Options(null, MathRNG(seed: seed + type.index)));
}
enum UuidType {
// 0.6.0
publicSpace,
privateSpace,
}

View File

@ -2174,10 +2174,10 @@ packages:
dependency: "direct overridden"
description:
name: uuid
sha256: cd210a09f7c18cbe5a02511718e0334de6559871052c90a90c0cca46a4aa81c8
sha256: "814e9e88f21a176ae1359149021870e87f7cddaf633ab678a5d2b0bff7fd1ba8"
url: "https://pub.dev"
source: hosted
version: "4.3.3"
version: "4.4.0"
value_layout_builder:
dependency: transitive
description:

View File

@ -15,7 +15,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
# Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
version: 0.6.0
version: 0.6.1
environment:
flutter: ">=3.22.0"
@ -199,7 +199,7 @@ dependency_overrides:
ref: e44458d
path: sheet
uuid: ^4.1.0
uuid: ^4.4.0
flutter_cache_manager:
git:

View File

@ -21,6 +21,7 @@ impl EventIntegrationTest {
set_as_current: true,
index: None,
section: None,
view_id: None,
};
EventBuilder::new(self.clone())
.event(FolderEvent::CreateView)

View File

@ -45,6 +45,7 @@ impl EventIntegrationTest {
set_as_current: true,
index: None,
section: None,
view_id: None,
};
EventBuilder::new(self.clone())
.event(FolderEvent::CreateView)
@ -76,6 +77,7 @@ impl EventIntegrationTest {
set_as_current: true,
index: None,
section: None,
view_id: None,
};
EventBuilder::new(self.clone())
.event(FolderEvent::CreateView)
@ -102,6 +104,7 @@ impl EventIntegrationTest {
set_as_current: true,
index: None,
section: None,
view_id: None,
};
EventBuilder::new(self.clone())
.event(FolderEvent::CreateView)

View File

@ -65,6 +65,7 @@ impl DocumentEventTest {
set_as_current: true,
index: None,
section: None,
view_id: None,
};
EventBuilder::new(core.clone())
.event(FolderEvent::CreateView)

View File

@ -42,6 +42,7 @@ impl EventIntegrationTest {
set_as_current: true,
index: None,
section: None,
view_id: None,
};
let view = EventBuilder::new(self.clone())
.event(FolderEvent::CreateView)

View File

@ -230,6 +230,7 @@ impl EventIntegrationTest {
set_as_current: false,
index: None,
section: None,
view_id: None,
};
EventBuilder::new(self.clone())
.event(FolderEvent::CreateView)
@ -293,6 +294,7 @@ impl ViewTest {
set_as_current: true,
index: None,
section: None,
view_id: None,
};
let view = EventBuilder::new(sdk.clone())

View File

@ -252,6 +252,7 @@ pub async fn create_view(
set_as_current: true,
index: None,
section: None,
view_id: None,
};
EventBuilder::new(sdk.clone())
.event(CreateView)

View File

@ -258,6 +258,9 @@ pub struct CreateViewPayloadPB {
// The view in private section will only be shown in the user's private view list.
#[pb(index = 10, one_of)]
pub section: Option<ViewSectionPB>,
#[pb(index = 11, one_of)]
pub view_id: Option<String>,
}
#[derive(Eq, PartialEq, Hash, Debug, ProtoBuf_Enum, Clone, Default)]
@ -313,7 +316,8 @@ impl TryInto<CreateViewParams> for CreateViewPayloadPB {
fn try_into(self) -> Result<CreateViewParams, Self::Error> {
let name = ViewName::parse(self.name)?.0;
let parent_view_id = ViewIdentify::parse(self.parent_view_id)?.0;
let view_id = gen_view_id().to_string();
// if view_id is not provided, generate a new view_id
let view_id = self.view_id.unwrap_or_else(|| gen_view_id().to_string());
Ok(CreateViewParams {
parent_view_id,

View File

@ -59,8 +59,6 @@ AppDir:
- libwayland-cursor0:amd64
- libwayland-client0:amd64
- libwayland-egl1:amd64
- libmpv-dev:amd64
- mpv:amd64
files:
include: []
exclude: