feat: optimize the workspace menu loading speed (#6758)

* feat: optimize the workspace menu loading speed

* chore: add workspace menu animation

* feat: optimize workspace menu loading speed on mobile

* test: workspace member count test

* fix: rust ci
This commit is contained in:
Lucas 2024-11-13 20:36:15 +08:00 committed by GitHub
parent 57933736ea
commit cd3be696dc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 87 additions and 61 deletions

View File

@ -43,6 +43,7 @@ jobs:
cp deploy.env .env
sed -i '' 's|RUST_LOG=.*|RUST_LOG=trace|' .env
sed -i '' 's|API_EXTERNAL_URL=.*|API_EXTERNAL_URL=http://localhost|' .env
sed -i '' 's|APPFLOWY_AI_OPENAI_API_KEY=.*|APPFLOWY_AI_OPENAI_API_KEY=${{ secrets.CI_OPENAI_API_KEY }}|' .env
- name: Ensure AppFlowy-Cloud is Running with Correct Version
working-directory: AppFlowy-Cloud
@ -137,7 +138,7 @@ jobs:
run: |
cp deploy.env .env
sed -i 's|RUST_LOG=.*|RUST_LOG=trace|' .env
sed -i 's|GOTRUE_MAILER_AUTOCONFIRM=.*|GOTRUE_MAILER_AUTOCONFIRM=true|' .env
sed -i 's|GOTRUE_MAILER_AUTOCONFIRM=.*|GOTRUE_MAILER_AUTOCONFIRM=true|' .env
sed -i 's|API_EXTERNAL_URL=.*|API_EXTERNAL_URL=http://localhost|' .env
- name: Ensure AppFlowy-Cloud is Running with Correct Version
@ -160,7 +161,7 @@ jobs:
else
echo "No volumes to remove."
fi
docker compose pull
docker compose up -d
echo "Waiting for the container to be ready..."

View File

@ -13,7 +13,7 @@ import '../../../shared/util.dart';
void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
group('collaborative workspace: ', () {
group('collaborative workspace:', () {
// combine the create and delete workspace test to reduce the time
testWidgets('create a new workspace, open it and then delete it',
(tester) async {
@ -74,5 +74,32 @@ void main() {
},
);
});
testWidgets('check the member count immediately after creating a workspace',
(tester) async {
// only run the test when the feature flag is on
if (!FeatureFlag.collaborativeWorkspace.isOn) {
return;
}
await tester.initializeAppFlowy(
cloudType: AuthenticatorType.appflowyCloudSelfHost,
);
await tester.tapGoogleLoginInButton();
await tester.expectToSeeHomePageWithGetStartedPage();
const name = 'AppFlowy.IO';
// the workspace will be opened after created
await tester.createCollaborativeWorkspace(name);
final loading = find.byType(Loading);
await tester.pumpUntilNotFound(loading);
await tester.openCollaborativeWorkspaceMenu();
// expect to see the member count
final memberCount = find.text('1 member');
expect(memberCount, findsNWidgets(2));
});
});
}

View File

@ -234,6 +234,7 @@ class _WorkspaceMenuItemContent extends StatelessWidget {
@override
Widget build(BuildContext context) {
final memberCount = workspace.memberCount.toInt();
return Padding(
padding: const EdgeInsets.only(left: 12),
child: Column(
@ -247,10 +248,10 @@ class _WorkspaceMenuItemContent extends StatelessWidget {
overflow: TextOverflow.ellipsis,
),
FlowyText(
context.read<WorkspaceMemberBloc>().state.isLoading
memberCount == 0
? ''
: LocaleKeys.settings_appearance_members_membersCount.plural(
context.read<WorkspaceMemberBloc>().state.members.length,
memberCount,
),
fontSize: 10.0,
color: Theme.of(context).hintColor,

View File

@ -170,7 +170,7 @@ class _WorkspaceMoreActionWrapper extends CustomActionCell {
switch (inner) {
case WorkspaceMoreAction.delete:
return FlowySvg(
FlowySvgs.delete_s,
FlowySvgs.trash_s,
color: onHover ? Theme.of(context).colorScheme.error : null,
);
case WorkspaceMoreAction.rename:

View File

@ -196,26 +196,23 @@ class _WorkspaceMenuItemState extends State<WorkspaceMenuItem> {
}
Widget _buildRightIcon(BuildContext context, ValueNotifier<bool> isHovered) {
// only the owner can update or delete workspace.
if (context.read<WorkspaceMemberBloc>().state.isLoading) {
return const SizedBox.shrink();
}
return Row(
children: [
ValueListenableBuilder(
valueListenable: isHovered,
builder: (context, value, child) {
return Padding(
padding: const EdgeInsets.only(left: 8.0),
child: Opacity(
opacity: value ? 1.0 : 0.0,
child: child,
),
);
},
child: WorkspaceMoreActionList(workspace: widget.workspace),
),
// only the owner can update or delete workspace.
if (!context.read<WorkspaceMemberBloc>().state.isLoading)
ValueListenableBuilder(
valueListenable: isHovered,
builder: (context, value, child) {
return Padding(
padding: const EdgeInsets.only(left: 8.0),
child: Opacity(
opacity: value ? 1.0 : 0.0,
child: child,
),
);
},
child: WorkspaceMoreActionList(workspace: widget.workspace),
),
const HSpace(8.0),
if (widget.isSelected) ...[
const Padding(
@ -244,43 +241,38 @@ class _WorkspaceInfo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocBuilder<WorkspaceMemberBloc, WorkspaceMemberState>(
builder: (context, state) {
final members = state.members;
return FlowyButton(
onTap: () => _openWorkspace(context),
iconPadding: 10.0,
leftIconSize: const Size.square(32),
leftIcon: const SizedBox.square(dimension: 32),
rightIcon: const HSpace(32.0),
text: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: [
// workspace name
FlowyText.medium(
workspace.name,
fontSize: 14.0,
figmaLineHeight: 17.0,
overflow: TextOverflow.ellipsis,
withTooltip: true,
),
// workspace members count
FlowyText.regular(
state.isLoading
? ''
: LocaleKeys.settings_appearance_members_membersCount
.plural(
members.length,
),
fontSize: 10.0,
figmaLineHeight: 12.0,
color: Theme.of(context).hintColor,
),
],
final memberCount = workspace.memberCount.toInt();
return FlowyButton(
onTap: () => _openWorkspace(context),
iconPadding: 10.0,
leftIconSize: const Size.square(32),
leftIcon: const SizedBox.square(dimension: 32),
rightIcon: const HSpace(32.0),
text: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: [
// workspace name
FlowyText.medium(
workspace.name,
fontSize: 14.0,
figmaLineHeight: 17.0,
overflow: TextOverflow.ellipsis,
withTooltip: true,
),
);
},
// workspace members count
FlowyText.regular(
memberCount == 0
? ''
: LocaleKeys.settings_appearance_members_membersCount.plural(
memberCount,
),
fontSize: 10.0,
figmaLineHeight: 12.0,
color: Theme.of(context).hintColor,
),
],
),
);
}

View File

@ -204,9 +204,12 @@ class _SidebarSwitchWorkspaceButtonState
@override
Widget build(BuildContext context) {
return AppFlowyPopover(
direction: PopoverDirection.bottomWithLeftAligned,
direction: PopoverDirection.bottomWithCenterAligned,
offset: const Offset(0, 5),
constraints: const BoxConstraints(maxWidth: 300, maxHeight: 600),
animationDuration: Durations.short3,
beginScaleFactor: 1.0,
beginOpacity: 0.8,
controller: _popoverController,
triggerActions: PopoverTriggerFlags.none,
onOpen: () {

View File

@ -679,6 +679,7 @@ pub fn save_user_workspace(
user_workspace_table::created_at.eq(&user_workspace.created_at),
user_workspace_table::database_storage_id.eq(&user_workspace.database_storage_id),
user_workspace_table::icon.eq(&user_workspace.icon),
user_workspace_table::member_count.eq(&user_workspace.member_count),
))
.execute(conn)?;
@ -729,6 +730,7 @@ pub fn save_all_user_workspaces(
user_workspace_table::created_at.eq(&user_workspace.created_at),
user_workspace_table::database_storage_id.eq(&user_workspace.database_storage_id),
user_workspace_table::icon.eq(&user_workspace.icon),
user_workspace_table::member_count.eq(&user_workspace.member_count),
))
.execute(conn)?;