diff --git a/frontend/appflowy_flutter/lib/plugins/document/application/document_collab_adapter.dart b/frontend/appflowy_flutter/lib/plugins/document/application/document_collab_adapter.dart index 976a205d98..738549875d 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/application/document_collab_adapter.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/application/document_collab_adapter.dart @@ -77,7 +77,6 @@ class DocumentCollabAdapter { final ops = diffNodes(editorState.document.root, document.root); if (ops.isEmpty) { - Log.info('Doc diff, no changes'); return; } diff --git a/frontend/appflowy_flutter/lib/workspace/application/user/user_workspace_bloc.dart b/frontend/appflowy_flutter/lib/workspace/application/user/user_workspace_bloc.dart index 80855872ad..a85cd3ca34 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/user/user_workspace_bloc.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/user/user_workspace_bloc.dart @@ -39,7 +39,12 @@ class UserWorkspaceBloc extends Bloc { final isCollabWorkspaceOn = userProfile.authenticator == AuthenticatorPB.AppFlowyCloud && FeatureFlag.collaborativeWorkspace.isOn; + Log.info( + 'init workspace, current workspace: ${currentWorkspace?.workspaceId}, ' + 'workspaces: ${workspaces.map((e) => e.workspaceId)}, isCollabWorkspaceOn: $isCollabWorkspaceOn', + ); if (currentWorkspace != null && result.$3 == true) { + Log.info('init open workspace: ${currentWorkspace.workspaceId}'); await _userService.openWorkspace(currentWorkspace.workspaceId); } emit( @@ -53,10 +58,17 @@ class UserWorkspaceBloc extends Bloc { }, fetchWorkspaces: () async { final result = await _fetchWorkspaces(); + + final currentWorkspace = result.$1; + final workspaces = result.$2; + Log.info( + 'fetch workspaces: current workspace: ${currentWorkspace?.workspaceId}, workspaces: ${workspaces.map((e) => e.workspaceId)}', + ); + emit( state.copyWith( - currentWorkspace: result.$1, - workspaces: result.$2, + currentWorkspace: currentWorkspace, + workspaces: workspaces, ), ); }, @@ -86,11 +98,17 @@ class UserWorkspaceBloc extends Bloc { ), ); // open the created workspace by default - result.onSuccess((s) { - add(OpenWorkspace(s.workspaceId)); - }); + result + ..onSuccess((s) { + Log.info('create workspace success: $s'); + add(OpenWorkspace(s.workspaceId)); + }) + ..onFailure((f) { + Log.error('create workspace error: $f'); + }); }, deleteWorkspace: (workspaceId) async { + Log.info('try to delete workspace: $workspaceId'); emit( state.copyWith( actionResult: const UserWorkspaceActionResult( @@ -106,6 +124,7 @@ class UserWorkspaceBloc extends Bloc { if (state.workspaces.length <= 1 || remoteWorkspaces.length <= 1) { // do not allow to delete the last workspace, otherwise the user // cannot do create workspace again + Log.error('cannot delete the only workspace'); final result = FlowyResult.failure( FlowyError( code: ErrorCode.Internal, @@ -132,12 +151,17 @@ class UserWorkspaceBloc extends Bloc { .toList(), (e) => state.workspaces, ); - result.onSuccess((_) { - // if the current workspace is deleted, open the first workspace - if (state.currentWorkspace?.workspaceId == workspaceId) { - add(OpenWorkspace(workspaces.first.workspaceId)); - } - }); + result + ..onSuccess((_) { + Log.info('delete workspace success: $workspaceId'); + // if the current workspace is deleted, open the first workspace + if (state.currentWorkspace?.workspaceId == workspaceId) { + add(OpenWorkspace(workspaces.first.workspaceId)); + } + }) + ..onFailure((f) { + Log.error('delete workspace error: $f'); + }); emit( state.copyWith( workspaces: workspaces, @@ -166,6 +190,17 @@ class UserWorkspaceBloc extends Bloc { ), (e) => state.currentWorkspace, ); + + result + ..onSuccess((s) { + Log.info( + 'open workspace success: $workspaceId, current workspace: ${currentWorkspace?.toProto3Json()}', + ); + }) + ..onFailure((f) { + Log.error('open workspace error: $f'); + }); + emit( state.copyWith( currentWorkspace: currentWorkspace, @@ -197,6 +232,15 @@ class UserWorkspaceBloc extends Bloc { final currentWorkspace = workspaces.firstWhere( (e) => e.workspaceId == state.currentWorkspace?.workspaceId, ); + + Log.info( + 'rename workspace: $workspaceId, name: $name', + ); + + result.onFailure((f) { + Log.error('rename workspace error: $f'); + }); + emit( state.copyWith( workspaces: workspaces, @@ -231,6 +275,15 @@ class UserWorkspaceBloc extends Bloc { final currentWorkspace = workspaces.firstWhere( (e) => e.workspaceId == state.currentWorkspace?.workspaceId, ); + + Log.info( + 'update workspace icon: $workspaceId, icon: $icon', + ); + + result.onFailure((f) { + Log.error('update workspace icon error: $f'); + }); + emit( state.copyWith( workspaces: workspaces, @@ -251,12 +304,17 @@ class UserWorkspaceBloc extends Bloc { .toList(), (e) => state.workspaces, ); - result.onSuccess((_) { - // if leaving the current workspace, open the first workspace - if (state.currentWorkspace?.workspaceId == workspaceId) { - add(OpenWorkspace(workspaces.first.workspaceId)); - } - }); + result + ..onSuccess((_) { + Log.info('leave workspace success: $workspaceId'); + // if leaving the current workspace, open the first workspace + if (state.currentWorkspace?.workspaceId == workspaceId) { + add(OpenWorkspace(workspaces.first.workspaceId)); + } + }) + ..onFailure((f) { + Log.error('leave workspace error: $f'); + }); emit( state.copyWith( workspaces: workspaces, diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/sidebar_workspace.dart b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/sidebar_workspace.dart index eeba819a46..115968796c 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/sidebar_workspace.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/sidebar_workspace.dart @@ -1,5 +1,3 @@ -import 'package:flutter/material.dart'; - import 'package:appflowy/generated/flowy_svgs.g.dart'; import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/plugins/document/presentation/editor_plugins/openai/widgets/loading.dart'; @@ -16,6 +14,7 @@ import 'package:appflowy_backend/protobuf/flowy-user/user_profile.pb.dart'; import 'package:appflowy_popover/appflowy_popover.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; +import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; class SidebarWorkspace extends StatefulWidget { @@ -142,7 +141,6 @@ class _SidebarWorkspaceState extends State { } if (message != null) { - Log.info('[Workspace] $message'); showSnackBarMessage(context, message); } } @@ -167,6 +165,7 @@ class SidebarSwitchWorkspaceButton extends StatelessWidget { onOpen: () => context .read() .add(const UserWorkspaceEvent.fetchWorkspaces()), + onClose: () => Log.info('close workspace menu'), popupBuilder: (_) { return BlocProvider.value( value: context.read(), @@ -177,6 +176,7 @@ class SidebarSwitchWorkspaceButton extends StatelessWidget { if (currentWorkspace == null) { return const SizedBox.shrink(); } + Log.info('open workspace menu'); return WorkspacesMenu( userProfile: userProfile, currentWorkspace: currentWorkspace, diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/workspace/_sidebar_workspace_menu.dart b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/workspace/_sidebar_workspace_menu.dart index d1b71481c9..65830eddd7 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/workspace/_sidebar_workspace_menu.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/workspace/_sidebar_workspace_menu.dart @@ -5,6 +5,7 @@ import 'package:appflowy/workspace/presentation/home/menu/sidebar/workspace/_sid import 'package:appflowy/workspace/presentation/home/menu/sidebar/workspace/_sidebar_workspace_icon.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/log.dart'; import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart'; import 'package:appflowy_popover/appflowy_popover.dart'; import 'package:easy_localization/easy_localization.dart'; @@ -117,7 +118,6 @@ class WorkspaceMenuItem extends StatelessWidget { ..add(const WorkspaceMemberEvent.initial()), child: BlocBuilder( 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. @@ -126,70 +126,14 @@ class WorkspaceMenuItem extends StatelessWidget { child: Stack( alignment: Alignment.center, children: [ - FlowyButton( - onTap: () { - if (!isSelected) { - context.read().add( - UserWorkspaceEvent.openWorkspace( - workspace.workspaceId, - ), - ); - PopoverContainer.of(context).closeAll(); - } - }, - margin: const EdgeInsets.symmetric( - vertical: 8, - horizontal: 12, - ), - iconPadding: 10.0, - leftIconSize: const Size.square(32), - leftIcon: const SizedBox.square( - dimension: 32, - ), - rightIcon: const HSpace(42.0), - text: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - FlowyText.medium( - workspace.name, - fontSize: 14.0, - overflow: TextOverflow.ellipsis, - withTooltip: true, - ), - FlowyText( - state.isLoading - ? '' - : LocaleKeys - .settings_appearance_members_membersCount - .plural( - members.length, - ), - fontSize: 10.0, - color: Theme.of(context).hintColor, - ), - ], - ), - ), - Positioned( - left: 8, - child: SizedBox.square( - dimension: 32, - child: FlowyTooltip( - message: - LocaleKeys.document_plugins_cover_changeIcon.tr(), - child: WorkspaceIcon( - workspace: workspace, - iconSize: 26, - enableEdit: true, - ), - ), - ), + _WorkspaceInfo( + isSelected: isSelected, + workspace: workspace, ), + Positioned(left: 8, child: _buildLeftIcon(context)), Positioned( right: 12.0, - child: Align( - child: _buildRightIcon(context), - ), + child: Align(child: _buildRightIcon(context)), ), ], ), @@ -199,6 +143,20 @@ class WorkspaceMenuItem extends StatelessWidget { ); } + Widget _buildLeftIcon(BuildContext context) { + return SizedBox.square( + dimension: 32, + child: FlowyTooltip( + message: LocaleKeys.document_plugins_cover_changeIcon.tr(), + child: WorkspaceIcon( + workspace: workspace, + iconSize: 26, + enableEdit: true, + ), + ), + ); + } + Widget _buildRightIcon(BuildContext context) { // only the owner can update or delete workspace. // only show the more action button when the workspace is selected. @@ -217,6 +175,68 @@ class WorkspaceMenuItem extends StatelessWidget { } } +class _WorkspaceInfo extends StatelessWidget { + const _WorkspaceInfo({ + required this.isSelected, + required this.workspace, + }); + + final bool isSelected; + final UserWorkspacePB workspace; + + @override + Widget build(BuildContext context) { + return BlocBuilder( + builder: (context, state) { + final members = state.members; + return FlowyButton( + onTap: () => _openWorkspace(context), + iconPadding: 10.0, + margin: const EdgeInsets.symmetric(vertical: 8, horizontal: 12), + leftIconSize: const Size.square(32), + leftIcon: const SizedBox.square(dimension: 32), + rightIcon: const HSpace(42.0), + text: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // workspace name + FlowyText.medium( + workspace.name, + fontSize: 14.0, + overflow: TextOverflow.ellipsis, + withTooltip: true, + ), + // workspace members count + FlowyText( + state.isLoading + ? '' + : LocaleKeys.settings_appearance_members_membersCount + .plural( + members.length, + ), + fontSize: 10.0, + color: Theme.of(context).hintColor, + ), + ], + ), + ); + }, + ); + } + + void _openWorkspace(BuildContext context) { + if (!isSelected) { + Log.info('open workspace: ${workspace.workspaceId}'); + context.read().add( + UserWorkspaceEvent.openWorkspace( + workspace.workspaceId, + ), + ); + PopoverContainer.of(context).closeAll(); + } + } +} + class CreateWorkspaceDialog extends StatelessWidget { const CreateWorkspaceDialog({ super.key, diff --git a/frontend/rust-lib/flowy-core/src/integrate/log.rs b/frontend/rust-lib/flowy-core/src/integrate/log.rs index 76c8efb9c4..66c37837d1 100644 --- a/frontend/rust-lib/flowy-core/src/integrate/log.rs +++ b/frontend/rust-lib/flowy-core/src/integrate/log.rs @@ -52,6 +52,9 @@ pub fn create_log_filter(level: String, with_crates: Vec, platform: Plat filters.push(format!("flowy_notification={}", "info")); filters.push(format!("lib_infra={}", level)); filters.push(format!("flowy_search={}", level)); + // Enable the frontend logs. DO NOT DISABLE. + // These logs are essential for debugging and verifying frontend behavior. + filters.push(format!("dart_ffi={}", level)); // Most of the time, we don't need to see the logs from the following crates // filters.push(format!("flowy_sqlite={}", "info"));