fix(ios): fix mobile blob storage (#8702)

This commit is contained in:
EYHN
2024-11-05 11:16:00 +00:00
parent c0d802a169
commit 4977055a2e
5 changed files with 60 additions and 37 deletions

View File

@@ -141,26 +141,25 @@ export function configureFetchProvider(framework: Framework) {
undefined, undefined,
optionHeaders['Content-Type'] || optionHeaders['content-type'] optionHeaders['Content-Type'] || optionHeaders['content-type']
); );
const accept = optionHeaders['Accept'] || optionHeaders['accept'];
const nativeResponse = await CapacitorHttp.request({ const nativeResponse = await CapacitorHttp.request({
url: request.url, url: request.url,
method: method, method: method,
data: requestData, data: requestData,
dataType: type as any, dataType: type as any,
responseType: responseType:
(optionHeaders['Accept'] || optionHeaders['accept']) === accept === 'application/octet-stream' ? 'arraybuffer' : undefined,
'application/octet-stream'
? 'arraybuffer'
: undefined,
headers: Object.assign(Object.assign({}, headers), optionHeaders), headers: Object.assign(Object.assign({}, headers), optionHeaders),
}); });
const contentType = const contentType =
nativeResponse.headers['Content-Type'] || nativeResponse.headers['Content-Type'] ||
nativeResponse.headers['content-type']; nativeResponse.headers['content-type'];
let data = ( let data =
contentType === null || contentType === void 0 accept === 'application/octet-stream'
? base64ToUint8Array(nativeResponse.data)
: contentType === null || contentType === void 0
? void 0 ? void 0
: contentType.startsWith('application/json') : contentType.startsWith('application/json')
)
? JSON.stringify(nativeResponse.data) ? JSON.stringify(nativeResponse.data)
: contentType === 'application/octet-stream' : contentType === 'application/octet-stream'
? base64ToUint8Array(nativeResponse.data) ? base64ToUint8Array(nativeResponse.data)
@@ -171,7 +170,7 @@ export function configureFetchProvider(framework: Framework) {
data = null; data = null;
} }
// intercept & parse response before returning // intercept & parse response before returning
const response = new Response(data, { const response = new Response(new Blob([data], { type: contentType }), {
headers: nativeResponse.headers, headers: nativeResponse.headers,
status: nativeResponse.status, status: nativeResponse.status,
}); });

View File

