mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-09-22 03:33:06 +08:00
fix(core): remove quota modal (#12586)
<!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Removed Features** - Removed all quota-reached modal dialogs, including both cloud and local storage quota notifications. - Users will no longer see modal alerts when storage limits are reached in workspaces. - **User Interface** - Quota-reached modals and related styles have been removed from workspace layouts on both desktop and mobile. - **Other Changes** - Quota notification logic and related settings have been eliminated from the application. - Maximum blob size enforcement and related callbacks have been removed from blob management. - Localization entries related to file upload size limits and quota tips have been removed. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
@@ -36,11 +36,6 @@ export class BlobFrontend {
|
|||||||
|
|
||||||
async set(blob: BlobRecord) {
|
async set(blob: BlobRecord) {
|
||||||
await this.waitForConnected();
|
await this.waitForConnected();
|
||||||
if (blob.data.byteLength > this.maxBlobSize) {
|
|
||||||
for (const cb of this.onReachedMaxBlobSizeCallbacks) {
|
|
||||||
cb(blob.data.byteLength);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
await using lock = await this.lock.lock('blob', blob.key);
|
await using lock = await this.lock.lock('blob', blob.key);
|
||||||
await this.storage.set(blob);
|
await this.storage.set(blob);
|
||||||
await lock[Symbol.asyncDispose]();
|
await lock[Symbol.asyncDispose]();
|
||||||
@@ -77,20 +72,6 @@ export class BlobFrontend {
|
|||||||
return this.sync.fullDownload(peerId, signal);
|
return this.sync.fullDownload(peerId, signal);
|
||||||
}
|
}
|
||||||
|
|
||||||
private maxBlobSize = 1024 * 1024 * 100; // 100MB
|
|
||||||
private readonly onReachedMaxBlobSizeCallbacks: Set<
|
|
||||||
(byteSize: number) => void
|
|
||||||
> = new Set();
|
|
||||||
|
|
||||||
setMaxBlobSize(max: number) {
|
|
||||||
this.maxBlobSize = max;
|
|
||||||
}
|
|
||||||
|
|
||||||
onReachedMaxBlobSize(cb: (byteSize: number) => void): () => void {
|
|
||||||
this.onReachedMaxBlobSizeCallbacks.add(cb);
|
|
||||||
return () => this.onReachedMaxBlobSizeCallbacks.delete(cb);
|
|
||||||
}
|
|
||||||
|
|
||||||
private waitForConnected(signal?: AbortSignal) {
|
private waitForConnected(signal?: AbortSignal) {
|
||||||
return this.storage.connection.waitForConnected(signal);
|
return this.storage.connection.waitForConnected(signal);
|
||||||
}
|
}
|
||||||
|
|||||||
-27
@@ -1,27 +0,0 @@
|
|||||||
import { cssVar } from '@toeverything/theme';
|
|
||||||
import { cssVarV2 } from '@toeverything/theme/v2';
|
|
||||||
import { style } from '@vanilla-extract/css';
|
|
||||||
|
|
||||||
export const ulStyle = style({
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'column',
|
|
||||||
justifyContent: 'center',
|
|
||||||
gap: '8px',
|
|
||||||
marginTop: '12px',
|
|
||||||
});
|
|
||||||
|
|
||||||
export const liStyle = style({
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'row',
|
|
||||||
alignItems: 'start',
|
|
||||||
fontSize: cssVar('fontBase'),
|
|
||||||
});
|
|
||||||
|
|
||||||
export const prefixDot = style({
|
|
||||||
background: cssVarV2('icon/activated'),
|
|
||||||
width: '5px',
|
|
||||||
height: '5px',
|
|
||||||
borderRadius: '50%',
|
|
||||||
marginRight: '12px',
|
|
||||||
marginTop: '10px',
|
|
||||||
});
|
|
||||||
-123
@@ -1,123 +0,0 @@
|
|||||||
import { ConfirmModal } from '@affine/component/ui/modal';
|
|
||||||
import { openQuotaModalAtom } from '@affine/core/components/atoms';
|
|
||||||
import { WorkspaceDialogService } from '@affine/core/modules/dialogs';
|
|
||||||
import { WorkspacePermissionService } from '@affine/core/modules/permissions';
|
|
||||||
import { WorkspaceQuotaService } from '@affine/core/modules/quota';
|
|
||||||
import { WorkspaceService } from '@affine/core/modules/workspace';
|
|
||||||
import { type I18nString, useI18n } from '@affine/i18n';
|
|
||||||
import { track } from '@affine/track';
|
|
||||||
import { useLiveData, useService } from '@toeverything/infra';
|
|
||||||
import { useAtom } from 'jotai';
|
|
||||||
import { useCallback, useEffect, useMemo } from 'react';
|
|
||||||
|
|
||||||
import { useAsyncCallback } from '../../hooks/affine-async-hooks';
|
|
||||||
import * as styles from './cloud-quota-modal.css';
|
|
||||||
|
|
||||||
export const CloudQuotaModal = () => {
|
|
||||||
const t = useI18n();
|
|
||||||
const currentWorkspace = useService(WorkspaceService).workspace;
|
|
||||||
const [open, setOpen] = useAtom(openQuotaModalAtom);
|
|
||||||
const workspaceQuotaService = useService(WorkspaceQuotaService);
|
|
||||||
useEffect(() => {
|
|
||||||
workspaceQuotaService.quota.revalidate();
|
|
||||||
}, [workspaceQuotaService]);
|
|
||||||
const workspaceQuota = useLiveData(workspaceQuotaService.quota.quota$);
|
|
||||||
const permissionService = useService(WorkspacePermissionService);
|
|
||||||
const isOwner = useLiveData(permissionService.permission.isOwner$);
|
|
||||||
useEffect(() => {
|
|
||||||
// revalidate permission
|
|
||||||
permissionService.permission.revalidate();
|
|
||||||
}, [permissionService]);
|
|
||||||
|
|
||||||
const workspaceDialogService = useService(WorkspaceDialogService);
|
|
||||||
const handleUpgradeConfirm = useCallback(() => {
|
|
||||||
workspaceDialogService.open('setting', {
|
|
||||||
activeTab: 'plans',
|
|
||||||
scrollAnchor: 'cloudPricingPlan',
|
|
||||||
});
|
|
||||||
|
|
||||||
track.$.paywall.storage.viewPlans();
|
|
||||||
setOpen(false);
|
|
||||||
}, [workspaceDialogService, setOpen]);
|
|
||||||
|
|
||||||
const description = useMemo(() => {
|
|
||||||
if (!workspaceQuota) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (isOwner) {
|
|
||||||
return (
|
|
||||||
<OwnerDescription quota={workspaceQuota.humanReadable.blobLimit} />
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return t['com.affine.payment.blob-limit.description.member']({
|
|
||||||
quota: workspaceQuota.humanReadable.blobLimit,
|
|
||||||
});
|
|
||||||
}, [isOwner, workspaceQuota, t]);
|
|
||||||
|
|
||||||
const onAbortLargeBlob = useAsyncCallback(
|
|
||||||
async (byteSize: number) => {
|
|
||||||
// wait for quota revalidation
|
|
||||||
await workspaceQuotaService.quota.waitForRevalidation();
|
|
||||||
if (
|
|
||||||
byteSize > (workspaceQuotaService.quota.quota$.value?.blobLimit ?? 0)
|
|
||||||
) {
|
|
||||||
setOpen(true);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[setOpen, workspaceQuotaService]
|
|
||||||
);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!workspaceQuota) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
currentWorkspace.engine.blob.setMaxBlobSize(workspaceQuota.blobLimit);
|
|
||||||
|
|
||||||
const disposable =
|
|
||||||
currentWorkspace.engine.blob.onReachedMaxBlobSize(onAbortLargeBlob);
|
|
||||||
return () => {
|
|
||||||
disposable();
|
|
||||||
};
|
|
||||||
}, [currentWorkspace.engine.blob, onAbortLargeBlob, workspaceQuota]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ConfirmModal
|
|
||||||
open={open}
|
|
||||||
title={t['com.affine.payment.blob-limit.title']()}
|
|
||||||
onOpenChange={setOpen}
|
|
||||||
description={description}
|
|
||||||
onConfirm={handleUpgradeConfirm}
|
|
||||||
confirmText={t['com.affine.payment.upgrade']()}
|
|
||||||
confirmButtonOptions={{
|
|
||||||
variant: 'primary',
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const tips: I18nString[] = [
|
|
||||||
'com.affine.payment.blob-limit.description.owner.tips-1',
|
|
||||||
'com.affine.payment.blob-limit.description.owner.tips-2',
|
|
||||||
'com.affine.payment.blob-limit.description.owner.tips-3',
|
|
||||||
];
|
|
||||||
|
|
||||||
const OwnerDescription = ({ quota }: { quota: string }) => {
|
|
||||||
const t = useI18n();
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
{t['com.affine.payment.blob-limit.description.owner']({
|
|
||||||
quota: quota,
|
|
||||||
})}
|
|
||||||
<ul className={styles.ulStyle}>
|
|
||||||
{tips.map((tip, index) => (
|
|
||||||
<li className={styles.liStyle} key={index}>
|
|
||||||
<div className={styles.prefixDot} />
|
|
||||||
{t.t(tip)}
|
|
||||||
</li>
|
|
||||||
))}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
export * from './cloud-quota-modal';
|
|
||||||
export * from './local-quota-modal';
|
|
||||||
-45
@@ -1,45 +0,0 @@
|
|||||||
import { ConfirmModal } from '@affine/component/ui/modal';
|
|
||||||
import { openQuotaModalAtom } from '@affine/core/components/atoms';
|
|
||||||
import { WorkspaceService } from '@affine/core/modules/workspace';
|
|
||||||
import { useI18n } from '@affine/i18n';
|
|
||||||
import { useService } from '@toeverything/infra';
|
|
||||||
import { useAtom } from 'jotai';
|
|
||||||
import { useCallback, useEffect } from 'react';
|
|
||||||
|
|
||||||
export const LocalQuotaModal = () => {
|
|
||||||
const t = useI18n();
|
|
||||||
const currentWorkspace = useService(WorkspaceService).workspace;
|
|
||||||
const [open, setOpen] = useAtom(openQuotaModalAtom);
|
|
||||||
|
|
||||||
const onConfirm = useCallback(() => {
|
|
||||||
setOpen(false);
|
|
||||||
}, [setOpen]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const disposable = currentWorkspace.engine.blob.onReachedMaxBlobSize(() => {
|
|
||||||
setOpen(true);
|
|
||||||
});
|
|
||||||
return () => {
|
|
||||||
disposable();
|
|
||||||
};
|
|
||||||
}, [currentWorkspace.engine.blob, setOpen]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ConfirmModal
|
|
||||||
open={open}
|
|
||||||
title={t['com.affine.payment.blob-limit.title']()}
|
|
||||||
description={t['com.affine.payment.blob-limit.description.local']({
|
|
||||||
quota: '100MB',
|
|
||||||
})}
|
|
||||||
onOpenChange={setOpen}
|
|
||||||
cancelButtonOptions={{
|
|
||||||
hidden: true,
|
|
||||||
}}
|
|
||||||
onConfirm={onConfirm}
|
|
||||||
confirmText={t['Got it']()}
|
|
||||||
confirmButtonOptions={{
|
|
||||||
variant: 'primary',
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
@@ -1,10 +1,5 @@
|
|||||||
import { uniReactRoot } from '@affine/component';
|
import { uniReactRoot } from '@affine/component';
|
||||||
// import { WorkspaceAIOnboarding } from '@affine/core/components/affine/ai-onboarding';
|
|
||||||
import { AiLoginRequiredModal } from '@affine/core/components/affine/auth/ai-login-required';
|
import { AiLoginRequiredModal } from '@affine/core/components/affine/auth/ai-login-required';
|
||||||
import {
|
|
||||||
CloudQuotaModal,
|
|
||||||
LocalQuotaModal,
|
|
||||||
} from '@affine/core/components/affine/quota-reached-modal';
|
|
||||||
import { useResponsiveSidebar } from '@affine/core/components/hooks/use-responsive-siedebar';
|
import { useResponsiveSidebar } from '@affine/core/components/hooks/use-responsive-siedebar';
|
||||||
import { SWRConfigProvider } from '@affine/core/components/providers/swr-config-provider';
|
import { SWRConfigProvider } from '@affine/core/components/providers/swr-config-provider';
|
||||||
import { WorkspaceSideEffects } from '@affine/core/components/providers/workspace-side-effects';
|
import { WorkspaceSideEffects } from '@affine/core/components/providers/workspace-side-effects';
|
||||||
@@ -29,13 +24,8 @@ export const WorkspaceLayout = function WorkspaceLayout({
|
|||||||
|
|
||||||
{/* ---- some side-effect components ---- */}
|
{/* ---- some side-effect components ---- */}
|
||||||
{currentWorkspace?.flavour !== 'local' ? (
|
{currentWorkspace?.flavour !== 'local' ? (
|
||||||
<>
|
<QuotaCheck workspaceMeta={currentWorkspace.meta} />
|
||||||
<CloudQuotaModal />
|
) : null}
|
||||||
<QuotaCheck workspaceMeta={currentWorkspace.meta} />
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<LocalQuotaModal />
|
|
||||||
)}
|
|
||||||
<AiLoginRequiredModal />
|
<AiLoginRequiredModal />
|
||||||
<WorkspaceSideEffects />
|
<WorkspaceSideEffects />
|
||||||
<PeekViewManagerModal />
|
<PeekViewManagerModal />
|
||||||
|
|||||||
@@ -1,10 +1,6 @@
|
|||||||
import { uniReactRoot } from '@affine/component';
|
import { uniReactRoot } from '@affine/component';
|
||||||
import { AffineErrorBoundary } from '@affine/core/components/affine/affine-error-boundary';
|
import { AffineErrorBoundary } from '@affine/core/components/affine/affine-error-boundary';
|
||||||
import { AiLoginRequiredModal } from '@affine/core/components/affine/auth/ai-login-required';
|
import { AiLoginRequiredModal } from '@affine/core/components/affine/auth/ai-login-required';
|
||||||
import {
|
|
||||||
CloudQuotaModal,
|
|
||||||
LocalQuotaModal,
|
|
||||||
} from '@affine/core/components/affine/quota-reached-modal';
|
|
||||||
import { SWRConfigProvider } from '@affine/core/components/providers/swr-config-provider';
|
import { SWRConfigProvider } from '@affine/core/components/providers/swr-config-provider';
|
||||||
import { WorkspaceSideEffects } from '@affine/core/components/providers/workspace-side-effects';
|
import { WorkspaceSideEffects } from '@affine/core/components/providers/workspace-side-effects';
|
||||||
import {
|
import {
|
||||||
@@ -146,11 +142,6 @@ export const WorkspaceLayout = ({
|
|||||||
|
|
||||||
{/* ---- some side-effect components ---- */}
|
{/* ---- some side-effect components ---- */}
|
||||||
<PeekViewManagerModal />
|
<PeekViewManagerModal />
|
||||||
{workspace?.flavour !== 'local' ? (
|
|
||||||
<CloudQuotaModal />
|
|
||||||
) : (
|
|
||||||
<LocalQuotaModal />
|
|
||||||
)}
|
|
||||||
<AiLoginRequiredModal />
|
<AiLoginRequiredModal />
|
||||||
<uniReactRoot.Root />
|
<uniReactRoot.Root />
|
||||||
<WorkspaceSideEffects />
|
<WorkspaceSideEffects />
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
"it-IT": 100,
|
"it-IT": 100,
|
||||||
"it": 1,
|
"it": 1,
|
||||||
"ja": 100,
|
"ja": 100,
|
||||||
"ko": 53,
|
"ko": 54,
|
||||||
"pl": 100,
|
"pl": 100,
|
||||||
"pt-BR": 100,
|
"pt-BR": 100,
|
||||||
"ru": 100,
|
"ru": 100,
|
||||||
|
|||||||
@@ -3622,36 +3622,6 @@ export function useAFFiNEI18N(): {
|
|||||||
* `Tell us your use case`
|
* `Tell us your use case`
|
||||||
*/
|
*/
|
||||||
["com.affine.payment.billing-type-form.title"](): string;
|
["com.affine.payment.billing-type-form.title"](): string;
|
||||||
/**
|
|
||||||
* `The maximum file upload size for local workspaces is {{quota}}.`
|
|
||||||
*/
|
|
||||||
["com.affine.payment.blob-limit.description.local"](options: {
|
|
||||||
readonly quota: string;
|
|
||||||
}): string;
|
|
||||||
/**
|
|
||||||
* `The maximum file upload size for this joined workspace is {{quota}}. You can contact the owner of this workspace.`
|
|
||||||
*/
|
|
||||||
["com.affine.payment.blob-limit.description.member"](options: {
|
|
||||||
readonly quota: string;
|
|
||||||
}): string;
|
|
||||||
/**
|
|
||||||
* `The maximum file upload size for this workspace is {{quota}}. To proceed, you can:`
|
|
||||||
*/
|
|
||||||
["com.affine.payment.blob-limit.description.owner"](options: {
|
|
||||||
readonly quota: string;
|
|
||||||
}): string;
|
|
||||||
/**
|
|
||||||
* `Upgrade your account for larger file upload limits`
|
|
||||||
*/
|
|
||||||
["com.affine.payment.blob-limit.description.owner.tips-1"](): string;
|
|
||||||
/**
|
|
||||||
* `Upgrade the workspace plan to increase storage for all member`
|
|
||||||
*/
|
|
||||||
["com.affine.payment.blob-limit.description.owner.tips-2"](): string;
|
|
||||||
/**
|
|
||||||
* `Compress your file and upload again`
|
|
||||||
*/
|
|
||||||
["com.affine.payment.blob-limit.description.owner.tips-3"](): string;
|
|
||||||
/**
|
/**
|
||||||
* `You have reached the limit`
|
* `You have reached the limit`
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -903,12 +903,6 @@
|
|||||||
"com.affine.payment.billing-type-form.description": "Please tell us more about your use case, to make AFFiNE better.",
|
"com.affine.payment.billing-type-form.description": "Please tell us more about your use case, to make AFFiNE better.",
|
||||||
"com.affine.payment.billing-type-form.go": "Go",
|
"com.affine.payment.billing-type-form.go": "Go",
|
||||||
"com.affine.payment.billing-type-form.title": "Tell us your use case",
|
"com.affine.payment.billing-type-form.title": "Tell us your use case",
|
||||||
"com.affine.payment.blob-limit.description.local": "The maximum file upload size for local workspaces is {{quota}}.",
|
|
||||||
"com.affine.payment.blob-limit.description.member": "The maximum file upload size for this joined workspace is {{quota}}. You can contact the owner of this workspace.",
|
|
||||||
"com.affine.payment.blob-limit.description.owner": "The maximum file upload size for this workspace is {{quota}}. To proceed, you can:",
|
|
||||||
"com.affine.payment.blob-limit.description.owner.tips-1": "Upgrade your account for larger file upload limits",
|
|
||||||
"com.affine.payment.blob-limit.description.owner.tips-2": "Upgrade the workspace plan to increase storage for all member",
|
|
||||||
"com.affine.payment.blob-limit.description.owner.tips-3": "Compress your file and upload again",
|
|
||||||
"com.affine.payment.blob-limit.title": "You have reached the limit",
|
"com.affine.payment.blob-limit.title": "You have reached the limit",
|
||||||
"com.affine.payment.book-a-demo": "Book a demo",
|
"com.affine.payment.book-a-demo": "Book a demo",
|
||||||
"com.affine.payment.buy-pro": "Buy Pro",
|
"com.affine.payment.buy-pro": "Buy Pro",
|
||||||
|
|||||||
Reference in New Issue
Block a user