mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
Merge branch 'main' into workspace-rename-no-icon
This commit is contained in:
commit
76fcba5966
2
frontend/.vscode/launch.json
vendored
2
frontend/.vscode/launch.json
vendored
@ -12,7 +12,7 @@
|
|||||||
"program": "./lib/main.dart",
|
"program": "./lib/main.dart",
|
||||||
"type": "dart",
|
"type": "dart",
|
||||||
"env": {
|
"env": {
|
||||||
"RUST_LOG": "trace",
|
"RUST_LOG": "debug",
|
||||||
"RUST_BACKTRACE": "1"
|
"RUST_BACKTRACE": "1"
|
||||||
},
|
},
|
||||||
// uncomment the following line to testing performance.
|
// uncomment the following line to testing performance.
|
||||||
|
@ -26,7 +26,7 @@ CARGO_MAKE_EXTEND_WORKSPACE_MAKEFILE = true
|
|||||||
CARGO_MAKE_CRATE_FS_NAME = "dart_ffi"
|
CARGO_MAKE_CRATE_FS_NAME = "dart_ffi"
|
||||||
CARGO_MAKE_CRATE_NAME = "dart-ffi"
|
CARGO_MAKE_CRATE_NAME = "dart-ffi"
|
||||||
LIB_NAME = "dart_ffi"
|
LIB_NAME = "dart_ffi"
|
||||||
APPFLOWY_VERSION = "0.5.0"
|
APPFLOWY_VERSION = "0.5.1"
|
||||||
FLUTTER_DESKTOP_FEATURES = "dart,rev-sqlite"
|
FLUTTER_DESKTOP_FEATURES = "dart,rev-sqlite"
|
||||||
PRODUCT_NAME = "AppFlowy"
|
PRODUCT_NAME = "AppFlowy"
|
||||||
MACOSX_DEPLOYMENT_TARGET = "11.0"
|
MACOSX_DEPLOYMENT_TARGET = "11.0"
|
||||||
|
@ -40,19 +40,19 @@ void main() {
|
|||||||
|
|
||||||
await tester.openSettings();
|
await tester.openSettings();
|
||||||
await tester.openSettingsPage(SettingsPage.user);
|
await tester.openSettingsPage(SettingsPage.user);
|
||||||
final userAvatarFinder = find.descendant(
|
// final userAvatarFinder = find.descendant(
|
||||||
of: find.byType(SettingsUserView),
|
// of: find.byType(SettingsUserView),
|
||||||
matching: find.byType(UserAvatar),
|
// matching: find.byType(UserAvatar),
|
||||||
);
|
// );
|
||||||
|
|
||||||
// Open icon picker dialog and select emoji
|
// Open icon picker dialog and select emoji
|
||||||
await tester.tap(userAvatarFinder);
|
// await tester.tap(userAvatarFinder);
|
||||||
await tester.pumpAndSettle();
|
// await tester.pumpAndSettle();
|
||||||
await tester.tapEmoji('😁');
|
// await tester.tapEmoji('😁');
|
||||||
await tester.pumpAndSettle();
|
// await tester.pumpAndSettle();
|
||||||
final UserAvatar userAvatar =
|
// final UserAvatar userAvatar =
|
||||||
tester.widget(userAvatarFinder) as UserAvatar;
|
// tester.widget(userAvatarFinder) as UserAvatar;
|
||||||
expect(userAvatar.iconUrl, '😁');
|
// expect(userAvatar.iconUrl, '😁');
|
||||||
|
|
||||||
// enter user name
|
// enter user name
|
||||||
final userNameFinder = find.descendant(
|
final userNameFinder = find.descendant(
|
||||||
@ -81,12 +81,12 @@ void main() {
|
|||||||
await tester.openSettingsPage(SettingsPage.user);
|
await tester.openSettingsPage(SettingsPage.user);
|
||||||
|
|
||||||
// verify icon
|
// verify icon
|
||||||
final userAvatarFinder = find.descendant(
|
// final userAvatarFinder = find.descendant(
|
||||||
of: find.byType(SettingsUserView),
|
// of: find.byType(SettingsUserView),
|
||||||
matching: find.byType(UserAvatar),
|
// matching: find.byType(UserAvatar),
|
||||||
);
|
// );
|
||||||
final UserAvatar userAvatar = tester.widget(userAvatarFinder) as UserAvatar;
|
// final UserAvatar userAvatar = tester.widget(userAvatarFinder) as UserAvatar;
|
||||||
expect(userAvatar.iconUrl, '😁');
|
// expect(userAvatar.iconUrl, '😁');
|
||||||
|
|
||||||
// verify name
|
// verify name
|
||||||
final userNameFinder = find.descendant(
|
final userNameFinder = find.descendant(
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/workspace/application/settings/prelude.dart';
|
import 'package:appflowy/workspace/application/settings/prelude.dart';
|
||||||
import 'package:appflowy/workspace/presentation/home/menu/sidebar/sidebar_user.dart';
|
import 'package:appflowy/workspace/presentation/home/menu/sidebar/sidebar_setting.dart';
|
||||||
import 'package:appflowy/workspace/presentation/settings/settings_dialog.dart';
|
import 'package:appflowy/workspace/presentation/settings/settings_dialog.dart';
|
||||||
import 'package:appflowy/workspace/presentation/settings/widgets/settings_appearance/direction_setting.dart';
|
import 'package:appflowy/workspace/presentation/settings/widgets/settings_appearance/direction_setting.dart';
|
||||||
import 'package:appflowy/workspace/presentation/settings/widgets/settings_menu_element.dart';
|
import 'package:appflowy/workspace/presentation/settings/widgets/settings_menu_element.dart';
|
||||||
|
@ -1,13 +1,15 @@
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
import 'package:appflowy/core/helpers/url_launcher.dart';
|
import 'package:appflowy/core/helpers/url_launcher.dart';
|
||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/mobile/presentation/bottom_sheet/show_mobile_bottom_sheet.dart';
|
import 'package:appflowy/mobile/presentation/bottom_sheet/show_mobile_bottom_sheet.dart';
|
||||||
import 'package:appflowy/mobile/presentation/widgets/widgets.dart';
|
import 'package:appflowy/mobile/presentation/widgets/widgets.dart';
|
||||||
|
import 'package:appflowy/shared/appflowy_cache_manager.dart';
|
||||||
|
import 'package:appflowy/startup/startup.dart';
|
||||||
import 'package:appflowy/util/share_log_files.dart';
|
import 'package:appflowy/util/share_log_files.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
import 'package:package_info_plus/package_info_plus.dart';
|
import 'package:package_info_plus/package_info_plus.dart';
|
||||||
|
|
||||||
import 'widgets/widgets.dart';
|
import 'widgets/widgets.dart';
|
||||||
@ -51,6 +53,31 @@ class SupportSettingGroup extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
MobileSettingItem(
|
||||||
|
name: LocaleKeys.settings_files_clearCache.tr(),
|
||||||
|
trailing: const Icon(
|
||||||
|
Icons.chevron_right,
|
||||||
|
),
|
||||||
|
onTap: () async {
|
||||||
|
await showFlowyMobileConfirmDialog(
|
||||||
|
context,
|
||||||
|
title: FlowyText(
|
||||||
|
LocaleKeys.settings_files_areYouSureToClearCache.tr(),
|
||||||
|
maxLines: 2,
|
||||||
|
),
|
||||||
|
content: FlowyText(
|
||||||
|
LocaleKeys.settings_files_clearCacheDesc.tr(),
|
||||||
|
fontSize: 12,
|
||||||
|
maxLines: 4,
|
||||||
|
),
|
||||||
|
actionButtonTitle: LocaleKeys.button_yes.tr(),
|
||||||
|
actionButtonColor: Theme.of(context).colorScheme.error,
|
||||||
|
onActionButtonPressed: () async {
|
||||||
|
await getIt<FlowyCacheManager>().clearAllCache();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
import 'package:appflowy/plugins/database/grid/presentation/layout/sizes.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/plugins/database/application/tab_bar_bloc.dart';
|
import 'package:appflowy/plugins/database/application/tab_bar_bloc.dart';
|
||||||
|
import 'package:appflowy/plugins/database/grid/presentation/layout/sizes.dart';
|
||||||
import 'package:appflowy/workspace/application/view/view_ext.dart';
|
import 'package:appflowy/workspace/application/view/view_ext.dart';
|
||||||
import 'package:appflowy/workspace/presentation/widgets/dialogs.dart';
|
import 'package:appflowy/workspace/presentation/widgets/dialogs.dart';
|
||||||
import 'package:appflowy/workspace/presentation/widgets/pop_up_action.dart';
|
import 'package:appflowy/workspace/presentation/widgets/pop_up_action.dart';
|
||||||
@ -13,6 +11,7 @@ import 'package:easy_localization/easy_localization.dart';
|
|||||||
import 'package:flowy_infra/size.dart';
|
import 'package:flowy_infra/size.dart';
|
||||||
import 'package:flowy_infra/theme_extension.dart';
|
import 'package:flowy_infra/theme_extension.dart';
|
||||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
import 'tab_bar_add_button.dart';
|
import 'tab_bar_add_button.dart';
|
||||||
@ -235,7 +234,7 @@ class TabBarItemButton extends StatelessWidget {
|
|||||||
NavigatorTextFieldDialog(
|
NavigatorTextFieldDialog(
|
||||||
title: LocaleKeys.menuAppHeader_renameDialog.tr(),
|
title: LocaleKeys.menuAppHeader_renameDialog.tr(),
|
||||||
value: view.name,
|
value: view.name,
|
||||||
confirm: (newValue) {
|
onConfirm: (newValue, _) {
|
||||||
context.read<DatabaseTabBarBloc>().add(
|
context.read<DatabaseTabBarBloc>().add(
|
||||||
DatabaseTabBarEvent.renameView(view.id, newValue),
|
DatabaseTabBarEvent.renameView(view.id, newValue),
|
||||||
);
|
);
|
||||||
|
@ -360,9 +360,7 @@ class DepthOptionAction extends PopoverActionCell {
|
|||||||
(e) => HoverButton(
|
(e) => HoverButton(
|
||||||
onTap: () => onTap(e.inner),
|
onTap: () => onTap(e.inner),
|
||||||
itemHeight: ActionListSizes.itemHeight,
|
itemHeight: ActionListSizes.itemHeight,
|
||||||
leftIcon: null,
|
|
||||||
name: e.name,
|
name: e.name,
|
||||||
rightIcon: null,
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.toList();
|
.toList();
|
||||||
|
@ -59,9 +59,7 @@ class _ResizableImageState extends State<ResizableImage> {
|
|||||||
|
|
||||||
imageWidth = widget.width;
|
imageWidth = widget.width;
|
||||||
|
|
||||||
if (widget.type == CustomImageType.internal) {
|
_userProfilePB = context.read<DocumentBloc>().state.userProfilePB;
|
||||||
_userProfilePB = context.read<DocumentBloc>().state.userProfilePB;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -0,0 +1,25 @@
|
|||||||
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
|
import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart';
|
||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
|
||||||
|
extension AFRolePBExtension on AFRolePB {
|
||||||
|
bool get isOwner => this == AFRolePB.Owner;
|
||||||
|
|
||||||
|
bool get canInvite => isOwner;
|
||||||
|
|
||||||
|
bool get canDelete => isOwner;
|
||||||
|
|
||||||
|
bool get canUpdate => isOwner;
|
||||||
|
|
||||||
|
String get description {
|
||||||
|
switch (this) {
|
||||||
|
case AFRolePB.Owner:
|
||||||
|
return LocaleKeys.settings_appearance_members_owner.tr();
|
||||||
|
case AFRolePB.Member:
|
||||||
|
return LocaleKeys.settings_appearance_members_member.tr();
|
||||||
|
case AFRolePB.Guest:
|
||||||
|
return LocaleKeys.settings_appearance_members_guest.tr();
|
||||||
|
}
|
||||||
|
throw UnimplementedError('Unknown role: $this');
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,61 @@
|
|||||||
|
import 'package:appflowy_backend/log.dart';
|
||||||
|
import 'package:path_provider/path_provider.dart';
|
||||||
|
|
||||||
|
class FlowyCacheManager {
|
||||||
|
final _caches = <ICache>[];
|
||||||
|
|
||||||
|
// if you add a new cache, you should register it here.
|
||||||
|
void registerCache(ICache cache) {
|
||||||
|
_caches.add(cache);
|
||||||
|
}
|
||||||
|
|
||||||
|
void unregisterAllCache(ICache cache) {
|
||||||
|
_caches.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> clearAllCache() async {
|
||||||
|
try {
|
||||||
|
for (final cache in _caches) {
|
||||||
|
await cache.clearAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.info('Cache cleared');
|
||||||
|
} catch (e) {
|
||||||
|
Log.error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<int> getCacheSize() async {
|
||||||
|
try {
|
||||||
|
int tmpDirSize = 0;
|
||||||
|
for (final cache in _caches) {
|
||||||
|
tmpDirSize += await cache.cacheSize();
|
||||||
|
}
|
||||||
|
Log.info('Cache size: $tmpDirSize');
|
||||||
|
return tmpDirSize;
|
||||||
|
} catch (e) {
|
||||||
|
Log.error(e);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class ICache {
|
||||||
|
Future<int> cacheSize();
|
||||||
|
Future<void> clearAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
class TemporaryDirectoryCache implements ICache {
|
||||||
|
@override
|
||||||
|
Future<int> cacheSize() async {
|
||||||
|
final tmpDir = await getTemporaryDirectory();
|
||||||
|
final tmpDirStat = await tmpDir.stat();
|
||||||
|
return tmpDirStat.size;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> clearAll() async {
|
||||||
|
final tmpDir = await getTemporaryDirectory();
|
||||||
|
await tmpDir.delete(recursive: true);
|
||||||
|
}
|
||||||
|
}
|
@ -39,8 +39,10 @@ class FlowyNetworkImage extends StatelessWidget {
|
|||||||
assert(userProfilePB != null && userProfilePB!.token.isNotEmpty);
|
assert(userProfilePB != null && userProfilePB!.token.isNotEmpty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final manager = CustomImageCacheManager();
|
||||||
|
|
||||||
return CachedNetworkImage(
|
return CachedNetworkImage(
|
||||||
cacheManager: CustomImageCacheManager(),
|
cacheManager: manager,
|
||||||
httpHeaders: _header(),
|
httpHeaders: _header(),
|
||||||
imageUrl: url,
|
imageUrl: url,
|
||||||
fit: fit,
|
fit: fit,
|
||||||
@ -50,6 +52,12 @@ class FlowyNetworkImage extends StatelessWidget {
|
|||||||
errorWidget: (context, url, error) =>
|
errorWidget: (context, url, error) =>
|
||||||
errorWidgetBuilder?.call(context, url, error) ??
|
errorWidgetBuilder?.call(context, url, error) ??
|
||||||
const SizedBox.shrink(),
|
const SizedBox.shrink(),
|
||||||
|
errorListener: (value) {
|
||||||
|
// try to clear the image cache.
|
||||||
|
manager.removeFile(url);
|
||||||
|
|
||||||
|
Log.error(value.toString());
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
|
import 'package:appflowy/shared/appflowy_cache_manager.dart';
|
||||||
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
|
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
|
||||||
|
|
||||||
class CustomImageCacheManager extends CacheManager with ImageCacheManager {
|
class CustomImageCacheManager extends CacheManager
|
||||||
|
with ImageCacheManager
|
||||||
|
implements ICache {
|
||||||
CustomImageCacheManager._() : super(Config(key));
|
CustomImageCacheManager._() : super(Config(key));
|
||||||
|
|
||||||
factory CustomImageCacheManager() => _instance;
|
factory CustomImageCacheManager() => _instance;
|
||||||
@ -8,4 +11,16 @@ class CustomImageCacheManager extends CacheManager with ImageCacheManager {
|
|||||||
static final CustomImageCacheManager _instance = CustomImageCacheManager._();
|
static final CustomImageCacheManager _instance = CustomImageCacheManager._();
|
||||||
|
|
||||||
static const key = 'appflowy_image_cache';
|
static const key = 'appflowy_image_cache';
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<int> cacheSize() async {
|
||||||
|
// https://github.com/Baseflow/flutter_cache_manager/issues/239#issuecomment-719475429
|
||||||
|
// this package does not provide a way to get the cache size
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> clearAll() async {
|
||||||
|
await emptyCache();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,8 @@ import 'package:appflowy/plugins/document/presentation/editor_plugins/copy_and_p
|
|||||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/openai/service/openai_client.dart';
|
import 'package:appflowy/plugins/document/presentation/editor_plugins/openai/service/openai_client.dart';
|
||||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/stability_ai/stability_ai_client.dart';
|
import 'package:appflowy/plugins/document/presentation/editor_plugins/stability_ai/stability_ai_client.dart';
|
||||||
import 'package:appflowy/plugins/trash/application/prelude.dart';
|
import 'package:appflowy/plugins/trash/application/prelude.dart';
|
||||||
|
import 'package:appflowy/shared/appflowy_cache_manager.dart';
|
||||||
|
import 'package:appflowy/shared/custom_image_cache_manager.dart';
|
||||||
import 'package:appflowy/startup/startup.dart';
|
import 'package:appflowy/startup/startup.dart';
|
||||||
import 'package:appflowy/startup/tasks/appflowy_cloud_task.dart';
|
import 'package:appflowy/startup/tasks/appflowy_cloud_task.dart';
|
||||||
import 'package:appflowy/user/application/auth/af_cloud_auth_service.dart';
|
import 'package:appflowy/user/application/auth/af_cloud_auth_service.dart';
|
||||||
@ -128,6 +130,12 @@ void _resolveCommonService(
|
|||||||
getIt.registerFactory<BaseAppearance>(
|
getIt.registerFactory<BaseAppearance>(
|
||||||
() => PlatformExtension.isMobile ? MobileAppearance() : DesktopAppearance(),
|
() => PlatformExtension.isMobile ? MobileAppearance() : DesktopAppearance(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
getIt.registerFactory<FlowyCacheManager>(
|
||||||
|
() => FlowyCacheManager()
|
||||||
|
..registerCache(TemporaryDirectoryCache())
|
||||||
|
..registerCache(CustomImageCacheManager()),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _resolveUserDeps(GetIt getIt, IntegrationMode mode) {
|
void _resolveUserDeps(GetIt getIt, IntegrationMode mode) {
|
||||||
|
@ -5,7 +5,6 @@ import 'package:appflowy/env/backend_env.dart';
|
|||||||
import 'package:appflowy/env/cloud_env.dart';
|
import 'package:appflowy/env/cloud_env.dart';
|
||||||
import 'package:appflowy/user/application/auth/device_id.dart';
|
import 'package:appflowy/user/application/auth/device_id.dart';
|
||||||
import 'package:appflowy_backend/appflowy_backend.dart';
|
import 'package:appflowy_backend/appflowy_backend.dart';
|
||||||
import 'package:appflowy_backend/log.dart';
|
|
||||||
import 'package:path_provider/path_provider.dart';
|
import 'package:path_provider/path_provider.dart';
|
||||||
import 'package:path/path.dart' as path;
|
import 'package:path/path.dart' as path;
|
||||||
|
|
||||||
@ -39,7 +38,6 @@ class InitRustSDKTask extends LaunchTask {
|
|||||||
rustEnvs: context.config.rustEnvs,
|
rustEnvs: context.config.rustEnvs,
|
||||||
);
|
);
|
||||||
await context.getIt<FlowySDK>().init(jsonEncode(env.toJson()));
|
await context.getIt<FlowySDK>().init(jsonEncode(env.toJson()));
|
||||||
Log.info('Rust SDK initialized');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -79,15 +79,13 @@ class UserBackendService {
|
|||||||
return UserEventOpenAnonUser().send();
|
return UserEventOpenAnonUser().send();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<FlowyResult<List<WorkspacePB>, FlowyError>> getWorkspaces() {
|
Future<FlowyResult<List<UserWorkspacePB>, FlowyError>> getWorkspaces() {
|
||||||
// final request = WorkspaceIdPB.create();
|
return UserEventGetAllWorkspace().send().then((value) {
|
||||||
// return FolderEventReadAllWorkspaces(request).send().then((result) {
|
return value.fold(
|
||||||
// return result.fold(
|
(workspaces) => FlowyResult.success(workspaces.items),
|
||||||
// (workspaces) => FlowyResult.success(workspaces.items),
|
(error) => FlowyResult.failure(error),
|
||||||
// (error) => FlowyResult.failure(error),
|
);
|
||||||
// );
|
});
|
||||||
// });
|
|
||||||
return Future.value(FlowyResult.success([]));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<FlowyResult<void, FlowyError>> openWorkspace(String workspaceId) {
|
Future<FlowyResult<void, FlowyError>> openWorkspace(String workspaceId) {
|
||||||
@ -118,4 +116,18 @@ class UserBackendService {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<FlowyResult<UserWorkspacePB, FlowyError>> createUserWorkspace(
|
||||||
|
String name,
|
||||||
|
) {
|
||||||
|
final request = CreateWorkspacePB.create()..name = name;
|
||||||
|
return UserEventCreateWorkspace(request).send();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<FlowyResult<void, FlowyError>> deleteWorkspaceById(
|
||||||
|
String workspaceId,
|
||||||
|
) {
|
||||||
|
final request = UserWorkspaceIdPB.create()..workspaceId = workspaceId;
|
||||||
|
return UserEventDeleteWorkspace(request).send();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
import 'dart:ui';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class ColorGenerator {
|
class ColorGenerator {
|
||||||
Color generateColorFromString(String string) {
|
static Color generateColorFromString(String string) {
|
||||||
final hash = string.hashCode;
|
final int hash =
|
||||||
final int r = (hash & 0xFF0000) >> 16;
|
string.codeUnits.fold(0, (int acc, int unit) => acc + unit);
|
||||||
final int g = (hash & 0x00FF00) >> 8;
|
final double hue = (hash % 360).toDouble();
|
||||||
final int b = hash & 0x0000FF;
|
return HSLColor.fromAHSL(1.0, hue, 0.5, 0.8).toColor();
|
||||||
return Color.fromRGBO(r, g, b, 0.5);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1 +1,2 @@
|
|||||||
export 'settings_user_bloc.dart';
|
export 'settings_user_bloc.dart';
|
||||||
|
export 'user_workspace_bloc.dart';
|
||||||
|
@ -0,0 +1,134 @@
|
|||||||
|
import 'package:appflowy/user/application/user_service.dart';
|
||||||
|
import 'package:appflowy_backend/log.dart';
|
||||||
|
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
|
||||||
|
import 'package:appflowy_backend/protobuf/flowy-user/user_profile.pb.dart';
|
||||||
|
import 'package:appflowy_result/appflowy_result.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
|
|
||||||
|
part 'user_workspace_bloc.freezed.dart';
|
||||||
|
|
||||||
|
class UserWorkspaceBloc extends Bloc<UserWorkspaceEvent, UserWorkspaceState> {
|
||||||
|
UserWorkspaceBloc({
|
||||||
|
required this.userProfile,
|
||||||
|
}) : _userService = UserBackendService(userId: userProfile.id),
|
||||||
|
super(UserWorkspaceState.initial()) {
|
||||||
|
on<UserWorkspaceEvent>(
|
||||||
|
(event, emit) async {
|
||||||
|
await event.when(
|
||||||
|
initial: () async {
|
||||||
|
// do nothing
|
||||||
|
},
|
||||||
|
workspacesReceived: (workspaceId) async {},
|
||||||
|
fetchWorkspaces: () async {
|
||||||
|
final result = await _fetchWorkspaces();
|
||||||
|
if (result != null) {
|
||||||
|
emit(
|
||||||
|
state.copyWith(
|
||||||
|
currentWorkspace: result.$1,
|
||||||
|
workspaces: result.$2,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
createWorkspace: (name, desc) async {
|
||||||
|
final result = await _userService.createUserWorkspace(name);
|
||||||
|
emit(
|
||||||
|
state.copyWith(
|
||||||
|
openWorkspaceResult: null,
|
||||||
|
deleteWorkspaceResult: null,
|
||||||
|
createWorkspaceResult:
|
||||||
|
result.fold((s) => FlowyResult.success(null), (e) {
|
||||||
|
Log.error(e);
|
||||||
|
return FlowyResult.failure(e);
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
deleteWorkspace: (workspaceId) async {
|
||||||
|
final result = await _userService.deleteWorkspaceById(workspaceId);
|
||||||
|
emit(
|
||||||
|
state.copyWith(
|
||||||
|
openWorkspaceResult: null,
|
||||||
|
createWorkspaceResult: null,
|
||||||
|
deleteWorkspaceResult:
|
||||||
|
result.fold((s) => FlowyResult.success(null), (e) {
|
||||||
|
Log.error(e);
|
||||||
|
return FlowyResult.failure(e);
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
openWorkspace: (workspaceId) async {
|
||||||
|
final result = await _userService.openWorkspace(workspaceId);
|
||||||
|
emit(
|
||||||
|
state.copyWith(
|
||||||
|
createWorkspaceResult: null,
|
||||||
|
deleteWorkspaceResult: null,
|
||||||
|
openWorkspaceResult:
|
||||||
|
result.fold((s) => FlowyResult.success(null), (e) {
|
||||||
|
Log.error(e);
|
||||||
|
return FlowyResult.failure(e);
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
final UserProfilePB userProfile;
|
||||||
|
final UserBackendService _userService;
|
||||||
|
|
||||||
|
Future<(UserWorkspacePB currentWorkspace, List<UserWorkspacePB> workspaces)?>
|
||||||
|
_fetchWorkspaces() async {
|
||||||
|
final result = await _userService.getCurrentWorkspace();
|
||||||
|
return result.fold((currentWorkspace) async {
|
||||||
|
final result = await _userService.getWorkspaces();
|
||||||
|
return result.fold((workspaces) {
|
||||||
|
return (
|
||||||
|
workspaces.firstWhere(
|
||||||
|
(e) => e.workspaceId == currentWorkspace.id,
|
||||||
|
),
|
||||||
|
workspaces
|
||||||
|
);
|
||||||
|
}, (e) {
|
||||||
|
Log.error(e);
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
}, (e) {
|
||||||
|
Log.error(e);
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
class UserWorkspaceEvent with _$UserWorkspaceEvent {
|
||||||
|
const factory UserWorkspaceEvent.initial() = Initial;
|
||||||
|
const factory UserWorkspaceEvent.createWorkspace(String name, String desc) =
|
||||||
|
CreateWorkspace;
|
||||||
|
const factory UserWorkspaceEvent.fetchWorkspaces() = FetchWorkspaces;
|
||||||
|
const factory UserWorkspaceEvent.deleteWorkspace(String workspaceId) =
|
||||||
|
DeleteWorkspace;
|
||||||
|
const factory UserWorkspaceEvent.openWorkspace(String workspaceId) =
|
||||||
|
OpenWorkspace;
|
||||||
|
const factory UserWorkspaceEvent.workspacesReceived(
|
||||||
|
FlowyResult<List<UserWorkspacePB>, FlowyError> workspacesOrFail,
|
||||||
|
) = WorkspacesReceived;
|
||||||
|
}
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
class UserWorkspaceState with _$UserWorkspaceState {
|
||||||
|
const factory UserWorkspaceState({
|
||||||
|
required UserWorkspacePB? currentWorkspace,
|
||||||
|
required List<UserWorkspacePB> workspaces,
|
||||||
|
@Default(null) FlowyResult<void, FlowyError>? createWorkspaceResult,
|
||||||
|
@Default(null) FlowyResult<void, FlowyError>? deleteWorkspaceResult,
|
||||||
|
@Default(null) FlowyResult<void, FlowyError>? openWorkspaceResult,
|
||||||
|
}) = _UserWorkspaceState;
|
||||||
|
|
||||||
|
factory UserWorkspaceState.initial() =>
|
||||||
|
const UserWorkspaceState(currentWorkspace: null, workspaces: []);
|
||||||
|
}
|
@ -48,7 +48,7 @@ class WorkspaceBloc extends Bloc<WorkspaceEvent, WorkspaceState> {
|
|||||||
emit(
|
emit(
|
||||||
workspacesOrFailed.fold(
|
workspacesOrFailed.fold(
|
||||||
(workspaces) => state.copyWith(
|
(workspaces) => state.copyWith(
|
||||||
workspaces: workspaces,
|
workspaces: [],
|
||||||
successOrFailure: FlowyResult.success(null),
|
successOrFailure: FlowyResult.success(null),
|
||||||
),
|
),
|
||||||
(error) {
|
(error) {
|
||||||
|
@ -182,7 +182,7 @@ class DesktopHomeScreen extends StatelessWidget {
|
|||||||
required WorkspaceSettingPB workspaceSetting,
|
required WorkspaceSettingPB workspaceSetting,
|
||||||
}) {
|
}) {
|
||||||
final homeMenu = HomeSideBar(
|
final homeMenu = HomeSideBar(
|
||||||
user: userProfile,
|
userProfile: userProfile,
|
||||||
workspaceSetting: workspaceSetting,
|
workspaceSetting: workspaceSetting,
|
||||||
);
|
);
|
||||||
return FocusTraversalGroup(child: RepaintBoundary(child: homeMenu));
|
return FocusTraversalGroup(child: RepaintBoundary(child: homeMenu));
|
||||||
|
@ -1,13 +1,12 @@
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
import 'package:appflowy/startup/startup.dart';
|
import 'package:appflowy/startup/startup.dart';
|
||||||
import 'package:appflowy/workspace/application/home/home_setting_bloc.dart';
|
import 'package:appflowy/workspace/application/home/home_setting_bloc.dart';
|
||||||
import 'package:appflowy/workspace/application/settings/appearance/appearance_cubit.dart';
|
import 'package:appflowy/workspace/application/settings/appearance/appearance_cubit.dart';
|
||||||
import 'package:appflowy/workspace/application/sidebar/rename_view/rename_view_bloc.dart';
|
import 'package:appflowy/workspace/application/sidebar/rename_view/rename_view_bloc.dart';
|
||||||
import 'package:appflowy/workspace/application/tabs/tabs_bloc.dart';
|
import 'package:appflowy/workspace/application/tabs/tabs_bloc.dart';
|
||||||
import 'package:appflowy/workspace/presentation/home/menu/sidebar/sidebar_user.dart';
|
import 'package:appflowy/workspace/presentation/home/menu/sidebar/sidebar_setting.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
import 'package:hotkey_manager/hotkey_manager.dart';
|
import 'package:hotkey_manager/hotkey_manager.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
@ -119,7 +119,7 @@ class _PersonalFolderHeaderState extends State<PersonalFolderHeader> {
|
|||||||
createViewAndShowRenameDialogIfNeeded(
|
createViewAndShowRenameDialogIfNeeded(
|
||||||
context,
|
context,
|
||||||
LocaleKeys.newPageText.tr(),
|
LocaleKeys.newPageText.tr(),
|
||||||
(viewName) {
|
(viewName, _) {
|
||||||
if (viewName.isNotEmpty) {
|
if (viewName.isNotEmpty) {
|
||||||
context.read<MenuBloc>().add(
|
context.read<MenuBloc>().add(
|
||||||
MenuEvent.createApp(
|
MenuEvent.createApp(
|
||||||
|
@ -15,7 +15,7 @@ import 'package:flutter/material.dart';
|
|||||||
Future<void> createViewAndShowRenameDialogIfNeeded(
|
Future<void> createViewAndShowRenameDialogIfNeeded(
|
||||||
BuildContext context,
|
BuildContext context,
|
||||||
String dialogTitle,
|
String dialogTitle,
|
||||||
void Function(String viewName) createView,
|
void Function(String viewName, BuildContext context) createView,
|
||||||
) async {
|
) async {
|
||||||
final value = await getIt<KeyValueStorage>().getWithFormat(
|
final value = await getIt<KeyValueStorage>().getWithFormat(
|
||||||
KVKeys.showRenameDialogWhenCreatingNewFile,
|
KVKeys.showRenameDialogWhenCreatingNewFile,
|
||||||
@ -27,9 +27,9 @@ Future<void> createViewAndShowRenameDialogIfNeeded(
|
|||||||
title: dialogTitle,
|
title: dialogTitle,
|
||||||
value: LocaleKeys.menuAppHeader_defaultNewPageName.tr(),
|
value: LocaleKeys.menuAppHeader_defaultNewPageName.tr(),
|
||||||
autoSelectAllText: true,
|
autoSelectAllText: true,
|
||||||
confirm: createView,
|
onConfirm: createView,
|
||||||
).show(context);
|
).show(context);
|
||||||
} else {
|
} else if (context.mounted) {
|
||||||
createView(LocaleKeys.menuAppHeader_defaultNewPageName.tr());
|
createView(LocaleKeys.menuAppHeader_defaultNewPageName.tr(), context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:appflowy/shared/feature_flags.dart';
|
||||||
|
|
||||||
import 'package:appflowy/startup/startup.dart';
|
import 'package:appflowy/startup/startup.dart';
|
||||||
import 'package:appflowy/workspace/application/favorite/favorite_bloc.dart';
|
import 'package:appflowy/workspace/application/favorite/favorite_bloc.dart';
|
||||||
import 'package:appflowy/workspace/application/menu/menu_bloc.dart';
|
import 'package:appflowy/workspace/application/menu/menu_bloc.dart';
|
||||||
@ -12,12 +11,14 @@ import 'package:appflowy/workspace/presentation/home/menu/sidebar/sidebar_new_pa
|
|||||||
import 'package:appflowy/workspace/presentation/home/menu/sidebar/sidebar_top_menu.dart';
|
import 'package:appflowy/workspace/presentation/home/menu/sidebar/sidebar_top_menu.dart';
|
||||||
import 'package:appflowy/workspace/presentation/home/menu/sidebar/sidebar_trash.dart';
|
import 'package:appflowy/workspace/presentation/home/menu/sidebar/sidebar_trash.dart';
|
||||||
import 'package:appflowy/workspace/presentation/home/menu/sidebar/sidebar_user.dart';
|
import 'package:appflowy/workspace/presentation/home/menu/sidebar/sidebar_user.dart';
|
||||||
|
import 'package:appflowy/workspace/presentation/home/menu/sidebar/sidebar_workspace.dart';
|
||||||
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
|
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
|
||||||
import 'package:appflowy_backend/protobuf/flowy-folder/workspace.pb.dart';
|
import 'package:appflowy_backend/protobuf/flowy-folder/workspace.pb.dart';
|
||||||
import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart'
|
import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart'
|
||||||
show UserProfilePB;
|
show UserProfilePB;
|
||||||
import 'package:appflowy_editor/appflowy_editor.dart';
|
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||||
import 'package:flowy_infra_ui/widget/spacing.dart';
|
import 'package:flowy_infra_ui/widget/spacing.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
/// Home Sidebar is the left side bar of the home page.
|
/// Home Sidebar is the left side bar of the home page.
|
||||||
@ -30,11 +31,11 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
|||||||
class HomeSideBar extends StatelessWidget {
|
class HomeSideBar extends StatelessWidget {
|
||||||
const HomeSideBar({
|
const HomeSideBar({
|
||||||
super.key,
|
super.key,
|
||||||
required this.user,
|
required this.userProfile,
|
||||||
required this.workspaceSetting,
|
required this.workspaceSetting,
|
||||||
});
|
});
|
||||||
|
|
||||||
final UserProfilePB user;
|
final UserProfilePB userProfile;
|
||||||
|
|
||||||
final WorkspaceSettingPB workspaceSetting;
|
final WorkspaceSettingPB workspaceSetting;
|
||||||
|
|
||||||
@ -47,7 +48,7 @@ class HomeSideBar extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
BlocProvider(
|
BlocProvider(
|
||||||
create: (_) => MenuBloc(
|
create: (_) => MenuBloc(
|
||||||
user: user,
|
user: userProfile,
|
||||||
workspaceId: workspaceSetting.workspaceId,
|
workspaceId: workspaceSetting.workspaceId,
|
||||||
)..add(const MenuEvent.initial()),
|
)..add(const MenuEvent.initial()),
|
||||||
),
|
),
|
||||||
@ -103,11 +104,14 @@ class HomeSideBar extends StatelessWidget {
|
|||||||
padding: menuHorizontalInset,
|
padding: menuHorizontalInset,
|
||||||
child: SidebarTopMenu(),
|
child: SidebarTopMenu(),
|
||||||
),
|
),
|
||||||
// user, setting
|
// user or workspace, setting
|
||||||
Padding(
|
Padding(
|
||||||
padding: menuHorizontalInset,
|
padding: menuHorizontalInset,
|
||||||
child: SidebarUser(user: user, views: views),
|
child: FeatureFlag.collaborativeWorkspace.isOn
|
||||||
|
? SidebarWorkspace(userProfile: userProfile, views: views)
|
||||||
|
: SidebarUser(userProfile: userProfile, views: views),
|
||||||
),
|
),
|
||||||
|
|
||||||
const VSpace(20),
|
const VSpace(20),
|
||||||
// scrollable document list
|
// scrollable document list
|
||||||
Expanded(
|
Expanded(
|
||||||
|
@ -23,7 +23,7 @@ class SidebarNewPageButton extends StatelessWidget {
|
|||||||
onPressed: () async => createViewAndShowRenameDialogIfNeeded(
|
onPressed: () async => createViewAndShowRenameDialogIfNeeded(
|
||||||
context,
|
context,
|
||||||
LocaleKeys.newPageText.tr(),
|
LocaleKeys.newPageText.tr(),
|
||||||
(viewName) {
|
(viewName, _) {
|
||||||
if (viewName.isNotEmpty) {
|
if (viewName.isNotEmpty) {
|
||||||
context.read<MenuBloc>().add(MenuEvent.createApp(viewName));
|
context.read<MenuBloc>().add(MenuEvent.createApp(viewName));
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,104 @@
|
|||||||
|
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/startup.dart';
|
||||||
|
import 'package:appflowy/user/application/auth/auth_service.dart';
|
||||||
|
import 'package:appflowy/workspace/presentation/home/hotkeys.dart';
|
||||||
|
import 'package:appflowy/workspace/presentation/settings/settings_dialog.dart';
|
||||||
|
import 'package:appflowy_backend/log.dart';
|
||||||
|
import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart'
|
||||||
|
show UserProfilePB;
|
||||||
|
import 'package:appflowy_editor/appflowy_editor.dart' hide Log;
|
||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
import 'package:flowy_infra_ui/widget/flowy_tooltip.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:hotkey_manager/hotkey_manager.dart';
|
||||||
|
|
||||||
|
final GlobalKey _settingsDialogKey = GlobalKey();
|
||||||
|
|
||||||
|
Future<HotKeyItem?> openSettingsHotKey(BuildContext context) async {
|
||||||
|
final userProfileOrFailure = await getIt<AuthService>().getUser();
|
||||||
|
|
||||||
|
return userProfileOrFailure.fold(
|
||||||
|
(userProfile) => HotKeyItem(
|
||||||
|
hotKey: HotKey(
|
||||||
|
KeyCode.comma,
|
||||||
|
scope: HotKeyScope.inapp,
|
||||||
|
modifiers: [
|
||||||
|
PlatformExtension.isMacOS ? KeyModifier.meta : KeyModifier.control,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
keyDownHandler: (_) {
|
||||||
|
if (_settingsDialogKey.currentContext == null) {
|
||||||
|
showSettingsDialog(context, userProfile);
|
||||||
|
} else {
|
||||||
|
Navigator.of(context, rootNavigator: true)
|
||||||
|
.popUntil((route) => route.isFirst);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
(e) {
|
||||||
|
Log.error('Failed to get user $e');
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
class UserSettingButton extends StatelessWidget {
|
||||||
|
const UserSettingButton({required this.userProfile, super.key});
|
||||||
|
|
||||||
|
final UserProfilePB userProfile;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return FlowyTooltip(
|
||||||
|
message: LocaleKeys.settings_menu_open.tr(),
|
||||||
|
child: IconButton(
|
||||||
|
onPressed: () => showSettingsDialog(context, userProfile),
|
||||||
|
icon: SizedBox.square(
|
||||||
|
dimension: 20,
|
||||||
|
child: FlowySvg(
|
||||||
|
FlowySvgs.settings_m,
|
||||||
|
color: Theme.of(context).colorScheme.tertiary,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void showSettingsDialog(
|
||||||
|
BuildContext context,
|
||||||
|
UserProfilePB userProfile,
|
||||||
|
) {
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (dialogContext) {
|
||||||
|
return BlocProvider<DocumentAppearanceCubit>.value(
|
||||||
|
key: _settingsDialogKey,
|
||||||
|
value: BlocProvider.of<DocumentAppearanceCubit>(dialogContext),
|
||||||
|
child: SettingsDialog(
|
||||||
|
userProfile,
|
||||||
|
didLogout: () async {
|
||||||
|
// Pop the dialog using the dialog context
|
||||||
|
Navigator.of(dialogContext).pop();
|
||||||
|
await runAppFlowy();
|
||||||
|
},
|
||||||
|
dismissDialog: () {
|
||||||
|
if (Navigator.of(dialogContext).canPop()) {
|
||||||
|
Navigator.of(dialogContext).pop();
|
||||||
|
} else {
|
||||||
|
Log.warn("Can't pop dialog context");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
restartApp: () async {
|
||||||
|
// Pop the dialog using the dialog context
|
||||||
|
Navigator.of(dialogContext).pop();
|
||||||
|
await runAppFlowy();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
@ -1,70 +1,32 @@
|
|||||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
|
||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/plugins/document/application/document_appearance_cubit.dart';
|
|
||||||
import 'package:appflowy/startup/startup.dart';
|
|
||||||
import 'package:appflowy/user/application/auth/auth_service.dart';
|
|
||||||
import 'package:appflowy/workspace/application/menu/menu_user_bloc.dart';
|
import 'package:appflowy/workspace/application/menu/menu_user_bloc.dart';
|
||||||
import 'package:appflowy/workspace/presentation/home/hotkeys.dart';
|
import 'package:appflowy/workspace/presentation/home/menu/sidebar/sidebar_setting.dart';
|
||||||
import 'package:appflowy/workspace/presentation/notifications/widgets/notification_button.dart';
|
import 'package:appflowy/workspace/presentation/notifications/widgets/notification_button.dart';
|
||||||
import 'package:appflowy/workspace/presentation/settings/settings_dialog.dart';
|
|
||||||
import 'package:appflowy/workspace/presentation/widgets/user_avatar.dart';
|
import 'package:appflowy/workspace/presentation/widgets/user_avatar.dart';
|
||||||
import 'package:appflowy_backend/log.dart';
|
|
||||||
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
|
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
|
||||||
import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart'
|
import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart'
|
||||||
show UserProfilePB;
|
show UserProfilePB;
|
||||||
import 'package:appflowy_editor/appflowy_editor.dart' hide Log;
|
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flowy_infra_ui/style_widget/text.dart';
|
import 'package:flowy_infra_ui/style_widget/text.dart';
|
||||||
import 'package:flowy_infra_ui/widget/flowy_tooltip.dart';
|
|
||||||
import 'package:flowy_infra_ui/widget/spacing.dart';
|
import 'package:flowy_infra_ui/widget/spacing.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:hotkey_manager/hotkey_manager.dart';
|
|
||||||
|
|
||||||
final GlobalKey _settingsDialogKey = GlobalKey();
|
|
||||||
|
|
||||||
Future<HotKeyItem?> openSettingsHotKey(BuildContext context) async {
|
|
||||||
final userProfileOrFailure = await getIt<AuthService>().getUser();
|
|
||||||
|
|
||||||
return userProfileOrFailure.fold(
|
|
||||||
(userProfile) => HotKeyItem(
|
|
||||||
hotKey: HotKey(
|
|
||||||
KeyCode.comma,
|
|
||||||
scope: HotKeyScope.inapp,
|
|
||||||
modifiers: [
|
|
||||||
PlatformExtension.isMacOS ? KeyModifier.meta : KeyModifier.control,
|
|
||||||
],
|
|
||||||
),
|
|
||||||
keyDownHandler: (_) {
|
|
||||||
if (_settingsDialogKey.currentContext == null) {
|
|
||||||
_showSettingsDialog(context, userProfile);
|
|
||||||
} else {
|
|
||||||
Navigator.of(context, rootNavigator: true)
|
|
||||||
.popUntil((route) => route.isFirst);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
(e) {
|
|
||||||
Log.error('Failed to get user $e');
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// keep this widget in case we need to roll back (lucas.xu)
|
||||||
class SidebarUser extends StatelessWidget {
|
class SidebarUser extends StatelessWidget {
|
||||||
const SidebarUser({
|
const SidebarUser({
|
||||||
super.key,
|
super.key,
|
||||||
required this.user,
|
required this.userProfile,
|
||||||
required this.views,
|
required this.views,
|
||||||
});
|
});
|
||||||
|
|
||||||
final UserProfilePB user;
|
final UserProfilePB userProfile;
|
||||||
final List<ViewPB> views;
|
final List<ViewPB> views;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocProvider<MenuUserBloc>(
|
return BlocProvider<MenuUserBloc>(
|
||||||
create: (context) => MenuUserBloc(user)
|
create: (context) => MenuUserBloc(userProfile)
|
||||||
..add(
|
..add(
|
||||||
const MenuUserEvent.initial(),
|
const MenuUserEvent.initial(),
|
||||||
),
|
),
|
||||||
@ -106,61 +68,3 @@ class SidebarUser extends StatelessWidget {
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class UserSettingButton extends StatelessWidget {
|
|
||||||
const UserSettingButton({required this.userProfile, super.key});
|
|
||||||
|
|
||||||
final UserProfilePB userProfile;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return FlowyTooltip(
|
|
||||||
message: LocaleKeys.settings_menu_open.tr(),
|
|
||||||
child: IconButton(
|
|
||||||
onPressed: () => _showSettingsDialog(context, userProfile),
|
|
||||||
icon: SizedBox.square(
|
|
||||||
dimension: 20,
|
|
||||||
child: FlowySvg(
|
|
||||||
FlowySvgs.settings_m,
|
|
||||||
color: Theme.of(context).colorScheme.tertiary,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void _showSettingsDialog(
|
|
||||||
BuildContext context,
|
|
||||||
UserProfilePB userProfile,
|
|
||||||
) {
|
|
||||||
showDialog(
|
|
||||||
context: context,
|
|
||||||
builder: (dialogContext) {
|
|
||||||
return BlocProvider<DocumentAppearanceCubit>.value(
|
|
||||||
key: _settingsDialogKey,
|
|
||||||
value: BlocProvider.of<DocumentAppearanceCubit>(dialogContext),
|
|
||||||
child: SettingsDialog(
|
|
||||||
userProfile,
|
|
||||||
didLogout: () async {
|
|
||||||
// Pop the dialog using the dialog context
|
|
||||||
Navigator.of(dialogContext).pop();
|
|
||||||
await runAppFlowy();
|
|
||||||
},
|
|
||||||
dismissDialog: () {
|
|
||||||
if (Navigator.of(dialogContext).canPop()) {
|
|
||||||
Navigator.of(dialogContext).pop();
|
|
||||||
} else {
|
|
||||||
Log.warn("Can't pop dialog context");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
restartApp: () async {
|
|
||||||
// Pop the dialog using the dialog context
|
|
||||||
Navigator.of(dialogContext).pop();
|
|
||||||
await runAppFlowy();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
@ -0,0 +1,183 @@
|
|||||||
|
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||||
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
|
import 'package:appflowy/workspace/application/user/user_workspace_bloc.dart';
|
||||||
|
import 'package:appflowy/workspace/presentation/home/menu/sidebar/sidebar_setting.dart';
|
||||||
|
import 'package:appflowy/workspace/presentation/home/menu/sidebar/workspace/_sidebar_workspace_icon.dart';
|
||||||
|
import 'package:appflowy/workspace/presentation/home/menu/sidebar/workspace/_sidebar_workspace_item_list.dart';
|
||||||
|
import 'package:appflowy/workspace/presentation/home/toast.dart';
|
||||||
|
import 'package:appflowy/workspace/presentation/notifications/widgets/notification_button.dart';
|
||||||
|
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
|
||||||
|
import 'package:appflowy_backend/protobuf/flowy-user/user_profile.pb.dart';
|
||||||
|
import 'package:appflowy_editor/appflowy_editor.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:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
|
class SidebarWorkspace extends StatelessWidget {
|
||||||
|
const SidebarWorkspace({
|
||||||
|
super.key,
|
||||||
|
required this.userProfile,
|
||||||
|
required this.views,
|
||||||
|
});
|
||||||
|
|
||||||
|
final UserProfilePB userProfile;
|
||||||
|
final List<ViewPB> views;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return BlocProvider<UserWorkspaceBloc>(
|
||||||
|
create: (_) => UserWorkspaceBloc(userProfile: userProfile)
|
||||||
|
..add(const UserWorkspaceEvent.fetchWorkspaces()),
|
||||||
|
child: BlocConsumer<UserWorkspaceBloc, UserWorkspaceState>(
|
||||||
|
listener: _showResultDialog,
|
||||||
|
builder: (context, state) {
|
||||||
|
final currentWorkspace = state.currentWorkspace;
|
||||||
|
// todo: show something if there is no workspace
|
||||||
|
if (currentWorkspace == null) {
|
||||||
|
return const SizedBox.shrink();
|
||||||
|
}
|
||||||
|
return Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: _WorkspaceWrapper(
|
||||||
|
userProfile: userProfile,
|
||||||
|
currentWorkspace: currentWorkspace,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
UserSettingButton(userProfile: userProfile),
|
||||||
|
const HSpace(4),
|
||||||
|
NotificationButton(views: views),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _showResultDialog(BuildContext context, UserWorkspaceState state) {
|
||||||
|
var result = state.createWorkspaceResult;
|
||||||
|
|
||||||
|
if (result != null) {
|
||||||
|
final message = result.fold(
|
||||||
|
(s) => LocaleKeys.workspace_createSuccess.tr(),
|
||||||
|
(e) => '${LocaleKeys.workspace_createFailed.tr()}: ${e.msg}',
|
||||||
|
);
|
||||||
|
return showSnackBarMessage(context, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
result = state.deleteWorkspaceResult;
|
||||||
|
if (result != null) {
|
||||||
|
final message = result.fold(
|
||||||
|
(s) => LocaleKeys.workspace_deleteSuccess.tr(),
|
||||||
|
(e) => '${LocaleKeys.workspace_deleteFailed.tr()}: ${e.msg}',
|
||||||
|
);
|
||||||
|
showSnackBarMessage(context, message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = state.openWorkspaceResult;
|
||||||
|
if (result != null) {
|
||||||
|
final message = result.fold(
|
||||||
|
(s) => LocaleKeys.workspace_openSuccess.tr(),
|
||||||
|
(e) => '${LocaleKeys.workspace_openFailed.tr()}: ${e.msg}',
|
||||||
|
);
|
||||||
|
showSnackBarMessage(context, message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _WorkspaceWrapper extends StatefulWidget {
|
||||||
|
const _WorkspaceWrapper({
|
||||||
|
required this.userProfile,
|
||||||
|
required this.currentWorkspace,
|
||||||
|
});
|
||||||
|
|
||||||
|
final UserWorkspacePB currentWorkspace;
|
||||||
|
final UserProfilePB userProfile;
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<_WorkspaceWrapper> createState() => _WorkspaceWrapperState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _WorkspaceWrapperState extends State<_WorkspaceWrapper> {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
if (PlatformExtension.isDesktopOrWeb) {
|
||||||
|
return _DesktopWorkspaceWrapper(
|
||||||
|
userProfile: widget.userProfile,
|
||||||
|
currentWorkspace: widget.currentWorkspace,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// TODO(Lucas) mobile workspace menu
|
||||||
|
return const Placeholder();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _DesktopWorkspaceWrapper extends StatefulWidget {
|
||||||
|
const _DesktopWorkspaceWrapper({
|
||||||
|
required this.userProfile,
|
||||||
|
required this.currentWorkspace,
|
||||||
|
});
|
||||||
|
|
||||||
|
final UserWorkspacePB currentWorkspace;
|
||||||
|
final UserProfilePB userProfile;
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<_DesktopWorkspaceWrapper> createState() =>
|
||||||
|
_DesktopWorkspaceWrapperState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _DesktopWorkspaceWrapperState extends State<_DesktopWorkspaceWrapper> {
|
||||||
|
final controller = PopoverController();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return AppFlowyPopover(
|
||||||
|
direction: PopoverDirection.bottomWithCenterAligned,
|
||||||
|
offset: const Offset(0, 10),
|
||||||
|
constraints: const BoxConstraints(maxWidth: 260, maxHeight: 600),
|
||||||
|
popupBuilder: (_) {
|
||||||
|
return BlocProvider<UserWorkspaceBloc>.value(
|
||||||
|
value: context.read<UserWorkspaceBloc>(),
|
||||||
|
child: BlocBuilder<UserWorkspaceBloc, UserWorkspaceState>(
|
||||||
|
builder: (context, state) {
|
||||||
|
final currentWorkspace = state.currentWorkspace;
|
||||||
|
final workspaces = state.workspaces;
|
||||||
|
if (currentWorkspace == null || workspaces.isEmpty) {
|
||||||
|
return const SizedBox.shrink();
|
||||||
|
}
|
||||||
|
return WorkspacesMenu(
|
||||||
|
userProfile: widget.userProfile,
|
||||||
|
currentWorkspace: currentWorkspace,
|
||||||
|
workspaces: workspaces,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: FlowyButton(
|
||||||
|
onTap: () => controller.show(),
|
||||||
|
margin: const EdgeInsets.symmetric(vertical: 8),
|
||||||
|
text: Row(
|
||||||
|
children: [
|
||||||
|
const HSpace(4.0),
|
||||||
|
SizedBox(
|
||||||
|
width: 24.0,
|
||||||
|
child: WorkspaceIcon(workspace: widget.currentWorkspace),
|
||||||
|
),
|
||||||
|
const HSpace(8),
|
||||||
|
FlowyText.medium(
|
||||||
|
widget.currentWorkspace.name,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
const FlowySvg(FlowySvgs.drop_menu_show_m),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,97 @@
|
|||||||
|
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||||
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
|
import 'package:appflowy/workspace/application/user/user_workspace_bloc.dart';
|
||||||
|
import 'package:appflowy/workspace/presentation/widgets/dialogs.dart';
|
||||||
|
import 'package:appflowy/workspace/presentation/widgets/pop_up_action.dart';
|
||||||
|
import 'package:appflowy_backend/protobuf/flowy-user/protobuf.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:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
|
enum WorkspaceMoreAction {
|
||||||
|
rename,
|
||||||
|
delete,
|
||||||
|
}
|
||||||
|
|
||||||
|
class WorkspaceMoreActionList extends StatelessWidget {
|
||||||
|
const WorkspaceMoreActionList({
|
||||||
|
super.key,
|
||||||
|
required this.workspace,
|
||||||
|
});
|
||||||
|
|
||||||
|
final UserWorkspacePB workspace;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return PopoverActionList<_WorkspaceMoreActionWrapper>(
|
||||||
|
direction: PopoverDirection.bottomWithCenterAligned,
|
||||||
|
actions: WorkspaceMoreAction.values
|
||||||
|
.map((e) => _WorkspaceMoreActionWrapper(e, workspace))
|
||||||
|
.toList(),
|
||||||
|
buildChild: (controller) {
|
||||||
|
return FlowyButton(
|
||||||
|
margin: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 4.0),
|
||||||
|
useIntrinsicWidth: true,
|
||||||
|
text: const FlowySvg(
|
||||||
|
FlowySvgs.three_dots_vertical_s,
|
||||||
|
),
|
||||||
|
onTap: () {
|
||||||
|
controller.show();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
onSelected: (action, controller) {},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _WorkspaceMoreActionWrapper extends CustomActionCell {
|
||||||
|
_WorkspaceMoreActionWrapper(this.inner, this.workspace);
|
||||||
|
|
||||||
|
final WorkspaceMoreAction inner;
|
||||||
|
final UserWorkspacePB workspace;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget buildWithContext(BuildContext context) {
|
||||||
|
return FlowyButton(
|
||||||
|
text: FlowyText(
|
||||||
|
name,
|
||||||
|
color: inner == WorkspaceMoreAction.delete
|
||||||
|
? Theme.of(context).colorScheme.error
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
margin: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 6.0),
|
||||||
|
onTap: () async {
|
||||||
|
switch (inner) {
|
||||||
|
case WorkspaceMoreAction.delete:
|
||||||
|
await NavigatorAlertDialog(
|
||||||
|
title: LocaleKeys.workspace_deleteWorkspaceHintText.tr(),
|
||||||
|
confirm: () {
|
||||||
|
context.read<UserWorkspaceBloc>().add(
|
||||||
|
UserWorkspaceEvent.deleteWorkspace(workspace.workspaceId),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
).show(context);
|
||||||
|
case WorkspaceMoreAction.rename:
|
||||||
|
|
||||||
|
// TODO(Lucas): integrate with the backend
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context.mounted) {
|
||||||
|
PopoverContainer.of(context).closeAll();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
String get name {
|
||||||
|
switch (inner) {
|
||||||
|
case WorkspaceMoreAction.delete:
|
||||||
|
return LocaleKeys.button_delete.tr();
|
||||||
|
case WorkspaceMoreAction.rename:
|
||||||
|
return LocaleKeys.button_rename.tr();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
import 'package:appflowy/util/color_generator/color_generator.dart';
|
||||||
|
import 'package:appflowy_backend/protobuf/flowy-user/user_profile.pb.dart';
|
||||||
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class WorkspaceIcon extends StatelessWidget {
|
||||||
|
const WorkspaceIcon({
|
||||||
|
super.key,
|
||||||
|
required this.workspace,
|
||||||
|
});
|
||||||
|
|
||||||
|
final UserWorkspacePB workspace;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
// TODO(Lucas): support icon later
|
||||||
|
return Container(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: ColorGenerator.generateColorFromString(workspace.name),
|
||||||
|
borderRadius: BorderRadius.circular(4),
|
||||||
|
),
|
||||||
|
child: FlowyText(
|
||||||
|
workspace.name.isEmpty ? '' : workspace.name.substring(0, 1),
|
||||||
|
fontSize: 16,
|
||||||
|
color: Colors.black,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,195 @@
|
|||||||
|
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||||
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
|
import 'package:appflowy/shared/af_role_pb_extension.dart';
|
||||||
|
import 'package:appflowy/workspace/application/user/user_workspace_bloc.dart';
|
||||||
|
import 'package:appflowy/workspace/presentation/home/menu/sidebar/workspace/_sidebar_workspace_actions.dart';
|
||||||
|
import 'package:appflowy/workspace/presentation/home/menu/sidebar/workspace/_sidebar_workspace_icon.dart';
|
||||||
|
import 'package:appflowy/workspace/presentation/home/toast.dart';
|
||||||
|
import 'package:appflowy/workspace/presentation/settings/widgets/members/workspace_member_bloc.dart';
|
||||||
|
import 'package:appflowy/workspace/presentation/widgets/dialogs.dart';
|
||||||
|
import 'package:appflowy_backend/dispatch/dispatch.dart';
|
||||||
|
import 'package:appflowy_backend/protobuf/flowy-user/protobuf.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:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
|
class WorkspacesMenu extends StatelessWidget {
|
||||||
|
const WorkspacesMenu({
|
||||||
|
super.key,
|
||||||
|
required this.userProfile,
|
||||||
|
required this.currentWorkspace,
|
||||||
|
required this.workspaces,
|
||||||
|
});
|
||||||
|
|
||||||
|
final UserProfilePB userProfile;
|
||||||
|
final UserWorkspacePB currentWorkspace;
|
||||||
|
final List<UserWorkspacePB> workspaces;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
// user email
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 4),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
FlowyText.medium(
|
||||||
|
_getUserInfo(),
|
||||||
|
fontSize: 12.0,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
color: Theme.of(context).hintColor,
|
||||||
|
),
|
||||||
|
const Spacer(),
|
||||||
|
FlowyButton(
|
||||||
|
useIntrinsicWidth: true,
|
||||||
|
text: const FlowySvg(FlowySvgs.add_m),
|
||||||
|
onTap: () {
|
||||||
|
_showCreateWorkspaceDialog(context);
|
||||||
|
PopoverContainer.of(context).closeAll();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
for (final workspace in workspaces) ...[
|
||||||
|
_WorkspaceMenuItem(
|
||||||
|
workspace: workspace,
|
||||||
|
userProfile: userProfile,
|
||||||
|
isSelected: workspace.workspaceId == currentWorkspace.workspaceId,
|
||||||
|
),
|
||||||
|
const VSpace(4.0),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
String _getUserInfo() {
|
||||||
|
if (userProfile.email.isNotEmpty) {
|
||||||
|
return userProfile.email;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (userProfile.name.isNotEmpty) {
|
||||||
|
return userProfile.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
return LocaleKeys.defaultUsername.tr();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _showCreateWorkspaceDialog(BuildContext context) async {
|
||||||
|
if (context.mounted) {
|
||||||
|
await NavigatorTextFieldDialog(
|
||||||
|
title: LocaleKeys.workspace_create.tr(),
|
||||||
|
value: '',
|
||||||
|
hintText: '',
|
||||||
|
autoSelectAllText: true,
|
||||||
|
onConfirm: (name, context) async {
|
||||||
|
final request = CreateWorkspacePB.create()..name = name;
|
||||||
|
final result = await UserEventCreateWorkspace(request).send();
|
||||||
|
final message = result.fold(
|
||||||
|
(s) => LocaleKeys.workspace_createSuccess.tr(),
|
||||||
|
(e) => '${LocaleKeys.workspace_createFailed.tr()}: ${e.msg}',
|
||||||
|
);
|
||||||
|
if (context.mounted) {
|
||||||
|
showSnackBarMessage(context, message);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
).show(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _WorkspaceMenuItem extends StatelessWidget {
|
||||||
|
const _WorkspaceMenuItem({
|
||||||
|
required this.workspace,
|
||||||
|
required this.userProfile,
|
||||||
|
required this.isSelected,
|
||||||
|
});
|
||||||
|
|
||||||
|
final UserProfilePB userProfile;
|
||||||
|
final UserWorkspacePB workspace;
|
||||||
|
final bool isSelected;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return BlocProvider(
|
||||||
|
create: (_) =>
|
||||||
|
WorkspaceMemberBloc(userProfile: userProfile, workspace: workspace)
|
||||||
|
..add(const WorkspaceMemberEvent.initial())
|
||||||
|
..add(const WorkspaceMemberEvent.getWorkspaceMembers()),
|
||||||
|
child: BlocBuilder<WorkspaceMemberBloc, WorkspaceMemberState>(
|
||||||
|
builder: (context, state) {
|
||||||
|
final members = state.members;
|
||||||
|
// settings right icon inside the flowy button will
|
||||||
|
// cause the popover dismiss intermediately when click the right icon.
|
||||||
|
// so using the stack to put the right icon on the flowy button.
|
||||||
|
return Stack(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
children: [
|
||||||
|
FlowyButton(
|
||||||
|
onTap: () {
|
||||||
|
if (!isSelected) {
|
||||||
|
context.read<UserWorkspaceBloc>().add(
|
||||||
|
UserWorkspaceEvent.openWorkspace(
|
||||||
|
workspace.workspaceId,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
margin: const EdgeInsets.symmetric(vertical: 8, horizontal: 12),
|
||||||
|
iconPadding: 10.0,
|
||||||
|
leftIconSize: const Size.square(32),
|
||||||
|
leftIcon: WorkspaceIcon(
|
||||||
|
workspace: workspace,
|
||||||
|
),
|
||||||
|
text: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
FlowyText.medium(
|
||||||
|
workspace.name,
|
||||||
|
fontSize: 14.0,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
if (members.length > 1)
|
||||||
|
FlowyText(
|
||||||
|
'${members.length} ${LocaleKeys.settings_appearance_members_members.tr()}',
|
||||||
|
fontSize: 10.0,
|
||||||
|
color: Theme.of(context).hintColor,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Positioned(
|
||||||
|
right: 12.0,
|
||||||
|
child: Align(child: _buildRightIcon(context)),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildRightIcon(BuildContext context) {
|
||||||
|
// only the owner can update or delete workspace.
|
||||||
|
// only show the more action button when the workspace is selected.
|
||||||
|
if (!isSelected ||
|
||||||
|
!context.read<WorkspaceMemberBloc>().state.myRole.isOwner) {
|
||||||
|
return const SizedBox.shrink();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Row(
|
||||||
|
children: [
|
||||||
|
WorkspaceMoreActionList(workspace: workspace),
|
||||||
|
const FlowySvg(
|
||||||
|
FlowySvgs.blue_check_s,
|
||||||
|
blendMode: null,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,3 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/plugins/base/emoji/emoji_text.dart';
|
import 'package:appflowy/plugins/base/emoji/emoji_text.dart';
|
||||||
@ -25,6 +23,7 @@ import 'package:easy_localization/easy_localization.dart';
|
|||||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
import 'package:flowy_infra_ui/style_widget/hover.dart';
|
import 'package:flowy_infra_ui/style_widget/hover.dart';
|
||||||
import 'package:flowy_infra_ui/widget/flowy_tooltip.dart';
|
import 'package:flowy_infra_ui/widget/flowy_tooltip.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
typedef ViewItemOnSelected = void Function(ViewPB);
|
typedef ViewItemOnSelected = void Function(ViewPB);
|
||||||
@ -456,7 +455,7 @@ class _SingleInnerViewItemState extends State<SingleInnerViewItem> {
|
|||||||
createViewAndShowRenameDialogIfNeeded(
|
createViewAndShowRenameDialogIfNeeded(
|
||||||
context,
|
context,
|
||||||
_convertLayoutToHintText(pluginBuilder.layoutType!),
|
_convertLayoutToHintText(pluginBuilder.layoutType!),
|
||||||
(viewName) {
|
(viewName, _) {
|
||||||
if (viewName.isNotEmpty) {
|
if (viewName.isNotEmpty) {
|
||||||
viewBloc.add(
|
viewBloc.add(
|
||||||
ViewEvent.createView(
|
ViewEvent.createView(
|
||||||
@ -499,7 +498,7 @@ class _SingleInnerViewItemState extends State<SingleInnerViewItem> {
|
|||||||
autoSelectAllText: true,
|
autoSelectAllText: true,
|
||||||
value: widget.view.name,
|
value: widget.view.name,
|
||||||
maxLength: 256,
|
maxLength: 256,
|
||||||
confirm: (newValue) {
|
onConfirm: (newValue, _) {
|
||||||
context.read<ViewBloc>().add(ViewEvent.rename(newValue));
|
context.read<ViewBloc>().add(ViewEvent.rename(newValue));
|
||||||
},
|
},
|
||||||
).show(context);
|
).show(context);
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||||
import 'package:appflowy/workspace/presentation/settings/widgets/settings_file_exporter_widget.dart';
|
import 'package:appflowy/workspace/presentation/settings/widgets/files/settings_file_exporter_widget.dart';
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
import 'package:styled_widget/styled_widget.dart';
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
|
|
||||||
import '../../../../generated/locale_keys.g.dart';
|
import '../../../../../generated/locale_keys.g.dart';
|
||||||
|
|
||||||
class SettingsExportFileWidget extends StatefulWidget {
|
class SettingsExportFileWidget extends StatefulWidget {
|
||||||
const SettingsExportFileWidget({
|
const SettingsExportFileWidget({
|
@ -0,0 +1,80 @@
|
|||||||
|
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||||
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
|
import 'package:appflowy/shared/appflowy_cache_manager.dart';
|
||||||
|
import 'package:appflowy/startup/startup.dart';
|
||||||
|
import 'package:appflowy/workspace/presentation/home/toast.dart';
|
||||||
|
import 'package:appflowy/workspace/presentation/widgets/dialogs.dart';
|
||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class SettingsFileCacheWidget extends StatelessWidget {
|
||||||
|
const SettingsFileCacheWidget({
|
||||||
|
super.key,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 5.0),
|
||||||
|
child: FlowyText.medium(
|
||||||
|
LocaleKeys.settings_files_clearCache.tr(),
|
||||||
|
fontSize: 13,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const VSpace(8),
|
||||||
|
Opacity(
|
||||||
|
opacity: 0.6,
|
||||||
|
child: FlowyText(
|
||||||
|
LocaleKeys.settings_files_clearCacheDesc.tr(),
|
||||||
|
fontSize: 10,
|
||||||
|
maxLines: 3,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const _ClearCacheButton(),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ClearCacheButton extends StatelessWidget {
|
||||||
|
const _ClearCacheButton();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return FlowyIconButton(
|
||||||
|
hoverColor: Theme.of(context).colorScheme.secondaryContainer,
|
||||||
|
tooltipText: LocaleKeys.settings_files_clearCache.tr(),
|
||||||
|
icon: FlowySvg(
|
||||||
|
FlowySvgs.delete_s,
|
||||||
|
size: const Size.square(18),
|
||||||
|
color: Theme.of(context).iconTheme.color,
|
||||||
|
),
|
||||||
|
onPressed: () {
|
||||||
|
NavigatorAlertDialog(
|
||||||
|
title: LocaleKeys.settings_files_areYouSureToClearCache.tr(),
|
||||||
|
confirm: () async {
|
||||||
|
await getIt<FlowyCacheManager>().clearAllCache();
|
||||||
|
if (context.mounted) {
|
||||||
|
showSnackBarMessage(
|
||||||
|
context,
|
||||||
|
LocaleKeys.settings_files_clearCacheSuccess.tr(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
).show(context);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -1,8 +1,5 @@
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter/services.dart';
|
|
||||||
|
|
||||||
import 'package:appflowy/core/helpers/url_launcher.dart';
|
import 'package:appflowy/core/helpers/url_launcher.dart';
|
||||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||||
import 'package:appflowy/workspace/application/settings/settings_location_cubit.dart';
|
import 'package:appflowy/workspace/application/settings/settings_location_cubit.dart';
|
||||||
@ -12,12 +9,14 @@ import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
|||||||
import 'package:flowy_infra_ui/style_widget/hover.dart';
|
import 'package:flowy_infra_ui/style_widget/hover.dart';
|
||||||
import 'package:flowy_infra_ui/widget/buttons/secondary_button.dart';
|
import 'package:flowy_infra_ui/widget/buttons/secondary_button.dart';
|
||||||
import 'package:flowy_infra_ui/widget/flowy_tooltip.dart';
|
import 'package:flowy_infra_ui/widget/flowy_tooltip.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:styled_widget/styled_widget.dart';
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
|
|
||||||
import '../../../../generated/locale_keys.g.dart';
|
import '../../../../../generated/locale_keys.g.dart';
|
||||||
import '../../../../startup/startup.dart';
|
import '../../../../../startup/startup.dart';
|
||||||
import '../../../../startup/tasks/prelude.dart';
|
import '../../../../../startup/tasks/prelude.dart';
|
||||||
|
|
||||||
class SettingsFileLocationCustomizer extends StatefulWidget {
|
class SettingsFileLocationCustomizer extends StatefulWidget {
|
||||||
const SettingsFileLocationCustomizer({
|
const SettingsFileLocationCustomizer({
|
||||||
@ -262,7 +261,7 @@ class _RecoverDefaultStorageButtonState
|
|||||||
tooltipText: LocaleKeys.settings_files_recoverLocationTooltips.tr(),
|
tooltipText: LocaleKeys.settings_files_recoverLocationTooltips.tr(),
|
||||||
icon: const FlowySvg(
|
icon: const FlowySvg(
|
||||||
FlowySvgs.restore_s,
|
FlowySvgs.restore_s,
|
||||||
size: Size.square(24),
|
size: Size.square(20),
|
||||||
),
|
),
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
// reset to the default directory and reload app
|
// reset to the default directory and reload app
|
@ -18,7 +18,7 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:path/path.dart' as p;
|
import 'package:path/path.dart' as p;
|
||||||
|
|
||||||
import '../../../../generated/locale_keys.g.dart';
|
import '../../../../../generated/locale_keys.g.dart';
|
||||||
|
|
||||||
class FileExporterWidget extends StatefulWidget {
|
class FileExporterWidget extends StatefulWidget {
|
||||||
const FileExporterWidget({super.key});
|
const FileExporterWidget({super.key});
|
@ -20,10 +20,26 @@ class WorkspaceMemberBloc
|
|||||||
extends Bloc<WorkspaceMemberEvent, WorkspaceMemberState> {
|
extends Bloc<WorkspaceMemberEvent, WorkspaceMemberState> {
|
||||||
WorkspaceMemberBloc({
|
WorkspaceMemberBloc({
|
||||||
required this.userProfile,
|
required this.userProfile,
|
||||||
|
this.workspace,
|
||||||
}) : super(WorkspaceMemberState.initial()) {
|
}) : super(WorkspaceMemberState.initial()) {
|
||||||
on<WorkspaceMemberEvent>((event, emit) async {
|
on<WorkspaceMemberEvent>((event, emit) async {
|
||||||
await event.map(
|
await event.when(
|
||||||
getWorkspaceMembers: (_) async {
|
initial: () async {
|
||||||
|
if (workspace != null) {
|
||||||
|
workspaceId = workspace!.workspaceId;
|
||||||
|
} else {
|
||||||
|
final currentWorkspace =
|
||||||
|
await FolderEventReadCurrentWorkspace().send();
|
||||||
|
currentWorkspace.fold((s) {
|
||||||
|
workspaceId = s.id;
|
||||||
|
}, (e) {
|
||||||
|
assert(false, 'Failed to read current workspace: $e');
|
||||||
|
Log.error('Failed to read current workspace: $e');
|
||||||
|
workspaceId = '';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getWorkspaceMembers: () async {
|
||||||
final members = await _getWorkspaceMembers();
|
final members = await _getWorkspaceMembers();
|
||||||
final myRole = _getMyRole(members);
|
final myRole = _getMyRole(members);
|
||||||
emit(
|
emit(
|
||||||
@ -33,16 +49,16 @@ class WorkspaceMemberBloc
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
addWorkspaceMember: (e) async {
|
addWorkspaceMember: (email) async {
|
||||||
await _addWorkspaceMember(e.email);
|
await _addWorkspaceMember(email);
|
||||||
add(const WorkspaceMemberEvent.getWorkspaceMembers());
|
add(const WorkspaceMemberEvent.getWorkspaceMembers());
|
||||||
},
|
},
|
||||||
removeWorkspaceMember: (e) async {
|
removeWorkspaceMember: (email) async {
|
||||||
await _removeWorkspaceMember(e.email);
|
await _removeWorkspaceMember(email);
|
||||||
add(const WorkspaceMemberEvent.getWorkspaceMembers());
|
add(const WorkspaceMemberEvent.getWorkspaceMembers());
|
||||||
},
|
},
|
||||||
updateWorkspaceMember: (e) async {
|
updateWorkspaceMember: (email, role) async {
|
||||||
await _updateWorkspaceMember(e.email, e.role);
|
await _updateWorkspaceMember(email, role);
|
||||||
add(const WorkspaceMemberEvent.getWorkspaceMembers());
|
add(const WorkspaceMemberEvent.getWorkspaceMembers());
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@ -51,18 +67,16 @@ class WorkspaceMemberBloc
|
|||||||
|
|
||||||
final UserProfilePB userProfile;
|
final UserProfilePB userProfile;
|
||||||
|
|
||||||
|
// if the workspace is null, use the current workspace
|
||||||
|
final UserWorkspacePB? workspace;
|
||||||
|
|
||||||
|
late final String workspaceId;
|
||||||
|
|
||||||
Future<List<WorkspaceMemberPB>> _getWorkspaceMembers() async {
|
Future<List<WorkspaceMemberPB>> _getWorkspaceMembers() async {
|
||||||
// will the current workspace be synced across the app?
|
final data = QueryWorkspacePB()..workspaceId = workspaceId;
|
||||||
final currentWorkspace = await FolderEventReadCurrentWorkspace().send();
|
final result = await UserEventGetWorkspaceMember(data).send();
|
||||||
return currentWorkspace.fold((s) async {
|
return result.fold((s) => s.items, (e) {
|
||||||
final data = QueryWorkspacePB()..workspaceId = s.id;
|
Log.error('Failed to read workspace members: $e');
|
||||||
final result = await UserEventGetWorkspaceMember(data).send();
|
|
||||||
return result.fold((s) => s.items, (e) {
|
|
||||||
Log.error('Failed to read workspace members: $e');
|
|
||||||
return [];
|
|
||||||
});
|
|
||||||
}, (e) {
|
|
||||||
Log.error('Failed to read current workspace: $e');
|
|
||||||
return [];
|
return [];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -81,60 +95,46 @@ class WorkspaceMemberBloc
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _addWorkspaceMember(String email) async {
|
Future<void> _addWorkspaceMember(String email) async {
|
||||||
final currentWorkspace = await FolderEventReadCurrentWorkspace().send();
|
final data = AddWorkspaceMemberPB()
|
||||||
return currentWorkspace.fold((s) async {
|
..workspaceId = workspaceId
|
||||||
final data = AddWorkspaceMemberPB()
|
..email = email;
|
||||||
..workspaceId = s.id
|
final result = await UserEventAddWorkspaceMember(data).send();
|
||||||
..email = email;
|
result.fold((s) {
|
||||||
final result = await UserEventAddWorkspaceMember(data).send();
|
Log.info('Added workspace member: $data');
|
||||||
result.fold((s) {
|
|
||||||
Log.info('Added workspace member: $data');
|
|
||||||
}, (e) {
|
|
||||||
Log.error('Failed to add workspace member: $e');
|
|
||||||
});
|
|
||||||
}, (e) {
|
}, (e) {
|
||||||
Log.error('Failed to read current workspace: $e');
|
Log.error('Failed to add workspace member: $e');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _removeWorkspaceMember(String email) async {
|
Future<void> _removeWorkspaceMember(String email) async {
|
||||||
final currentWorkspace = await FolderEventReadCurrentWorkspace().send();
|
final data = RemoveWorkspaceMemberPB()
|
||||||
return currentWorkspace.fold((s) async {
|
..workspaceId = workspaceId
|
||||||
final data = RemoveWorkspaceMemberPB()
|
..email = email;
|
||||||
..workspaceId = s.id
|
final result = await UserEventRemoveWorkspaceMember(data).send();
|
||||||
..email = email;
|
result.fold((s) {
|
||||||
final result = await UserEventRemoveWorkspaceMember(data).send();
|
Log.info('Removed workspace member: $data');
|
||||||
result.fold((s) {
|
|
||||||
Log.info('Removed workspace member: $data');
|
|
||||||
}, (e) {
|
|
||||||
Log.error('Failed to remove workspace member: $e');
|
|
||||||
});
|
|
||||||
}, (e) {
|
}, (e) {
|
||||||
Log.error('Failed to read current workspace: $e');
|
Log.error('Failed to remove workspace member: $e');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _updateWorkspaceMember(String email, AFRolePB role) async {
|
Future<void> _updateWorkspaceMember(String email, AFRolePB role) async {
|
||||||
final currentWorkspace = await FolderEventReadCurrentWorkspace().send();
|
final data = UpdateWorkspaceMemberPB()
|
||||||
return currentWorkspace.fold((s) async {
|
..workspaceId = workspaceId
|
||||||
final data = UpdateWorkspaceMemberPB()
|
..email = email
|
||||||
..workspaceId = s.id
|
..role = role;
|
||||||
..email = email
|
final result = await UserEventUpdateWorkspaceMember(data).send();
|
||||||
..role = role;
|
result.fold((s) {
|
||||||
final result = await UserEventUpdateWorkspaceMember(data).send();
|
Log.info('Updated workspace member: $data');
|
||||||
result.fold((s) {
|
|
||||||
Log.info('Updated workspace member: $data');
|
|
||||||
}, (e) {
|
|
||||||
Log.error('Failed to update workspace member: $e');
|
|
||||||
});
|
|
||||||
}, (e) {
|
}, (e) {
|
||||||
Log.error('Failed to read current workspace: $e');
|
Log.error('Failed to update workspace member: $e');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
class WorkspaceMemberEvent with _$WorkspaceMemberEvent {
|
class WorkspaceMemberEvent with _$WorkspaceMemberEvent {
|
||||||
|
const factory WorkspaceMemberEvent.initial() = Initial;
|
||||||
const factory WorkspaceMemberEvent.getWorkspaceMembers() =
|
const factory WorkspaceMemberEvent.getWorkspaceMembers() =
|
||||||
GetWorkspaceMembers;
|
GetWorkspaceMembers;
|
||||||
const factory WorkspaceMemberEvent.addWorkspaceMember(String email) =
|
const factory WorkspaceMemberEvent.addWorkspaceMember(String email) =
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
|
import 'package:appflowy/shared/af_role_pb_extension.dart';
|
||||||
import 'package:appflowy/workspace/presentation/home/toast.dart';
|
import 'package:appflowy/workspace/presentation/home/toast.dart';
|
||||||
import 'package:appflowy/workspace/presentation/settings/widgets/members/workspace_member_bloc.dart';
|
import 'package:appflowy/workspace/presentation/settings/widgets/members/workspace_member_bloc.dart';
|
||||||
import 'package:appflowy/workspace/presentation/widgets/pop_up_action.dart';
|
import 'package:appflowy/workspace/presentation/widgets/pop_up_action.dart';
|
||||||
@ -454,25 +455,3 @@ class _MemberRoleActionWrapper extends ActionCell {
|
|||||||
throw UnimplementedError('Unknown role: $inner');
|
throw UnimplementedError('Unknown role: $inner');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension on AFRolePB {
|
|
||||||
bool get isOwner => this == AFRolePB.Owner;
|
|
||||||
|
|
||||||
bool get canInvite => isOwner;
|
|
||||||
|
|
||||||
bool get canDelete => isOwner;
|
|
||||||
|
|
||||||
bool get canUpdate => isOwner;
|
|
||||||
|
|
||||||
String get description {
|
|
||||||
switch (this) {
|
|
||||||
case AFRolePB.Owner:
|
|
||||||
return LocaleKeys.settings_appearance_members_owner.tr();
|
|
||||||
case AFRolePB.Member:
|
|
||||||
return LocaleKeys.settings_appearance_members_member.tr();
|
|
||||||
case AFRolePB.Guest:
|
|
||||||
return LocaleKeys.settings_appearance_members_guest.tr();
|
|
||||||
}
|
|
||||||
throw UnimplementedError('Unknown role: $this');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -217,7 +217,7 @@ class CloudTypeItem extends StatelessWidget {
|
|||||||
confirm: () async {
|
confirm: () async {
|
||||||
onSelected(cloudType);
|
onSelected(cloudType);
|
||||||
},
|
},
|
||||||
hideCancleButton: true,
|
hideCancelButton: true,
|
||||||
).show(context);
|
).show(context);
|
||||||
}
|
}
|
||||||
PopoverContainer.of(context).close();
|
PopoverContainer.of(context).close();
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
import 'package:appflowy/workspace/presentation/settings/widgets/setting_file_import_appflowy_data_view.dart';
|
import 'package:appflowy/workspace/presentation/settings/widgets/files/setting_file_import_appflowy_data_view.dart';
|
||||||
import 'package:appflowy/workspace/presentation/settings/widgets/settings_export_file_widget.dart';
|
import 'package:appflowy/workspace/presentation/settings/widgets/files/settings_export_file_widget.dart';
|
||||||
import 'package:appflowy/workspace/presentation/settings/widgets/settings_file_customize_location_view.dart';
|
import 'package:appflowy/workspace/presentation/settings/widgets/files/settings_file_cache_widget.dart';
|
||||||
|
import 'package:appflowy/workspace/presentation/settings/widgets/files/settings_file_customize_location_view.dart';
|
||||||
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
@ -19,15 +21,15 @@ class _SettingsFileSystemViewState extends State<SettingsFileSystemView> {
|
|||||||
// disable export data for v0.2.0 in release mode.
|
// disable export data for v0.2.0 in release mode.
|
||||||
if (kDebugMode) const SettingsExportFileWidget(),
|
if (kDebugMode) const SettingsExportFileWidget(),
|
||||||
const ImportAppFlowyData(),
|
const ImportAppFlowyData(),
|
||||||
|
// clear the cache
|
||||||
|
const SettingsFileCacheWidget(),
|
||||||
];
|
];
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return ListView.separated(
|
return SeparatedColumn(
|
||||||
shrinkWrap: true,
|
separatorBuilder: () => const Divider(),
|
||||||
itemBuilder: (context, index) => _items[index],
|
children: _items,
|
||||||
separatorBuilder: (context, index) => const Divider(),
|
|
||||||
itemCount: _items.length,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,16 @@
|
|||||||
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
|
import 'package:appflowy/startup/tasks/app_widget.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
import 'package:flowy_infra/size.dart';
|
||||||
import 'package:flowy_infra_ui/style_widget/text.dart';
|
import 'package:flowy_infra_ui/style_widget/text.dart';
|
||||||
|
import 'package:flowy_infra_ui/style_widget/text_input.dart';
|
||||||
import 'package:flowy_infra_ui/widget/buttons/primary_button.dart';
|
import 'package:flowy_infra_ui/widget/buttons/primary_button.dart';
|
||||||
import 'package:flowy_infra_ui/widget/buttons/secondary_button.dart';
|
import 'package:flowy_infra_ui/widget/buttons/secondary_button.dart';
|
||||||
|
import 'package:flowy_infra_ui/widget/dialog/styled_dialogs.dart';
|
||||||
import 'package:flowy_infra_ui/widget/spacing.dart';
|
import 'package:flowy_infra_ui/widget/spacing.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:appflowy/startup/tasks/app_widget.dart';
|
|
||||||
import 'package:flowy_infra/size.dart';
|
|
||||||
import 'package:flowy_infra_ui/style_widget/text_input.dart';
|
|
||||||
import 'package:flowy_infra_ui/widget/dialog/styled_dialogs.dart';
|
|
||||||
export 'package:flowy_infra_ui/widget/dialog/styled_dialogs.dart';
|
export 'package:flowy_infra_ui/widget/dialog/styled_dialogs.dart';
|
||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
|
||||||
|
|
||||||
class NavigatorTextFieldDialog extends StatefulWidget {
|
class NavigatorTextFieldDialog extends StatefulWidget {
|
||||||
const NavigatorTextFieldDialog({
|
const NavigatorTextFieldDialog({
|
||||||
@ -17,17 +18,19 @@ class NavigatorTextFieldDialog extends StatefulWidget {
|
|||||||
required this.title,
|
required this.title,
|
||||||
this.autoSelectAllText = false,
|
this.autoSelectAllText = false,
|
||||||
required this.value,
|
required this.value,
|
||||||
required this.confirm,
|
required this.onConfirm,
|
||||||
this.cancel,
|
this.onCancel,
|
||||||
this.maxLength,
|
this.maxLength,
|
||||||
|
this.hintText,
|
||||||
});
|
});
|
||||||
|
|
||||||
final String value;
|
final String value;
|
||||||
final String title;
|
final String title;
|
||||||
final void Function()? cancel;
|
final VoidCallback? onCancel;
|
||||||
final void Function(String) confirm;
|
final void Function(String, BuildContext) onConfirm;
|
||||||
final bool autoSelectAllText;
|
final bool autoSelectAllText;
|
||||||
final int? maxLength;
|
final int? maxLength;
|
||||||
|
final String? hintText;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<NavigatorTextFieldDialog> createState() =>
|
State<NavigatorTextFieldDialog> createState() =>
|
||||||
@ -69,7 +72,8 @@ class _NavigatorTextFieldDialogState extends State<NavigatorTextFieldDialog> {
|
|||||||
),
|
),
|
||||||
VSpace(Insets.m),
|
VSpace(Insets.m),
|
||||||
FlowyFormTextInput(
|
FlowyFormTextInput(
|
||||||
hintText: LocaleKeys.dialogCreatePageNameHint.tr(),
|
hintText:
|
||||||
|
widget.hintText ?? LocaleKeys.dialogCreatePageNameHint.tr(),
|
||||||
controller: controller,
|
controller: controller,
|
||||||
textStyle: Theme.of(context)
|
textStyle: Theme.of(context)
|
||||||
.textTheme
|
.textTheme
|
||||||
@ -82,20 +86,18 @@ class _NavigatorTextFieldDialogState extends State<NavigatorTextFieldDialog> {
|
|||||||
newValue = text;
|
newValue = text;
|
||||||
},
|
},
|
||||||
onEditingComplete: () {
|
onEditingComplete: () {
|
||||||
widget.confirm(newValue);
|
widget.onConfirm(newValue, context);
|
||||||
AppGlobals.nav.pop();
|
AppGlobals.nav.pop();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
VSpace(Insets.xl),
|
VSpace(Insets.xl),
|
||||||
OkCancelButton(
|
OkCancelButton(
|
||||||
onOkPressed: () {
|
onOkPressed: () {
|
||||||
widget.confirm(newValue);
|
widget.onConfirm(newValue, context);
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
},
|
},
|
||||||
onCancelPressed: () {
|
onCancelPressed: () {
|
||||||
if (widget.cancel != null) {
|
widget.onCancel?.call();
|
||||||
widget.cancel!();
|
|
||||||
}
|
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -111,13 +113,13 @@ class NavigatorAlertDialog extends StatefulWidget {
|
|||||||
required this.title,
|
required this.title,
|
||||||
this.cancel,
|
this.cancel,
|
||||||
this.confirm,
|
this.confirm,
|
||||||
this.hideCancleButton = false,
|
this.hideCancelButton = false,
|
||||||
});
|
});
|
||||||
|
|
||||||
final String title;
|
final String title;
|
||||||
final void Function()? cancel;
|
final void Function()? cancel;
|
||||||
final void Function()? confirm;
|
final void Function()? confirm;
|
||||||
final bool hideCancleButton;
|
final bool hideCancelButton;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<NavigatorAlertDialog> createState() => _CreateFlowyAlertDialog();
|
State<NavigatorAlertDialog> createState() => _CreateFlowyAlertDialog();
|
||||||
@ -158,7 +160,7 @@ class _CreateFlowyAlertDialog extends State<NavigatorAlertDialog> {
|
|||||||
widget.confirm?.call();
|
widget.confirm?.call();
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
},
|
},
|
||||||
onCancelPressed: widget.hideCancleButton
|
onCancelPressed: widget.hideCancelButton
|
||||||
? null
|
? null
|
||||||
: () {
|
: () {
|
||||||
widget.cancel?.call();
|
widget.cancel?.call();
|
||||||
|
@ -219,9 +219,9 @@ class HoverButton extends StatelessWidget {
|
|||||||
super.key,
|
super.key,
|
||||||
required this.onTap,
|
required this.onTap,
|
||||||
required this.itemHeight,
|
required this.itemHeight,
|
||||||
required this.leftIcon,
|
this.leftIcon,
|
||||||
required this.name,
|
required this.name,
|
||||||
required this.rightIcon,
|
this.rightIcon,
|
||||||
});
|
});
|
||||||
|
|
||||||
final VoidCallback onTap;
|
final VoidCallback onTap;
|
||||||
|
@ -29,7 +29,7 @@ class UserAvatar extends StatelessWidget {
|
|||||||
|
|
||||||
if (iconUrl.isEmpty) {
|
if (iconUrl.isEmpty) {
|
||||||
final String nameOrDefault = _userName(name);
|
final String nameOrDefault = _userName(name);
|
||||||
final Color color = ColorGenerator().generateColorFromString(name);
|
final Color color = ColorGenerator.generateColorFromString(name);
|
||||||
const initialsCount = 2;
|
const initialsCount = 2;
|
||||||
|
|
||||||
// Taking the first letters of the name components and limiting to 2 elements
|
// Taking the first letters of the name components and limiting to 2 elements
|
||||||
|
@ -88,7 +88,7 @@ class FlowyButton extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget _render(BuildContext context) {
|
Widget _render(BuildContext context) {
|
||||||
List<Widget> children = List.empty(growable: true);
|
final List<Widget> children = [];
|
||||||
|
|
||||||
if (leftIcon != null) {
|
if (leftIcon != null) {
|
||||||
children.add(
|
children.add(
|
||||||
|
@ -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.
|
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
|
||||||
# Read more about iOS versioning at
|
# Read more about iOS versioning at
|
||||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||||
version: 0.5.0
|
version: 0.5.1
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
flutter: ">=3.19.0"
|
flutter: ">=3.19.0"
|
||||||
|
37
frontend/appflowy_tauri/src-tauri/Cargo.lock
generated
37
frontend/appflowy_tauri/src-tauri/Cargo.lock
generated
@ -162,7 +162,7 @@ checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca"
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "app-error"
|
name = "app-error"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5ed6a149433e34b3dc4bfc66446033a33258e48c#5ed6a149433e34b3dc4bfc66446033a33258e48c"
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=15c03e4f85fffd35089a82c2a84aca8042a38946#15c03e4f85fffd35089a82c2a84aca8042a38946"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bincode",
|
"bincode",
|
||||||
@ -714,7 +714,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "client-api"
|
name = "client-api"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5ed6a149433e34b3dc4bfc66446033a33258e48c#5ed6a149433e34b3dc4bfc66446033a33258e48c"
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=15c03e4f85fffd35089a82c2a84aca8042a38946#15c03e4f85fffd35089a82c2a84aca8042a38946"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"again",
|
"again",
|
||||||
"anyhow",
|
"anyhow",
|
||||||
@ -733,7 +733,6 @@ dependencies = [
|
|||||||
"gotrue",
|
"gotrue",
|
||||||
"gotrue-entity",
|
"gotrue-entity",
|
||||||
"governor",
|
"governor",
|
||||||
"log",
|
|
||||||
"mime",
|
"mime",
|
||||||
"mime_guess",
|
"mime_guess",
|
||||||
"parking_lot 0.12.1",
|
"parking_lot 0.12.1",
|
||||||
@ -818,7 +817,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "collab"
|
name = "collab"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=9f340e85e09af97a83d44b66069a93d63c6f2279#9f340e85e09af97a83d44b66069a93d63c6f2279"
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=7148c6f94bd71469782dfad04aeef835d34900fc#7148c6f94bd71469782dfad04aeef835d34900fc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
@ -840,7 +839,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "collab-database"
|
name = "collab-database"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=9f340e85e09af97a83d44b66069a93d63c6f2279#9f340e85e09af97a83d44b66069a93d63c6f2279"
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=7148c6f94bd71469782dfad04aeef835d34900fc#7148c6f94bd71469782dfad04aeef835d34900fc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
@ -869,7 +868,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "collab-document"
|
name = "collab-document"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=9f340e85e09af97a83d44b66069a93d63c6f2279#9f340e85e09af97a83d44b66069a93d63c6f2279"
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=7148c6f94bd71469782dfad04aeef835d34900fc#7148c6f94bd71469782dfad04aeef835d34900fc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"collab",
|
"collab",
|
||||||
@ -888,7 +887,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "collab-entity"
|
name = "collab-entity"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=9f340e85e09af97a83d44b66069a93d63c6f2279#9f340e85e09af97a83d44b66069a93d63c6f2279"
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=7148c6f94bd71469782dfad04aeef835d34900fc#7148c6f94bd71469782dfad04aeef835d34900fc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bytes",
|
"bytes",
|
||||||
@ -903,7 +902,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "collab-folder"
|
name = "collab-folder"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=9f340e85e09af97a83d44b66069a93d63c6f2279#9f340e85e09af97a83d44b66069a93d63c6f2279"
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=7148c6f94bd71469782dfad04aeef835d34900fc#7148c6f94bd71469782dfad04aeef835d34900fc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"chrono",
|
"chrono",
|
||||||
@ -940,7 +939,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "collab-plugins"
|
name = "collab-plugins"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=9f340e85e09af97a83d44b66069a93d63c6f2279#9f340e85e09af97a83d44b66069a93d63c6f2279"
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=7148c6f94bd71469782dfad04aeef835d34900fc#7148c6f94bd71469782dfad04aeef835d34900fc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-stream",
|
"async-stream",
|
||||||
@ -979,7 +978,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "collab-user"
|
name = "collab-user"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=9f340e85e09af97a83d44b66069a93d63c6f2279#9f340e85e09af97a83d44b66069a93d63c6f2279"
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=7148c6f94bd71469782dfad04aeef835d34900fc#7148c6f94bd71469782dfad04aeef835d34900fc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"collab",
|
"collab",
|
||||||
@ -1313,7 +1312,7 @@ checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308"
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "database-entity"
|
name = "database-entity"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5ed6a149433e34b3dc4bfc66446033a33258e48c#5ed6a149433e34b3dc4bfc66446033a33258e48c"
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=15c03e4f85fffd35089a82c2a84aca8042a38946#15c03e4f85fffd35089a82c2a84aca8042a38946"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"app-error",
|
"app-error",
|
||||||
@ -2587,7 +2586,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "gotrue"
|
name = "gotrue"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5ed6a149433e34b3dc4bfc66446033a33258e48c#5ed6a149433e34b3dc4bfc66446033a33258e48c"
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=15c03e4f85fffd35089a82c2a84aca8042a38946#15c03e4f85fffd35089a82c2a84aca8042a38946"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
@ -2604,7 +2603,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "gotrue-entity"
|
name = "gotrue-entity"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5ed6a149433e34b3dc4bfc66446033a33258e48c#5ed6a149433e34b3dc4bfc66446033a33258e48c"
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=15c03e4f85fffd35089a82c2a84aca8042a38946#15c03e4f85fffd35089a82c2a84aca8042a38946"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"app-error",
|
"app-error",
|
||||||
@ -3059,7 +3058,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "infra"
|
name = "infra"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5ed6a149433e34b3dc4bfc66446033a33258e48c#5ed6a149433e34b3dc4bfc66446033a33258e48c"
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=15c03e4f85fffd35089a82c2a84aca8042a38946#15c03e4f85fffd35089a82c2a84aca8042a38946"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
@ -4790,7 +4789,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "realtime-entity"
|
name = "realtime-entity"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5ed6a149433e34b3dc4bfc66446033a33258e48c#5ed6a149433e34b3dc4bfc66446033a33258e48c"
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=15c03e4f85fffd35089a82c2a84aca8042a38946#15c03e4f85fffd35089a82c2a84aca8042a38946"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bincode",
|
"bincode",
|
||||||
@ -4814,7 +4813,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "realtime-protocol"
|
name = "realtime-protocol"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5ed6a149433e34b3dc4bfc66446033a33258e48c#5ed6a149433e34b3dc4bfc66446033a33258e48c"
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=15c03e4f85fffd35089a82c2a84aca8042a38946#15c03e4f85fffd35089a82c2a84aca8042a38946"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bincode",
|
"bincode",
|
||||||
@ -5462,7 +5461,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "shared-entity"
|
name = "shared-entity"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5ed6a149433e34b3dc4bfc66446033a33258e48c#5ed6a149433e34b3dc4bfc66446033a33258e48c"
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=15c03e4f85fffd35089a82c2a84aca8042a38946#15c03e4f85fffd35089a82c2a84aca8042a38946"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"app-error",
|
"app-error",
|
||||||
@ -6957,7 +6956,7 @@ checksum = "14247bb57be4f377dfb94c72830b8ce8fc6beac03cf4bf7b9732eadd414123fc"
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "websocket"
|
name = "websocket"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5ed6a149433e34b3dc4bfc66446033a33258e48c#5ed6a149433e34b3dc4bfc66446033a33258e48c"
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=15c03e4f85fffd35089a82c2a84aca8042a38946#15c03e4f85fffd35089a82c2a84aca8042a38946"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures-channel",
|
"futures-channel",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
@ -7376,7 +7375,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "workspace-template"
|
name = "workspace-template"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5ed6a149433e34b3dc4bfc66446033a33258e48c#5ed6a149433e34b3dc4bfc66446033a33258e48c"
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=15c03e4f85fffd35089a82c2a84aca8042a38946#15c03e4f85fffd35089a82c2a84aca8042a38946"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
|
@ -82,7 +82,7 @@ custom-protocol = ["tauri/custom-protocol"]
|
|||||||
# Run the script:
|
# Run the script:
|
||||||
# scripts/tool/update_client_api_rev.sh new_rev_id
|
# scripts/tool/update_client_api_rev.sh new_rev_id
|
||||||
# ⚠️⚠️⚠️️
|
# ⚠️⚠️⚠️️
|
||||||
client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "5ed6a149433e34b3dc4bfc66446033a33258e48c" }
|
client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "15c03e4f85fffd35089a82c2a84aca8042a38946" }
|
||||||
# Please use the following script to update collab.
|
# Please use the following script to update collab.
|
||||||
# Working directory: frontend
|
# Working directory: frontend
|
||||||
#
|
#
|
||||||
@ -92,10 +92,10 @@ client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "5ed
|
|||||||
# To switch to the local path, run:
|
# To switch to the local path, run:
|
||||||
# scripts/tool/update_collab_source.sh
|
# scripts/tool/update_collab_source.sh
|
||||||
# ⚠️⚠️⚠️️
|
# ⚠️⚠️⚠️️
|
||||||
collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "9f340e85e09af97a83d44b66069a93d63c6f2279" }
|
collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "7148c6f94bd71469782dfad04aeef835d34900fc" }
|
||||||
collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "9f340e85e09af97a83d44b66069a93d63c6f2279" }
|
collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "7148c6f94bd71469782dfad04aeef835d34900fc" }
|
||||||
collab-document = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "9f340e85e09af97a83d44b66069a93d63c6f2279" }
|
collab-document = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "7148c6f94bd71469782dfad04aeef835d34900fc" }
|
||||||
collab-database = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "9f340e85e09af97a83d44b66069a93d63c6f2279" }
|
collab-database = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "7148c6f94bd71469782dfad04aeef835d34900fc" }
|
||||||
collab-plugins = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "9f340e85e09af97a83d44b66069a93d63c6f2279" }
|
collab-plugins = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "7148c6f94bd71469782dfad04aeef835d34900fc" }
|
||||||
collab-user = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "9f340e85e09af97a83d44b66069a93d63c6f2279" }
|
collab-user = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "7148c6f94bd71469782dfad04aeef835d34900fc" }
|
||||||
collab-entity = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "9f340e85e09af97a83d44b66069a93d63c6f2279" }
|
collab-entity = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "7148c6f94bd71469782dfad04aeef835d34900fc" }
|
||||||
|
@ -20,9 +20,9 @@ function GridTableOverlay({
|
|||||||
const [openConfirm, setOpenConfirm] = useState(false);
|
const [openConfirm, setOpenConfirm] = useState(false);
|
||||||
const [confirmModalProps, setConfirmModalProps] = useState<
|
const [confirmModalProps, setConfirmModalProps] = useState<
|
||||||
| {
|
| {
|
||||||
onOk: () => Promise<void>;
|
onOk: () => Promise<void>;
|
||||||
onCancel: () => void;
|
onCancel: () => void;
|
||||||
}
|
}
|
||||||
| undefined
|
| undefined
|
||||||
>(undefined);
|
>(undefined);
|
||||||
|
|
||||||
@ -59,7 +59,7 @@ function GridTableOverlay({
|
|||||||
{openConfirm && (
|
{openConfirm && (
|
||||||
<DeleteConfirmDialog
|
<DeleteConfirmDialog
|
||||||
open={openConfirm}
|
open={openConfirm}
|
||||||
title={t('grid.removeSorting')}
|
title={t('grid.sort.removeSorting')}
|
||||||
okText={t('button.remove')}
|
okText={t('button.remove')}
|
||||||
cancelText={t('button.dontRemove')}
|
cancelText={t('button.dontRemove')}
|
||||||
onClose={() => {
|
onClose={() => {
|
||||||
|
35
frontend/appflowy_web/wasm-libs/Cargo.lock
generated
35
frontend/appflowy_web/wasm-libs/Cargo.lock
generated
@ -221,7 +221,7 @@ checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca"
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "app-error"
|
name = "app-error"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5ed6a149433e34b3dc4bfc66446033a33258e48c#5ed6a149433e34b3dc4bfc66446033a33258e48c"
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=15c03e4f85fffd35089a82c2a84aca8042a38946#15c03e4f85fffd35089a82c2a84aca8042a38946"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bincode",
|
"bincode",
|
||||||
@ -545,7 +545,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "client-api"
|
name = "client-api"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5ed6a149433e34b3dc4bfc66446033a33258e48c#5ed6a149433e34b3dc4bfc66446033a33258e48c"
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=15c03e4f85fffd35089a82c2a84aca8042a38946#15c03e4f85fffd35089a82c2a84aca8042a38946"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"again",
|
"again",
|
||||||
"anyhow",
|
"anyhow",
|
||||||
@ -564,7 +564,6 @@ dependencies = [
|
|||||||
"gotrue",
|
"gotrue",
|
||||||
"gotrue-entity",
|
"gotrue-entity",
|
||||||
"governor",
|
"governor",
|
||||||
"log",
|
|
||||||
"mime",
|
"mime",
|
||||||
"mime_guess",
|
"mime_guess",
|
||||||
"parking_lot 0.12.1",
|
"parking_lot 0.12.1",
|
||||||
@ -618,7 +617,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "collab"
|
name = "collab"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=9f340e85e09af97a83d44b66069a93d63c6f2279#9f340e85e09af97a83d44b66069a93d63c6f2279"
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=7148c6f94bd71469782dfad04aeef835d34900fc#7148c6f94bd71469782dfad04aeef835d34900fc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
@ -640,7 +639,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "collab-document"
|
name = "collab-document"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=9f340e85e09af97a83d44b66069a93d63c6f2279#9f340e85e09af97a83d44b66069a93d63c6f2279"
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=7148c6f94bd71469782dfad04aeef835d34900fc#7148c6f94bd71469782dfad04aeef835d34900fc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"collab",
|
"collab",
|
||||||
@ -659,7 +658,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "collab-entity"
|
name = "collab-entity"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=9f340e85e09af97a83d44b66069a93d63c6f2279#9f340e85e09af97a83d44b66069a93d63c6f2279"
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=7148c6f94bd71469782dfad04aeef835d34900fc#7148c6f94bd71469782dfad04aeef835d34900fc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bytes",
|
"bytes",
|
||||||
@ -674,7 +673,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "collab-folder"
|
name = "collab-folder"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=9f340e85e09af97a83d44b66069a93d63c6f2279#9f340e85e09af97a83d44b66069a93d63c6f2279"
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=7148c6f94bd71469782dfad04aeef835d34900fc#7148c6f94bd71469782dfad04aeef835d34900fc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"chrono",
|
"chrono",
|
||||||
@ -711,7 +710,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "collab-plugins"
|
name = "collab-plugins"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=9f340e85e09af97a83d44b66069a93d63c6f2279#9f340e85e09af97a83d44b66069a93d63c6f2279"
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=7148c6f94bd71469782dfad04aeef835d34900fc#7148c6f94bd71469782dfad04aeef835d34900fc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-stream",
|
"async-stream",
|
||||||
@ -749,7 +748,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "collab-user"
|
name = "collab-user"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=9f340e85e09af97a83d44b66069a93d63c6f2279#9f340e85e09af97a83d44b66069a93d63c6f2279"
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=7148c6f94bd71469782dfad04aeef835d34900fc#7148c6f94bd71469782dfad04aeef835d34900fc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"collab",
|
"collab",
|
||||||
@ -946,7 +945,7 @@ checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5"
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "database-entity"
|
name = "database-entity"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5ed6a149433e34b3dc4bfc66446033a33258e48c#5ed6a149433e34b3dc4bfc66446033a33258e48c"
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=15c03e4f85fffd35089a82c2a84aca8042a38946#15c03e4f85fffd35089a82c2a84aca8042a38946"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"app-error",
|
"app-error",
|
||||||
@ -1700,7 +1699,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "gotrue"
|
name = "gotrue"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5ed6a149433e34b3dc4bfc66446033a33258e48c#5ed6a149433e34b3dc4bfc66446033a33258e48c"
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=15c03e4f85fffd35089a82c2a84aca8042a38946#15c03e4f85fffd35089a82c2a84aca8042a38946"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
@ -1717,7 +1716,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "gotrue-entity"
|
name = "gotrue-entity"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5ed6a149433e34b3dc4bfc66446033a33258e48c#5ed6a149433e34b3dc4bfc66446033a33258e48c"
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=15c03e4f85fffd35089a82c2a84aca8042a38946#15c03e4f85fffd35089a82c2a84aca8042a38946"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"app-error",
|
"app-error",
|
||||||
@ -2051,7 +2050,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "infra"
|
name = "infra"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5ed6a149433e34b3dc4bfc66446033a33258e48c#5ed6a149433e34b3dc4bfc66446033a33258e48c"
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=15c03e4f85fffd35089a82c2a84aca8042a38946#15c03e4f85fffd35089a82c2a84aca8042a38946"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
@ -3309,7 +3308,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "realtime-entity"
|
name = "realtime-entity"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5ed6a149433e34b3dc4bfc66446033a33258e48c#5ed6a149433e34b3dc4bfc66446033a33258e48c"
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=15c03e4f85fffd35089a82c2a84aca8042a38946#15c03e4f85fffd35089a82c2a84aca8042a38946"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bincode",
|
"bincode",
|
||||||
@ -3333,7 +3332,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "realtime-protocol"
|
name = "realtime-protocol"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5ed6a149433e34b3dc4bfc66446033a33258e48c#5ed6a149433e34b3dc4bfc66446033a33258e48c"
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=15c03e4f85fffd35089a82c2a84aca8042a38946#15c03e4f85fffd35089a82c2a84aca8042a38946"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bincode",
|
"bincode",
|
||||||
@ -3780,7 +3779,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "shared-entity"
|
name = "shared-entity"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5ed6a149433e34b3dc4bfc66446033a33258e48c#5ed6a149433e34b3dc4bfc66446033a33258e48c"
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=15c03e4f85fffd35089a82c2a84aca8042a38946#15c03e4f85fffd35089a82c2a84aca8042a38946"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"app-error",
|
"app-error",
|
||||||
@ -4722,7 +4721,7 @@ checksum = "1778a42e8b3b90bff8d0f5032bf22250792889a5cdc752aa0020c84abe3aaf10"
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "websocket"
|
name = "websocket"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5ed6a149433e34b3dc4bfc66446033a33258e48c#5ed6a149433e34b3dc4bfc66446033a33258e48c"
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=15c03e4f85fffd35089a82c2a84aca8042a38946#15c03e4f85fffd35089a82c2a84aca8042a38946"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures-channel",
|
"futures-channel",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
@ -5029,4 +5028,4 @@ dependencies = [
|
|||||||
[[patch.unused]]
|
[[patch.unused]]
|
||||||
name = "collab-database"
|
name = "collab-database"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=9f340e85e09af97a83d44b66069a93d63c6f2279#9f340e85e09af97a83d44b66069a93d63c6f2279"
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=7148c6f94bd71469782dfad04aeef835d34900fc#7148c6f94bd71469782dfad04aeef835d34900fc"
|
||||||
|
@ -55,7 +55,7 @@ codegen-units = 1
|
|||||||
# Run the script:
|
# Run the script:
|
||||||
# scripts/tool/update_client_api_rev.sh new_rev_id
|
# scripts/tool/update_client_api_rev.sh new_rev_id
|
||||||
# ⚠️⚠️⚠️️
|
# ⚠️⚠️⚠️️
|
||||||
client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "5ed6a149433e34b3dc4bfc66446033a33258e48c" }
|
client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "15c03e4f85fffd35089a82c2a84aca8042a38946" }
|
||||||
# Please use the following script to update collab.
|
# Please use the following script to update collab.
|
||||||
# Working directory: frontend
|
# Working directory: frontend
|
||||||
#
|
#
|
||||||
@ -65,10 +65,10 @@ client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "5ed
|
|||||||
# To switch to the local path, run:
|
# To switch to the local path, run:
|
||||||
# scripts/tool/update_collab_source.sh
|
# scripts/tool/update_collab_source.sh
|
||||||
# ⚠️⚠️⚠️️
|
# ⚠️⚠️⚠️️
|
||||||
collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "9f340e85e09af97a83d44b66069a93d63c6f2279" }
|
collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "7148c6f94bd71469782dfad04aeef835d34900fc" }
|
||||||
collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "9f340e85e09af97a83d44b66069a93d63c6f2279" }
|
collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "7148c6f94bd71469782dfad04aeef835d34900fc" }
|
||||||
collab-document = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "9f340e85e09af97a83d44b66069a93d63c6f2279" }
|
collab-document = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "7148c6f94bd71469782dfad04aeef835d34900fc" }
|
||||||
collab-database = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "9f340e85e09af97a83d44b66069a93d63c6f2279" }
|
collab-database = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "7148c6f94bd71469782dfad04aeef835d34900fc" }
|
||||||
collab-plugins = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "9f340e85e09af97a83d44b66069a93d63c6f2279" }
|
collab-plugins = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "7148c6f94bd71469782dfad04aeef835d34900fc" }
|
||||||
collab-user = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "9f340e85e09af97a83d44b66069a93d63c6f2279" }
|
collab-user = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "7148c6f94bd71469782dfad04aeef835d34900fc" }
|
||||||
collab-entity = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "9f340e85e09af97a83d44b66069a93d63c6f2279" }
|
collab-entity = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "7148c6f94bd71469782dfad04aeef835d34900fc" }
|
||||||
|
@ -193,7 +193,7 @@
|
|||||||
"editContact": "እውቂያ ያርትዑ"
|
"editContact": "እውቂያ ያርትዑ"
|
||||||
},
|
},
|
||||||
"button": {
|
"button": {
|
||||||
"OK": "እሺ",
|
"ok": "እሺ",
|
||||||
"cancel": "ይቅር",
|
"cancel": "ይቅር",
|
||||||
"signIn": "ይግቡ",
|
"signIn": "ይግቡ",
|
||||||
"signOut": "ዘግተው ውጣ",
|
"signOut": "ዘግተው ውጣ",
|
||||||
|
@ -64,7 +64,14 @@
|
|||||||
"reportIssueOnGithub": "Report an issue on Github",
|
"reportIssueOnGithub": "Report an issue on Github",
|
||||||
"exportLogFiles": "Export log files",
|
"exportLogFiles": "Export log files",
|
||||||
"reachOut": "Reach out on Discord"
|
"reachOut": "Reach out on Discord"
|
||||||
}
|
},
|
||||||
|
"deleteWorkspaceHintText": "Are you sure you want to delete the workspace? This action cannot be undone.",
|
||||||
|
"createSuccess": "Workspace created successfully",
|
||||||
|
"createFailed": "Failed to create workspace",
|
||||||
|
"deleteSuccess": "Workspace deleted successfully",
|
||||||
|
"deleteFailed": "Failed to delete workspace",
|
||||||
|
"openSuccess": "Open workspace successfully",
|
||||||
|
"openFailed": "Failed to open workspace"
|
||||||
},
|
},
|
||||||
"shareAction": {
|
"shareAction": {
|
||||||
"buttonText": "Share",
|
"buttonText": "Share",
|
||||||
@ -242,8 +249,6 @@
|
|||||||
"helpCenter": "Help Center",
|
"helpCenter": "Help Center",
|
||||||
"add": "Add",
|
"add": "Add",
|
||||||
"yes": "Yes",
|
"yes": "Yes",
|
||||||
"Done": "Done",
|
|
||||||
"Cancel": "Cancel",
|
|
||||||
"clear": "Clear",
|
"clear": "Clear",
|
||||||
"remove": "Remove",
|
"remove": "Remove",
|
||||||
"dontRemove": "Don't remove",
|
"dontRemove": "Don't remove",
|
||||||
@ -414,7 +419,8 @@
|
|||||||
"memberHintText": "A member can read, comment, and edit pages. Invite members and guests.",
|
"memberHintText": "A member can read, comment, and edit pages. Invite members and guests.",
|
||||||
"guestHintText": "A Guest can read, react, comment, and can edit certain pages with permission.",
|
"guestHintText": "A Guest can read, react, comment, and can edit certain pages with permission.",
|
||||||
"emailInvalidError": "Invalid email, please check and try again",
|
"emailInvalidError": "Invalid email, please check and try again",
|
||||||
"emailSent": "Email sent, please check the inbox"
|
"emailSent": "Email sent, please check the inbox",
|
||||||
|
"members": "members"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"files": {
|
"files": {
|
||||||
@ -451,7 +457,11 @@
|
|||||||
"recoverLocationTooltips": "Reset to AppFlowy's default data directory",
|
"recoverLocationTooltips": "Reset to AppFlowy's default data directory",
|
||||||
"exportFileSuccess": "Export file successfully!",
|
"exportFileSuccess": "Export file successfully!",
|
||||||
"exportFileFail": "Export file failed!",
|
"exportFileFail": "Export file failed!",
|
||||||
"export": "Export"
|
"export": "Export",
|
||||||
|
"clearCache": "Clear cache",
|
||||||
|
"clearCacheDesc": "Clear the cache including the images, fonts, and other temporary files. This will not delete your data.",
|
||||||
|
"areYouSureToClearCache": "Are you sure to clear the cache?",
|
||||||
|
"clearCacheSuccess": "Cache cleared successfully!"
|
||||||
},
|
},
|
||||||
"user": {
|
"user": {
|
||||||
"name": "Name",
|
"name": "Name",
|
||||||
@ -664,7 +674,8 @@
|
|||||||
"empty": "No active sorts",
|
"empty": "No active sorts",
|
||||||
"cannotFindCreatableField": "Cannot find a suitable field to sort by",
|
"cannotFindCreatableField": "Cannot find a suitable field to sort by",
|
||||||
"deleteAllSorts": "Delete all sorts",
|
"deleteAllSorts": "Delete all sorts",
|
||||||
"addSort": "Add new sort"
|
"addSort": "Add new sort",
|
||||||
|
"removeSorting": "Would you like to remove sorting?"
|
||||||
},
|
},
|
||||||
"row": {
|
"row": {
|
||||||
"duplicate": "Duplicate",
|
"duplicate": "Duplicate",
|
||||||
@ -725,8 +736,7 @@
|
|||||||
"median": "Median",
|
"median": "Median",
|
||||||
"min": "Min",
|
"min": "Min",
|
||||||
"sum": "Sum"
|
"sum": "Sum"
|
||||||
},
|
}
|
||||||
"removeSorting": "Would you like to remove sorting?"
|
|
||||||
},
|
},
|
||||||
"document": {
|
"document": {
|
||||||
"menuName": "Document",
|
"menuName": "Document",
|
||||||
|
@ -238,8 +238,6 @@
|
|||||||
"helpCenter": "Centro assistenza",
|
"helpCenter": "Centro assistenza",
|
||||||
"add": "Aggiungi",
|
"add": "Aggiungi",
|
||||||
"yes": "SÌ",
|
"yes": "SÌ",
|
||||||
"Done": "Fatto",
|
|
||||||
"Cancel": "Annulla",
|
|
||||||
"remove": "Rimuovi",
|
"remove": "Rimuovi",
|
||||||
"dontRemove": "Non rimuovere"
|
"dontRemove": "Non rimuovere"
|
||||||
},
|
},
|
||||||
@ -621,7 +619,8 @@
|
|||||||
"cannotFindCreatableField": "Impossibile trovare un campo adatto per l'ordinamento",
|
"cannotFindCreatableField": "Impossibile trovare un campo adatto per l'ordinamento",
|
||||||
"deleteAllSorts": "Elimina tutti gli ordinamenti",
|
"deleteAllSorts": "Elimina tutti gli ordinamenti",
|
||||||
"addSort": "Aggiungi ordinamento",
|
"addSort": "Aggiungi ordinamento",
|
||||||
"deleteSort": "Elimina ordinamento"
|
"deleteSort": "Elimina ordinamento",
|
||||||
|
"removeSorting": "Si desidera rimuovere l'ordinamento?"
|
||||||
},
|
},
|
||||||
"row": {
|
"row": {
|
||||||
"duplicate": "Duplicare",
|
"duplicate": "Duplicare",
|
||||||
@ -675,8 +674,7 @@
|
|||||||
"median": "Medio",
|
"median": "Medio",
|
||||||
"min": "Minimo",
|
"min": "Minimo",
|
||||||
"sum": "Somma"
|
"sum": "Somma"
|
||||||
},
|
}
|
||||||
"removeSorting": "Si desidera rimuovere l'ordinamento?"
|
|
||||||
},
|
},
|
||||||
"document": {
|
"document": {
|
||||||
"menuName": "Documento",
|
"menuName": "Documento",
|
||||||
|
@ -242,8 +242,6 @@
|
|||||||
"helpCenter": "Центр помощи",
|
"helpCenter": "Центр помощи",
|
||||||
"add": "Добавить",
|
"add": "Добавить",
|
||||||
"yes": "Да",
|
"yes": "Да",
|
||||||
"Done": "Готово",
|
|
||||||
"Cancel": "Отмена",
|
|
||||||
"clear": "Очистить",
|
"clear": "Очистить",
|
||||||
"remove": "Удалить",
|
"remove": "Удалить",
|
||||||
"dontRemove": "Не удалять",
|
"dontRemove": "Не удалять",
|
||||||
@ -645,7 +643,8 @@
|
|||||||
"empty": "Нет активных сортировок",
|
"empty": "Нет активных сортировок",
|
||||||
"cannotFindCreatableField": "Не могу найти подходящее поле для сортировки",
|
"cannotFindCreatableField": "Не могу найти подходящее поле для сортировки",
|
||||||
"deleteAllSorts": "Удалить все сортировки",
|
"deleteAllSorts": "Удалить все сортировки",
|
||||||
"addSort": "Добавить сортировку"
|
"addSort": "Добавить сортировку",
|
||||||
|
"removeSorting": "Убрать сортировку?"
|
||||||
},
|
},
|
||||||
"row": {
|
"row": {
|
||||||
"duplicate": "Дублировать",
|
"duplicate": "Дублировать",
|
||||||
@ -706,8 +705,7 @@
|
|||||||
"median": "Медиана",
|
"median": "Медиана",
|
||||||
"min": "Минимум",
|
"min": "Минимум",
|
||||||
"sum": "Сумма"
|
"sum": "Сумма"
|
||||||
},
|
}
|
||||||
"removeSorting": "Убрать сортировку?"
|
|
||||||
},
|
},
|
||||||
"document": {
|
"document": {
|
||||||
"menuName": "Документ",
|
"menuName": "Документ",
|
||||||
|
@ -242,8 +242,6 @@
|
|||||||
"helpCenter": "帮助中心",
|
"helpCenter": "帮助中心",
|
||||||
"add": "添加",
|
"add": "添加",
|
||||||
"yes": "是",
|
"yes": "是",
|
||||||
"Done": "完成",
|
|
||||||
"Cancel": "取消",
|
|
||||||
"clear": "清空",
|
"clear": "清空",
|
||||||
"remove": "删除",
|
"remove": "删除",
|
||||||
"dontRemove": "请勿删除",
|
"dontRemove": "请勿删除",
|
||||||
@ -646,7 +644,8 @@
|
|||||||
"descending": "降序",
|
"descending": "降序",
|
||||||
"deleteAllSorts": "删除所有排序",
|
"deleteAllSorts": "删除所有排序",
|
||||||
"addSort": "添加排序",
|
"addSort": "添加排序",
|
||||||
"deleteSort": "取消排序"
|
"deleteSort": "取消排序",
|
||||||
|
"removeSorting": "你确定要移除排序吗?"
|
||||||
},
|
},
|
||||||
"row": {
|
"row": {
|
||||||
"duplicate": "复制",
|
"duplicate": "复制",
|
||||||
@ -705,8 +704,7 @@
|
|||||||
"median": "中位数",
|
"median": "中位数",
|
||||||
"min": "最小值",
|
"min": "最小值",
|
||||||
"sum": "求和"
|
"sum": "求和"
|
||||||
},
|
}
|
||||||
"removeSorting": "你确定要移除排序吗?"
|
|
||||||
},
|
},
|
||||||
"document": {
|
"document": {
|
||||||
"menuName": "文档",
|
"menuName": "文档",
|
||||||
|
37
frontend/rust-lib/Cargo.lock
generated
37
frontend/rust-lib/Cargo.lock
generated
@ -163,7 +163,7 @@ checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca"
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "app-error"
|
name = "app-error"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5ed6a149433e34b3dc4bfc66446033a33258e48c#5ed6a149433e34b3dc4bfc66446033a33258e48c"
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=15c03e4f85fffd35089a82c2a84aca8042a38946#15c03e4f85fffd35089a82c2a84aca8042a38946"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bincode",
|
"bincode",
|
||||||
@ -673,7 +673,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "client-api"
|
name = "client-api"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5ed6a149433e34b3dc4bfc66446033a33258e48c#5ed6a149433e34b3dc4bfc66446033a33258e48c"
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=15c03e4f85fffd35089a82c2a84aca8042a38946#15c03e4f85fffd35089a82c2a84aca8042a38946"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"again",
|
"again",
|
||||||
"anyhow",
|
"anyhow",
|
||||||
@ -692,7 +692,6 @@ dependencies = [
|
|||||||
"gotrue",
|
"gotrue",
|
||||||
"gotrue-entity",
|
"gotrue-entity",
|
||||||
"governor",
|
"governor",
|
||||||
"log",
|
|
||||||
"mime",
|
"mime",
|
||||||
"mime_guess",
|
"mime_guess",
|
||||||
"parking_lot 0.12.1",
|
"parking_lot 0.12.1",
|
||||||
@ -746,7 +745,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "collab"
|
name = "collab"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=9f340e85e09af97a83d44b66069a93d63c6f2279#9f340e85e09af97a83d44b66069a93d63c6f2279"
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=7148c6f94bd71469782dfad04aeef835d34900fc#7148c6f94bd71469782dfad04aeef835d34900fc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
@ -768,7 +767,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "collab-database"
|
name = "collab-database"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=9f340e85e09af97a83d44b66069a93d63c6f2279#9f340e85e09af97a83d44b66069a93d63c6f2279"
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=7148c6f94bd71469782dfad04aeef835d34900fc#7148c6f94bd71469782dfad04aeef835d34900fc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
@ -797,7 +796,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "collab-document"
|
name = "collab-document"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=9f340e85e09af97a83d44b66069a93d63c6f2279#9f340e85e09af97a83d44b66069a93d63c6f2279"
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=7148c6f94bd71469782dfad04aeef835d34900fc#7148c6f94bd71469782dfad04aeef835d34900fc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"collab",
|
"collab",
|
||||||
@ -816,7 +815,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "collab-entity"
|
name = "collab-entity"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=9f340e85e09af97a83d44b66069a93d63c6f2279#9f340e85e09af97a83d44b66069a93d63c6f2279"
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=7148c6f94bd71469782dfad04aeef835d34900fc#7148c6f94bd71469782dfad04aeef835d34900fc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bytes",
|
"bytes",
|
||||||
@ -831,7 +830,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "collab-folder"
|
name = "collab-folder"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=9f340e85e09af97a83d44b66069a93d63c6f2279#9f340e85e09af97a83d44b66069a93d63c6f2279"
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=7148c6f94bd71469782dfad04aeef835d34900fc#7148c6f94bd71469782dfad04aeef835d34900fc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"chrono",
|
"chrono",
|
||||||
@ -868,7 +867,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "collab-plugins"
|
name = "collab-plugins"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=9f340e85e09af97a83d44b66069a93d63c6f2279#9f340e85e09af97a83d44b66069a93d63c6f2279"
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=7148c6f94bd71469782dfad04aeef835d34900fc#7148c6f94bd71469782dfad04aeef835d34900fc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-stream",
|
"async-stream",
|
||||||
@ -907,7 +906,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "collab-user"
|
name = "collab-user"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=9f340e85e09af97a83d44b66069a93d63c6f2279#9f340e85e09af97a83d44b66069a93d63c6f2279"
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=7148c6f94bd71469782dfad04aeef835d34900fc#7148c6f94bd71469782dfad04aeef835d34900fc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"collab",
|
"collab",
|
||||||
@ -1237,7 +1236,7 @@ checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308"
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "database-entity"
|
name = "database-entity"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5ed6a149433e34b3dc4bfc66446033a33258e48c#5ed6a149433e34b3dc4bfc66446033a33258e48c"
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=15c03e4f85fffd35089a82c2a84aca8042a38946#15c03e4f85fffd35089a82c2a84aca8042a38946"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"app-error",
|
"app-error",
|
||||||
@ -2411,7 +2410,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "gotrue"
|
name = "gotrue"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5ed6a149433e34b3dc4bfc66446033a33258e48c#5ed6a149433e34b3dc4bfc66446033a33258e48c"
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=15c03e4f85fffd35089a82c2a84aca8042a38946#15c03e4f85fffd35089a82c2a84aca8042a38946"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
@ -2428,7 +2427,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "gotrue-entity"
|
name = "gotrue-entity"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5ed6a149433e34b3dc4bfc66446033a33258e48c#5ed6a149433e34b3dc4bfc66446033a33258e48c"
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=15c03e4f85fffd35089a82c2a84aca8042a38946#15c03e4f85fffd35089a82c2a84aca8042a38946"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"app-error",
|
"app-error",
|
||||||
@ -2822,7 +2821,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "infra"
|
name = "infra"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5ed6a149433e34b3dc4bfc66446033a33258e48c#5ed6a149433e34b3dc4bfc66446033a33258e48c"
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=15c03e4f85fffd35089a82c2a84aca8042a38946#15c03e4f85fffd35089a82c2a84aca8042a38946"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
@ -4319,7 +4318,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "realtime-entity"
|
name = "realtime-entity"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5ed6a149433e34b3dc4bfc66446033a33258e48c#5ed6a149433e34b3dc4bfc66446033a33258e48c"
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=15c03e4f85fffd35089a82c2a84aca8042a38946#15c03e4f85fffd35089a82c2a84aca8042a38946"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bincode",
|
"bincode",
|
||||||
@ -4343,7 +4342,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "realtime-protocol"
|
name = "realtime-protocol"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5ed6a149433e34b3dc4bfc66446033a33258e48c#5ed6a149433e34b3dc4bfc66446033a33258e48c"
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=15c03e4f85fffd35089a82c2a84aca8042a38946#15c03e4f85fffd35089a82c2a84aca8042a38946"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bincode",
|
"bincode",
|
||||||
@ -4931,7 +4930,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "shared-entity"
|
name = "shared-entity"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5ed6a149433e34b3dc4bfc66446033a33258e48c#5ed6a149433e34b3dc4bfc66446033a33258e48c"
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=15c03e4f85fffd35089a82c2a84aca8042a38946#15c03e4f85fffd35089a82c2a84aca8042a38946"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"app-error",
|
"app-error",
|
||||||
@ -6121,7 +6120,7 @@ checksum = "14247bb57be4f377dfb94c72830b8ce8fc6beac03cf4bf7b9732eadd414123fc"
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "websocket"
|
name = "websocket"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5ed6a149433e34b3dc4bfc66446033a33258e48c#5ed6a149433e34b3dc4bfc66446033a33258e48c"
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=15c03e4f85fffd35089a82c2a84aca8042a38946#15c03e4f85fffd35089a82c2a84aca8042a38946"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures-channel",
|
"futures-channel",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
@ -6361,7 +6360,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "workspace-template"
|
name = "workspace-template"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=5ed6a149433e34b3dc4bfc66446033a33258e48c#5ed6a149433e34b3dc4bfc66446033a33258e48c"
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=15c03e4f85fffd35089a82c2a84aca8042a38946#15c03e4f85fffd35089a82c2a84aca8042a38946"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
|
@ -105,7 +105,7 @@ incremental = false
|
|||||||
# Run the script:
|
# Run the script:
|
||||||
# scripts/tool/update_client_api_rev.sh new_rev_id
|
# scripts/tool/update_client_api_rev.sh new_rev_id
|
||||||
# ⚠️⚠️⚠️️
|
# ⚠️⚠️⚠️️
|
||||||
client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "5ed6a149433e34b3dc4bfc66446033a33258e48c" }
|
client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "15c03e4f85fffd35089a82c2a84aca8042a38946" }
|
||||||
# Please use the following script to update collab.
|
# Please use the following script to update collab.
|
||||||
# Working directory: frontend
|
# Working directory: frontend
|
||||||
#
|
#
|
||||||
@ -115,10 +115,10 @@ client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "5ed
|
|||||||
# To switch to the local path, run:
|
# To switch to the local path, run:
|
||||||
# scripts/tool/update_collab_source.sh
|
# scripts/tool/update_collab_source.sh
|
||||||
# ⚠️⚠️⚠️️
|
# ⚠️⚠️⚠️️
|
||||||
collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "9f340e85e09af97a83d44b66069a93d63c6f2279" }
|
collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "7148c6f94bd71469782dfad04aeef835d34900fc" }
|
||||||
collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "9f340e85e09af97a83d44b66069a93d63c6f2279" }
|
collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "7148c6f94bd71469782dfad04aeef835d34900fc" }
|
||||||
collab-document = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "9f340e85e09af97a83d44b66069a93d63c6f2279" }
|
collab-document = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "7148c6f94bd71469782dfad04aeef835d34900fc" }
|
||||||
collab-database = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "9f340e85e09af97a83d44b66069a93d63c6f2279" }
|
collab-database = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "7148c6f94bd71469782dfad04aeef835d34900fc" }
|
||||||
collab-plugins = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "9f340e85e09af97a83d44b66069a93d63c6f2279" }
|
collab-plugins = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "7148c6f94bd71469782dfad04aeef835d34900fc" }
|
||||||
collab-user = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "9f340e85e09af97a83d44b66069a93d63c6f2279" }
|
collab-user = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "7148c6f94bd71469782dfad04aeef835d34900fc" }
|
||||||
collab-entity = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "9f340e85e09af97a83d44b66069a93d63c6f2279" }
|
collab-entity = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "7148c6f94bd71469782dfad04aeef835d34900fc" }
|
||||||
|
@ -176,7 +176,6 @@ async fn post_to_flutter(response: AFPluginEventResponse, port: i64) {
|
|||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn rust_log(level: i64, data: *const c_char) {
|
pub extern "C" fn rust_log(level: i64, data: *const c_char) {
|
||||||
info!("backend_log");
|
|
||||||
// Check if the data pointer is not null
|
// Check if the data pointer is not null
|
||||||
if data.is_null() {
|
if data.is_null() {
|
||||||
error!("[flutter error]: null pointer provided to backend_log");
|
error!("[flutter error]: null pointer provided to backend_log");
|
||||||
|
@ -2,7 +2,7 @@ use flowy_storage::{ObjectIdentity, ObjectStorageService};
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use anyhow::Error;
|
use anyhow::Error;
|
||||||
use client_api::collab_sync::{SinkConfig, SinkStrategy, SyncObject, SyncPlugin};
|
use client_api::collab_sync::{SinkConfig, SyncObject, SyncPlugin};
|
||||||
use collab::core::collab::CollabDocState;
|
use collab::core::collab::CollabDocState;
|
||||||
use collab::core::origin::{CollabClient, CollabOrigin};
|
use collab::core::origin::{CollabClient, CollabOrigin};
|
||||||
use collab::preclude::CollabPlugin;
|
use collab::preclude::CollabPlugin;
|
||||||
@ -359,8 +359,7 @@ impl CollabCloudPluginProvider for ServerProvider {
|
|||||||
let (sink, stream) = (channel.sink(), channel.stream());
|
let (sink, stream) = (channel.sink(), channel.stream());
|
||||||
let sink_config = SinkConfig::new()
|
let sink_config = SinkConfig::new()
|
||||||
.send_timeout(8)
|
.send_timeout(8)
|
||||||
.with_max_payload_size(1024 * 10)
|
.with_max_payload_size(1024 * 10);
|
||||||
.with_strategy(sink_strategy_from_object(&sync_object));
|
|
||||||
let sync_plugin = SyncPlugin::new(
|
let sync_plugin = SyncPlugin::new(
|
||||||
origin,
|
origin,
|
||||||
sync_object,
|
sync_object,
|
||||||
@ -417,14 +416,3 @@ impl CollabCloudPluginProvider for ServerProvider {
|
|||||||
*self.user_enable_sync.read()
|
*self.user_enable_sync.read()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sink_strategy_from_object(object: &SyncObject) -> SinkStrategy {
|
|
||||||
match object.collab_type {
|
|
||||||
CollabType::Document => SinkStrategy::FixInterval(std::time::Duration::from_millis(300)),
|
|
||||||
CollabType::Folder => SinkStrategy::ASAP,
|
|
||||||
CollabType::Database => SinkStrategy::ASAP,
|
|
||||||
CollabType::WorkspaceDatabase => SinkStrategy::ASAP,
|
|
||||||
CollabType::DatabaseRow => SinkStrategy::ASAP,
|
|
||||||
CollabType::UserAwareness => SinkStrategy::ASAP,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -3,7 +3,7 @@ use std::sync::Arc;
|
|||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use anyhow::Error;
|
use anyhow::Error;
|
||||||
use client_api::collab_sync::collab_msg::CollabMessage;
|
use client_api::collab_sync::collab_msg::ServerCollabMessage;
|
||||||
use client_api::entity::UserMessage;
|
use client_api::entity::UserMessage;
|
||||||
use client_api::notify::{TokenState, TokenStateReceiver};
|
use client_api::notify::{TokenState, TokenStateReceiver};
|
||||||
use client_api::ws::{
|
use client_api::ws::{
|
||||||
@ -203,7 +203,7 @@ impl AppFlowyServer for AppFlowyCloudServer {
|
|||||||
_object_id: &str,
|
_object_id: &str,
|
||||||
) -> FutureResult<
|
) -> FutureResult<
|
||||||
Option<(
|
Option<(
|
||||||
Arc<WebSocketChannel<CollabMessage>>,
|
Arc<WebSocketChannel<ServerCollabMessage>>,
|
||||||
WSConnectStateReceiver,
|
WSConnectStateReceiver,
|
||||||
bool,
|
bool,
|
||||||
)>,
|
)>,
|
||||||
|
@ -5,7 +5,7 @@ use flowy_storage::ObjectStorageService;
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use anyhow::Error;
|
use anyhow::Error;
|
||||||
use client_api::collab_sync::collab_msg::CollabMessage;
|
use client_api::collab_sync::collab_msg::ServerCollabMessage;
|
||||||
use parking_lot::RwLock;
|
use parking_lot::RwLock;
|
||||||
use tokio_stream::wrappers::WatchStream;
|
use tokio_stream::wrappers::WatchStream;
|
||||||
#[cfg(feature = "enable_supabase")]
|
#[cfg(feature = "enable_supabase")]
|
||||||
@ -125,7 +125,7 @@ pub trait AppFlowyServer: Send + Sync + 'static {
|
|||||||
_object_id: &str,
|
_object_id: &str,
|
||||||
) -> FutureResult<
|
) -> FutureResult<
|
||||||
Option<(
|
Option<(
|
||||||
Arc<WebSocketChannel<CollabMessage>>,
|
Arc<WebSocketChannel<ServerCollabMessage>>,
|
||||||
WSConnectStateReceiver,
|
WSConnectStateReceiver,
|
||||||
bool,
|
bool,
|
||||||
)>,
|
)>,
|
||||||
|
@ -197,7 +197,7 @@ pub enum UserEvent {
|
|||||||
#[event(input = "ImportAppFlowyDataPB")]
|
#[event(input = "ImportAppFlowyDataPB")]
|
||||||
ImportAppFlowyDataFolder = 41,
|
ImportAppFlowyDataFolder = 41,
|
||||||
|
|
||||||
#[event(output = "CreateWorkspacePB")]
|
#[event(input = "CreateWorkspacePB", output = "UserWorkspacePB")]
|
||||||
CreateWorkspace = 42,
|
CreateWorkspace = 42,
|
||||||
|
|
||||||
#[event(input = "UserWorkspaceIdPB")]
|
#[event(input = "UserWorkspaceIdPB")]
|
||||||
|
@ -7,7 +7,7 @@ use tracing_appender::rolling::Rotation;
|
|||||||
use tracing_appender::{non_blocking::WorkerGuard, rolling::RollingFileAppender};
|
use tracing_appender::{non_blocking::WorkerGuard, rolling::RollingFileAppender};
|
||||||
use tracing_bunyan_formatter::JsonStorageLayer;
|
use tracing_bunyan_formatter::JsonStorageLayer;
|
||||||
use tracing_subscriber::fmt::format::Writer;
|
use tracing_subscriber::fmt::format::Writer;
|
||||||
use tracing_subscriber::{fmt, layer::SubscriberExt, EnvFilter};
|
use tracing_subscriber::{layer::SubscriberExt, EnvFilter};
|
||||||
|
|
||||||
use crate::layer::FlowyFormattingLayer;
|
use crate::layer::FlowyFormattingLayer;
|
||||||
|
|
||||||
@ -48,7 +48,7 @@ impl Builder {
|
|||||||
pub fn build(self) -> Result<(), String> {
|
pub fn build(self) -> Result<(), String> {
|
||||||
let env_filter = EnvFilter::new(self.env_filter);
|
let env_filter = EnvFilter::new(self.env_filter);
|
||||||
|
|
||||||
let std_out_layer = fmt::layer().with_writer(std::io::stdout).pretty();
|
// let std_out_layer = std::fmt::layer().with_writer(std::io::stdout).pretty();
|
||||||
let (non_blocking, guard) = tracing_appender::non_blocking(self.file_appender);
|
let (non_blocking, guard) = tracing_appender::non_blocking(self.file_appender);
|
||||||
let file_layer = FlowyFormattingLayer::new(non_blocking);
|
let file_layer = FlowyFormattingLayer::new(non_blocking);
|
||||||
|
|
||||||
@ -61,8 +61,7 @@ impl Builder {
|
|||||||
.with_env_filter(env_filter)
|
.with_env_filter(env_filter)
|
||||||
.finish()
|
.finish()
|
||||||
.with(JsonStorageLayer)
|
.with(JsonStorageLayer)
|
||||||
.with(file_layer)
|
.with(file_layer);
|
||||||
.with(std_out_layer);
|
|
||||||
|
|
||||||
set_global_default(subscriber).map_err(|e| format!("{:?}", e))?;
|
set_global_default(subscriber).map_err(|e| format!("{:?}", e))?;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user