@@ -1,6 +1,6 @@
import { useDocMetaHelper } from '@affine/core/components/hooks/use-block-suite-page-meta'; import { useDocMetaHelper } from '@affine/core/components/hooks/use-block-suite-page-meta';
import { useDocCollectionPage } from '@affine/core/components/hooks/use-block-suite-workspace-page'; import { useDocCollectionPage } from '@affine/core/components/hooks/use-block-suite-workspace-page';
import { FetchService } from '@affine/core/modules/cloud'; import { FetchService, GraphQLService } from '@affine/core/modules/cloud';
import { DebugLogger } from '@affine/debug'; import { DebugLogger } from '@affine/debug';
import type { ListHistoryQuery } from '@affine/graphql'; import type { ListHistoryQuery } from '@affine/graphql';
import { listHistoryQuery, recoverDocMutation } from '@affine/graphql'; import { listHistoryQuery, recoverDocMutation } from '@affine/graphql';
@@ -102,11 +102,16 @@ const docCollectionMap = new Map<string, DocCollection>();
// assume the workspace is a cloud workspace since the history feature is only enabled for cloud workspace // assume the workspace is a cloud workspace since the history feature is only enabled for cloud workspace
const getOrCreateShellWorkspace = ( const getOrCreateShellWorkspace = (
workspaceId: string, workspaceId: string,
fetchService: FetchService fetchService: FetchService,
graphQLService: GraphQLService
) => { ) => {
let docCollection = docCollectionMap.get(workspaceId); let docCollection = docCollectionMap.get(workspaceId);
if (!docCollection) { if (!docCollection) {
const blobStorage = new CloudBlobStorage(workspaceId, fetchService); const blobStorage = new CloudBlobStorage(
workspaceId,
fetchService,
graphQLService
);
docCollection = new DocCollection({ docCollection = new DocCollection({
id: workspaceId, id: workspaceId,
blobSources: { blobSources: {
@@ -144,6 +149,7 @@ export const useSnapshotPage = (
ts?: string ts?: string
) => { ) => {
const fetchService = useService(FetchService); const fetchService = useService(FetchService);
const graphQLService = useService(GraphQLService);
const snapshot = usePageHistory(docCollection.id, pageDocId, ts); const snapshot = usePageHistory(docCollection.id, pageDocId, ts);
const page = useMemo(() => { const page = useMemo(() => {
if (!ts) { if (!ts) {
@@ -152,7 +158,8 @@ export const useSnapshotPage = (
const pageId = pageDocId + '-' + ts; const pageId = pageDocId + '-' + ts;
const historyShellWorkspace = getOrCreateShellWorkspace( const historyShellWorkspace = getOrCreateShellWorkspace(
docCollection.id, docCollection.id,
fetchService fetchService,
graphQLService
); );
let page = historyShellWorkspace.getDoc(pageId); let page = historyShellWorkspace.getDoc(pageId);
if (!page && snapshot) { if (!page && snapshot) {
@@ -167,18 +174,19 @@ export const useSnapshotPage = (
}); // must load before applyUpdate }); // must load before applyUpdate
} }
return page ?? undefined; return page ?? undefined;
}, [ts, pageDocId, docCollection.id, fetchService, snapshot]); }, [ts, pageDocId, docCollection.id, fetchService, graphQLService, snapshot]);
useEffect(() => { useEffect(() => {
const historyShellWorkspace = getOrCreateShellWorkspace( const historyShellWorkspace = getOrCreateShellWorkspace(
docCollection.id, docCollection.id,
fetchService fetchService,
graphQLService
); );
// apply the rootdoc's update to the current workspace // apply the rootdoc's update to the current workspace
// this makes sure the page reference links are not deleted ones in the preview // this makes sure the page reference links are not deleted ones in the preview
const update = encodeStateAsUpdate(docCollection.doc); const update = encodeStateAsUpdate(docCollection.doc);
applyUpdate(historyShellWorkspace.doc, update); applyUpdate(historyShellWorkspace.doc, update);
}, [docCollection, fetchService]); }, [docCollection, fetchService, graphQLService]);
return page; return page;
}; };

View File

@@ -6,7 +6,11 @@ import { useNavigateHelper } from '@affine/core/components/hooks/use-navigate-he
import { PageDetailEditor } from '@affine/core/components/page-detail-editor'; import { PageDetailEditor } from '@affine/core/components/page-detail-editor';
import { SharePageNotFoundError } from '@affine/core/components/share-page-not-found-error'; import { SharePageNotFoundError } from '@affine/core/components/share-page-not-found-error';
import { AppContainer } from '@affine/core/desktop/components/app-container'; import { AppContainer } from '@affine/core/desktop/components/app-container';
import { AuthService, FetchService } from '@affine/core/modules/cloud'; import {
AuthService,
FetchService,
GraphQLService,
} from '@affine/core/modules/cloud';
import { import {
type Editor, type Editor,
type EditorSelector, type EditorSelector,
@@ -147,7 +151,7 @@ const SharePageInner = ({
}) => { }) => {
const workspacesService = useService(WorkspacesService); const workspacesService = useService(WorkspacesService);
const fetchService = useService(FetchService); const fetchService = useService(FetchService);
const graphQLService = useService(GraphQLService);
const [workspace, setWorkspace] = useState<Workspace | null>(null); const [workspace, setWorkspace] = useState<Workspace | null>(null);
const [page, setPage] = useState<Doc | null>(null); const [page, setPage] = useState<Doc | null>(null);
const [editor, setEditor] = useState<Editor | null>(null); const [editor, setEditor] = useState<Editor | null>(null);
@@ -181,7 +185,9 @@ const SharePageInner = ({
return EmptyBlobStorage; return EmptyBlobStorage;
}, },
getRemoteBlobStorages() { getRemoteBlobStorages() {
return [new CloudBlobStorage(workspaceId, fetchService)]; return [
new CloudBlobStorage(workspaceId, fetchService, graphQLService),
];
}, },
} }
); );
@@ -221,6 +227,7 @@ const SharePageInner = ({
workspaceBinary, workspaceBinary,
docBinary, docBinary,
fetchService, fetchService,
graphQLService,
]); ]);
const pageTitle = useLiveData(page?.title$); const pageTitle = useLiveData(page?.title$);

View File

@@ -237,7 +237,11 @@ export class CloudWorkspaceFlavourProviderService
return localBlob; return localBlob;
} }
const cloudBlob = new CloudBlobStorage(id, this.fetchService); const cloudBlob = new CloudBlobStorage(
id,
this.fetchService,
this.graphqlService
);
return await cloudBlob.get(blob); return await cloudBlob.get(blob);
} }
getEngineProvider(workspaceId: string): WorkspaceEngineProvider { getEngineProvider(workspaceId: string): WorkspaceEngineProvider {
@@ -259,7 +263,11 @@ export class CloudWorkspaceFlavourProviderService
}, },
getRemoteBlobStorages: () => { getRemoteBlobStorages: () => {
return [ return [
new CloudBlobStorage(workspaceId, this.fetchService), new CloudBlobStorage(
workspaceId,
this.fetchService,
this.graphqlService
),
new StaticBlobStorage(), new StaticBlobStorage(),
]; ];
}, },

View File

@@ -1,7 +1,6 @@
import type { FetchService } from '@affine/core/modules/cloud'; import type { FetchService, GraphQLService } from '@affine/core/modules/cloud';
import { import {
deleteBlobMutation, deleteBlobMutation,
fetcher,
listBlobsQuery, listBlobsQuery,
setBlobMutation, setBlobMutation,
UserFriendlyError, UserFriendlyError,
@@ -14,7 +13,8 @@ import { bufferToBlob } from '../../utils/buffer-to-blob';
export class CloudBlobStorage implements BlobStorage { export class CloudBlobStorage implements BlobStorage {
constructor( constructor(
private readonly workspaceId: string, private readonly workspaceId: string,
private readonly fetchService: FetchService private readonly fetchService: FetchService,
private readonly gqlService: GraphQLService
) {} ) {}
name = 'cloud'; name = 'cloud';
@@ -46,7 +46,8 @@ export class CloudBlobStorage implements BlobStorage {
async set(key: string, value: Blob) { async set(key: string, value: Blob) {
// set blob will check blob size & quota // set blob will check blob size & quota
return await fetcher({ return await this.gqlService
.gql({
query: setBlobMutation, query: setBlobMutation,
variables: { variables: {
workspaceId: this.workspaceId, workspaceId: this.workspaceId,
@@ -65,7 +66,7 @@ export class CloudBlobStorage implements BlobStorage {
} }
async delete(key: string) { async delete(key: string) {
await fetcher({ await this.gqlService.gql({
query: deleteBlobMutation, query: deleteBlobMutation,
variables: { variables: {
workspaceId: key, workspaceId: key,
@@ -75,7 +76,7 @@ export class CloudBlobStorage implements BlobStorage {
} }
async list() { async list() {
const result = await fetcher({ const result = await this.gqlService.gql({
query: listBlobsQuery, query: listBlobsQuery,
variables: { variables: {
workspaceId: this.workspaceId, workspaceId: this.workspaceId,