feat(core): remove empty workspace (#13317)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
* Added the ability to remove an empty workspace directly from the
workspace card when you are the owner.
* Workspace cards now display a "Remove" button for eligible workspaces.
* **Improvements**
* Workspace information now indicates if a workspace is empty, improving
clarity for users.
* **Bug Fixes**
* Enhanced accuracy in displaying workspace status by updating how
workspace profile data is handled.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
EYHN
2025-07-25 18:26:55 +08:00
committed by GitHub
parent 1dd4bbbaba
commit be55442f38
4 changed files with 47 additions and 12 deletions
@@ -335,6 +335,10 @@ class CloudWorkspaceFlavourProvider implements WorkspaceFlavourProvider {
const localData = (await docStorage.getDoc(id))?.bin;
const cloudData = (await cloudStorage.getDoc(id))?.bin;
const isEmpty = isEmptyUpdate(localData) && isEmptyUpdate(cloudData);
console.log('isEmpty', isEmpty, localData, cloudData);
docStorage.connection.disconnect();
const info = await this.getWorkspaceInfo(id, signal);
@@ -344,6 +348,7 @@ class CloudWorkspaceFlavourProvider implements WorkspaceFlavourProvider {
isOwner: info.workspace.role === Permission.Owner,
isAdmin: info.workspace.role === Permission.Admin,
isTeam: info.workspace.team,
isEmpty,
};
}
@@ -360,8 +365,10 @@ class CloudWorkspaceFlavourProvider implements WorkspaceFlavourProvider {
isOwner: info.workspace.role === Permission.Owner,
isAdmin: info.workspace.role === Permission.Admin,
isTeam: info.workspace.team,
isEmpty,
};
}
async getWorkspaceBlob(id: string, blob: string): Promise<Blob | null> {
const storage = new this.BlobStorageType({
id: id,
@@ -659,3 +666,13 @@ export class CloudWorkspaceFlavoursProvider
}
);
}
export function isEmptyUpdate(binary: Uint8Array | undefined) {
if (!binary) {
return true;
}
return (
binary.byteLength === 0 ||
(binary.byteLength === 2 && binary[0] === 0 && binary[1] === 0)
);
}
@@ -24,6 +24,7 @@ export interface WorkspaceProfileInfo {
isOwner?: boolean;
isAdmin?: boolean;
isTeam?: boolean;
isEmpty?: boolean;
}
/**
@@ -61,6 +62,7 @@ export class WorkspaceProfile extends Entity<{ metadata: WorkspaceMetadata }> {
}
private setProfile(info: WorkspaceProfileInfo) {
console.log('setProfile', info, isEqual(this.profile$.value, info));
if (isEqual(this.profile$.value, info)) {
return;
}
@@ -19,13 +19,7 @@ export class WorkspaceProfileCacheStore extends Store {
}
const info = data as WorkspaceProfileInfo;
return {
avatar: info.avatar,
name: info.name,
isOwner: info.isOwner,
isAdmin: info.isAdmin,
isTeam: info.isTeam,
};
return info;
})
);
}