mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-17 22:37:04 +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) {
|
||||
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 this.storage.set(blob);
|
||||
await lock[Symbol.asyncDispose]();
|
||||
@@ -77,20 +72,6 @@ export class BlobFrontend {
|
||||
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) {
|
||||
return this.storage.connection.waitForConnected(signal);
|
||||
}
|
||||
|
||||
@@ -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',
|
||||
});
|
||||
@@ -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';
|
||||
@@ -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 { WorkspaceAIOnboarding } from '@affine/core/components/affine/ai-onboarding';
|
||||
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 { SWRConfigProvider } from '@affine/core/components/providers/swr-config-provider';
|
||||
import { WorkspaceSideEffects } from '@affine/core/components/providers/workspace-side-effects';
|
||||
@@ -29,13 +24,8 @@ export const WorkspaceLayout = function WorkspaceLayout({
|
||||
|
||||
{/* ---- some side-effect components ---- */}
|
||||
{currentWorkspace?.flavour !== 'local' ? (
|
||||
<>
|
||||
<CloudQuotaModal />
|
||||
<QuotaCheck workspaceMeta={currentWorkspace.meta} />
|
||||
</>
|
||||
) : (
|
||||
<LocalQuotaModal />
|
||||
)}
|
||||
<QuotaCheck workspaceMeta={currentWorkspace.meta} />
|
||||
) : null}
|
||||
<AiLoginRequiredModal />
|
||||
<WorkspaceSideEffects />
|
||||
<PeekViewManagerModal />
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
import { uniReactRoot } from '@affine/component';
|
||||
import { AffineErrorBoundary } from '@affine/core/components/affine/affine-error-boundary';
|
||||
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 { WorkspaceSideEffects } from '@affine/core/components/providers/workspace-side-effects';
|
||||
import {
|
||||
@@ -146,11 +142,6 @@ export const WorkspaceLayout = ({
|
||||
|
||||
{/* ---- some side-effect components ---- */}
|
||||
<PeekViewManagerModal />
|
||||
{workspace?.flavour !== 'local' ? (
|
||||
<CloudQuotaModal />
|
||||
) : (
|
||||
<LocalQuotaModal />
|
||||
)}
|
||||
<AiLoginRequiredModal />
|
||||
<uniReactRoot.Root />
|
||||
<WorkspaceSideEffects />
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
"it-IT": 100,
|
||||
"it": 1,
|
||||
"ja": 100,
|
||||
"ko": 53,
|
||||
"ko": 54,
|
||||
"pl": 100,
|
||||
"pt-BR": 100,
|
||||
"ru": 100,
|
||||
|
||||
@@ -3622,36 +3622,6 @@ export function useAFFiNEI18N(): {
|
||||
* `Tell us your use case`
|
||||
*/
|
||||
["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`
|
||||
*/
|
||||
|
||||
@@ -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.go": "Go",
|
||||
"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.book-a-demo": "Book a demo",
|
||||
"com.affine.payment.buy-pro": "Buy Pro",
|
||||
|
||||
Reference in New Issue
Block a user