mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-20 03:26:47 +08:00
@@ -1,8 +1,11 @@
|
||||
import { useEnableCloud } from '@affine/core/components/hooks/affine/use-enable-cloud';
|
||||
import { WorkspaceShareSettingService } from '@affine/core/modules/share-setting';
|
||||
import type { Workspace } from '@affine/core/modules/workspace';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { track } from '@affine/track';
|
||||
import type { Store } from '@blocksuite/affine/store';
|
||||
import { useCallback } from 'react';
|
||||
import { useLiveData, useService } from '@toeverything/infra';
|
||||
import { useCallback, useEffect } from 'react';
|
||||
|
||||
import { ShareMenu } from './share-menu';
|
||||
export { CloudSvg } from './cloud-svg';
|
||||
@@ -14,6 +17,10 @@ type SharePageModalProps = {
|
||||
};
|
||||
|
||||
export const SharePageButton = ({ workspace, page }: SharePageModalProps) => {
|
||||
const t = useI18n();
|
||||
const shareSetting = useService(WorkspaceShareSettingService).sharePreview;
|
||||
const enableSharing = useLiveData(shareSetting.enableSharing$);
|
||||
|
||||
const confirmEnableCloud = useEnableCloud();
|
||||
const handleOpenShareModal = useCallback((open: boolean) => {
|
||||
if (open) {
|
||||
@@ -21,6 +28,18 @@ export const SharePageButton = ({ workspace, page }: SharePageModalProps) => {
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (workspace.meta.flavour === 'local') {
|
||||
return;
|
||||
}
|
||||
shareSetting.revalidate();
|
||||
}, [shareSetting, workspace.meta.flavour]);
|
||||
|
||||
const sharingDisabled = enableSharing === false;
|
||||
const disabledReason = sharingDisabled
|
||||
? t['com.affine.share-menu.workspace-sharing.disabled.tooltip']()
|
||||
: undefined;
|
||||
|
||||
return (
|
||||
<ShareMenu
|
||||
workspaceMetadata={workspace.meta}
|
||||
@@ -31,6 +50,8 @@ export const SharePageButton = ({ workspace, page }: SharePageModalProps) => {
|
||||
})
|
||||
}
|
||||
onOpenShareModal={handleOpenShareModal}
|
||||
disabled={sharingDisabled}
|
||||
disabledReason={disabledReason}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -35,6 +35,8 @@ export interface ShareMenuProps extends PropsWithChildren {
|
||||
onOpenShareModal?: (open: boolean) => void;
|
||||
openPaywallModal?: () => void;
|
||||
hittingPaywall?: boolean;
|
||||
disabled?: boolean;
|
||||
disabledReason?: string;
|
||||
}
|
||||
|
||||
export enum ShareMenuTab {
|
||||
@@ -203,7 +205,7 @@ export const ShareMenuContent = (props: ShareMenuProps) => {
|
||||
};
|
||||
|
||||
const DefaultShareButton = forwardRef(function DefaultShareButton(
|
||||
_,
|
||||
props: { disabled?: boolean; tooltip?: string },
|
||||
ref: Ref<HTMLButtonElement>
|
||||
) {
|
||||
const t = useI18n();
|
||||
@@ -211,18 +213,26 @@ const DefaultShareButton = forwardRef(function DefaultShareButton(
|
||||
const shared = useLiveData(shareInfoService.shareInfo.isShared$);
|
||||
|
||||
useEffect(() => {
|
||||
if (props.disabled) {
|
||||
return;
|
||||
}
|
||||
shareInfoService.shareInfo.revalidate();
|
||||
}, [shareInfoService]);
|
||||
}, [props.disabled, shareInfoService]);
|
||||
|
||||
const tooltip =
|
||||
props.tooltip ??
|
||||
(shared
|
||||
? t['com.affine.share-menu.option.link.readonly.description']()
|
||||
: t['com.affine.share-menu.option.link.no-access.description']());
|
||||
|
||||
return (
|
||||
<Tooltip
|
||||
content={
|
||||
shared
|
||||
? t['com.affine.share-menu.option.link.readonly.description']()
|
||||
: t['com.affine.share-menu.option.link.no-access.description']()
|
||||
}
|
||||
>
|
||||
<Button ref={ref} className={styles.button} variant="primary">
|
||||
<Tooltip content={tooltip}>
|
||||
<Button
|
||||
ref={ref}
|
||||
className={styles.button}
|
||||
variant="primary"
|
||||
disabled={props.disabled}
|
||||
>
|
||||
<div className={styles.buttonContainer}>
|
||||
{shared ? <PublishIcon fontSize={16} /> : <LockIcon fontSize={16} />}
|
||||
{t['com.affine.share-menu.shareButton']()}
|
||||
@@ -233,6 +243,13 @@ const DefaultShareButton = forwardRef(function DefaultShareButton(
|
||||
});
|
||||
|
||||
const LocalShareMenu = (props: ShareMenuProps) => {
|
||||
if (props.disabled) {
|
||||
return (
|
||||
<div data-testid="local-share-menu-button">
|
||||
<DefaultShareButton disabled tooltip={props.disabledReason} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<Menu
|
||||
items={<ShareMenuContent {...props} />}
|
||||
@@ -254,6 +271,13 @@ const LocalShareMenu = (props: ShareMenuProps) => {
|
||||
};
|
||||
|
||||
const CloudShareMenu = (props: ShareMenuProps) => {
|
||||
if (props.disabled) {
|
||||
return (
|
||||
<div data-testid="cloud-share-menu-button">
|
||||
<DefaultShareButton disabled tooltip={props.disabledReason} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<Menu
|
||||
items={<ShareMenuContent {...props} />}
|
||||
|
||||
@@ -16,6 +16,7 @@ import type { WorkspaceService } from '../../workspace';
|
||||
import type { WorkspaceShareSettingStore } from '../stores/share-setting';
|
||||
|
||||
type EnableAi = GetWorkspaceConfigQuery['workspace']['enableAi'];
|
||||
type EnableSharing = GetWorkspaceConfigQuery['workspace']['enableSharing'];
|
||||
type EnableUrlPreview =
|
||||
GetWorkspaceConfigQuery['workspace']['enableUrlPreview'];
|
||||
|
||||
@@ -23,6 +24,7 @@ const logger = new DebugLogger('affine:workspace-permission');
|
||||
|
||||
export class WorkspaceShareSetting extends Entity {
|
||||
enableAi$ = new LiveData<EnableAi | null>(null);
|
||||
enableSharing$ = new LiveData<EnableSharing | null>(null);
|
||||
enableUrlPreview$ = new LiveData<EnableUrlPreview | null>(null);
|
||||
inviteLink$ = new LiveData<InviteLink | null>(null);
|
||||
isLoading$ = new LiveData(false);
|
||||
@@ -48,12 +50,13 @@ export class WorkspaceShareSetting extends Entity {
|
||||
tap(value => {
|
||||
if (value) {
|
||||
this.enableAi$.next(value.enableAi);
|
||||
this.enableSharing$.next(value.enableSharing);
|
||||
this.enableUrlPreview$.next(value.enableUrlPreview);
|
||||
this.inviteLink$.next(value.inviteLink);
|
||||
}
|
||||
}),
|
||||
catchErrorInto(this.error$, error => {
|
||||
logger.error('Failed to fetch enableUrlPreview', error);
|
||||
logger.error('Failed to fetch workspace share settings', error);
|
||||
}),
|
||||
onStart(() => this.isLoading$.setValue(true)),
|
||||
onComplete(() => this.isLoading$.setValue(false))
|
||||
@@ -74,6 +77,14 @@ export class WorkspaceShareSetting extends Entity {
|
||||
await this.waitForRevalidation();
|
||||
}
|
||||
|
||||
async setEnableSharing(enableSharing: EnableSharing) {
|
||||
await this.store.updateWorkspaceEnableSharing(
|
||||
this.workspaceService.workspace.id,
|
||||
enableSharing
|
||||
);
|
||||
await this.waitForRevalidation();
|
||||
}
|
||||
|
||||
async setEnableAi(enableAi: EnableAi) {
|
||||
await this.store.updateWorkspaceEnableAi(
|
||||
this.workspaceService.workspace.id,
|
||||
|
||||
@@ -2,6 +2,7 @@ import type { WorkspaceServerService } from '@affine/core/modules/cloud';
|
||||
import {
|
||||
getWorkspaceConfigQuery,
|
||||
setEnableAiMutation,
|
||||
setEnableSharingMutation,
|
||||
setEnableUrlPreviewMutation,
|
||||
} from '@affine/graphql';
|
||||
import { Store } from '@toeverything/infra';
|
||||
@@ -47,6 +48,26 @@ export class WorkspaceShareSettingStore extends Store {
|
||||
});
|
||||
}
|
||||
|
||||
async updateWorkspaceEnableSharing(
|
||||
workspaceId: string,
|
||||
enableSharing: boolean,
|
||||
signal?: AbortSignal
|
||||
) {
|
||||
if (!this.workspaceServerService.server) {
|
||||
throw new Error('No Server');
|
||||
}
|
||||
await this.workspaceServerService.server.gql({
|
||||
query: setEnableSharingMutation,
|
||||
variables: {
|
||||
id: workspaceId,
|
||||
enableSharing,
|
||||
},
|
||||
context: {
|
||||
signal,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async updateWorkspaceEnableUrlPreview(
|
||||
workspaceId: string,
|
||||
enableUrlPreview: boolean,
|
||||
|
||||
Reference in New Issue
Block a user