mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-09-23 20:18:42 +08:00
feat: use baseurl from server config (#5369)
This commit is contained in:
@@ -10,6 +10,9 @@ export class ServerConfigType {
|
|||||||
|
|
||||||
@Field({ description: 'server flavor' })
|
@Field({ description: 'server flavor' })
|
||||||
flavor!: string;
|
flavor!: string;
|
||||||
|
|
||||||
|
@Field({ description: 'server base url' })
|
||||||
|
baseUrl!: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ServerConfigResolver {
|
export class ServerConfigResolver {
|
||||||
@@ -20,6 +23,7 @@ export class ServerConfigResolver {
|
|||||||
return {
|
return {
|
||||||
version: AFFiNE.version,
|
version: AFFiNE.version,
|
||||||
flavor: SERVER_FLAVOR,
|
flavor: SERVER_FLAVOR,
|
||||||
|
baseUrl: AFFiNE.baseUrl,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,9 @@ type ServerConfigType {
|
|||||||
|
|
||||||
"""server flavor"""
|
"""server flavor"""
|
||||||
flavor: String!
|
flavor: String!
|
||||||
|
|
||||||
|
"""server base url"""
|
||||||
|
baseUrl: String!
|
||||||
}
|
}
|
||||||
|
|
||||||
type UserQuotaHumanReadable {
|
type UserQuotaHumanReadable {
|
||||||
|
|||||||
@@ -391,7 +391,6 @@ export const createConfiguration: (
|
|||||||
proxy: {
|
proxy: {
|
||||||
'/api/worker/': {
|
'/api/worker/': {
|
||||||
target: 'https://affine-worker.toeverything.workers.dev',
|
target: 'https://affine-worker.toeverything.workers.dev',
|
||||||
pathRewrite: { '^/api/worker/': '/api/' },
|
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
secure: false,
|
secure: false,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ export function getRuntimeConfig(buildFlags: BuildFlags): RuntimeConfig {
|
|||||||
enablePayment: true,
|
enablePayment: true,
|
||||||
enablePageHistory: false,
|
enablePageHistory: false,
|
||||||
enableCopilot: false,
|
enableCopilot: false,
|
||||||
serverUrlPrefix: 'https://insider.affine.pro', // Let insider be stable environment temporarily.
|
serverUrlPrefix: 'https://app.affine.pro',
|
||||||
editorFlags,
|
editorFlags,
|
||||||
appVersion: packageJson.version,
|
appVersion: packageJson.version,
|
||||||
editorVersion: packageJson.dependencies['@blocksuite/presets'],
|
editorVersion: packageJson.dependencies['@blocksuite/presets'],
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
|||||||
import { useWorkspace } from '@toeverything/hooks/use-workspace';
|
import { useWorkspace } from '@toeverything/hooks/use-workspace';
|
||||||
import { useWorkspaceInfo } from '@toeverything/hooks/use-workspace-info';
|
import { useWorkspaceInfo } from '@toeverything/hooks/use-workspace-info';
|
||||||
|
|
||||||
import { useSelfHosted } from '../../../hooks/affine/use-server-flavor';
|
import { useSelfHosted } from '../../../hooks/affine/use-server-config';
|
||||||
import { DeleteLeaveWorkspace } from './delete-leave-workspace';
|
import { DeleteLeaveWorkspace } from './delete-leave-workspace';
|
||||||
import { EnableCloudPanel } from './enable-cloud';
|
import { EnableCloudPanel } from './enable-cloud';
|
||||||
import { ExportPanel } from './export';
|
import { ExportPanel } from './export';
|
||||||
|
|||||||
+1
-1
@@ -34,7 +34,7 @@ import {
|
|||||||
openSignOutModalAtom,
|
openSignOutModalAtom,
|
||||||
} from '../../../../atoms';
|
} from '../../../../atoms';
|
||||||
import { useCurrentUser } from '../../../../hooks/affine/use-current-user';
|
import { useCurrentUser } from '../../../../hooks/affine/use-current-user';
|
||||||
import { useSelfHosted } from '../../../../hooks/affine/use-server-flavor';
|
import { useSelfHosted } from '../../../../hooks/affine/use-server-config';
|
||||||
import { useUserSubscription } from '../../../../hooks/use-subscription';
|
import { useUserSubscription } from '../../../../hooks/use-subscription';
|
||||||
import { validateAndReduceImage } from '../../../../utils/reduce-image';
|
import { validateAndReduceImage } from '../../../../utils/reduce-image';
|
||||||
import { Upload } from '../../../pure/file-upload';
|
import { Upload } from '../../../pure/file-upload';
|
||||||
|
|||||||
+1
-1
@@ -8,7 +8,7 @@ import {
|
|||||||
import type { ReactElement, SVGProps } from 'react';
|
import type { ReactElement, SVGProps } from 'react';
|
||||||
|
|
||||||
import { useCurrentLoginStatus } from '../../../../hooks/affine/use-current-login-status';
|
import { useCurrentLoginStatus } from '../../../../hooks/affine/use-current-login-status';
|
||||||
import { useSelfHosted } from '../../../../hooks/affine/use-server-flavor';
|
import { useSelfHosted } from '../../../../hooks/affine/use-server-config';
|
||||||
import { AboutAffine } from './about';
|
import { AboutAffine } from './about';
|
||||||
import { AppearanceSettings } from './appearance';
|
import { AppearanceSettings } from './appearance';
|
||||||
import { BillingSettings } from './billing';
|
import { BillingSettings } from './billing';
|
||||||
|
|||||||
+2
-1
@@ -19,7 +19,7 @@ export const ShareExport = ({
|
|||||||
const t = useAFFiNEI18N();
|
const t = useAFFiNEI18N();
|
||||||
const workspaceId = workspace.id;
|
const workspaceId = workspace.id;
|
||||||
const pageId = currentPage.id;
|
const pageId = currentPage.id;
|
||||||
const { onClickCopyLink } = useSharingUrl({
|
const { sharingUrl, onClickCopyLink } = useSharingUrl({
|
||||||
workspaceId,
|
workspaceId,
|
||||||
pageId,
|
pageId,
|
||||||
urlType: 'workspace',
|
urlType: 'workspace',
|
||||||
@@ -57,6 +57,7 @@ export const ShareExport = ({
|
|||||||
onClick={onClickCopyLink}
|
onClick={onClickCopyLink}
|
||||||
icon={<LinkIcon />}
|
icon={<LinkIcon />}
|
||||||
type="plain"
|
type="plain"
|
||||||
|
disabled={!sharingUrl}
|
||||||
>
|
>
|
||||||
{t['com.affine.share-menu.copy-private-link']()}
|
{t['com.affine.share-menu.copy-private-link']()}
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
+10
-3
@@ -18,6 +18,7 @@ import { useCallback } from 'react';
|
|||||||
import type { PageMode } from '../../../../atoms';
|
import type { PageMode } from '../../../../atoms';
|
||||||
import { currentModeAtom } from '../../../../atoms/mode';
|
import { currentModeAtom } from '../../../../atoms/mode';
|
||||||
import { useIsSharedPage } from '../../../../hooks/affine/use-is-shared-page';
|
import { useIsSharedPage } from '../../../../hooks/affine/use-is-shared-page';
|
||||||
|
import { useServerBaseUrl } from '../../../../hooks/affine/use-server-config';
|
||||||
import * as styles from './index.css';
|
import * as styles from './index.css';
|
||||||
import type { ShareMenuProps } from './share-menu';
|
import type { ShareMenuProps } from './share-menu';
|
||||||
import { useSharingUrl } from './use-share-url';
|
import { useSharingUrl } from './use-share-url';
|
||||||
@@ -98,6 +99,7 @@ export const AffineSharePage = (props: ShareMenuProps) => {
|
|||||||
pageId,
|
pageId,
|
||||||
urlType: 'share',
|
urlType: 'share',
|
||||||
});
|
});
|
||||||
|
const baseUrl = useServerBaseUrl();
|
||||||
const t = useAFFiNEI18N();
|
const t = useAFFiNEI18N();
|
||||||
|
|
||||||
const onClickCreateLink = useCallback(() => {
|
const onClickCreateLink = useCallback(() => {
|
||||||
@@ -140,9 +142,13 @@ export const AffineSharePage = (props: ShareMenuProps) => {
|
|||||||
lineHeight: '20px',
|
lineHeight: '20px',
|
||||||
}}
|
}}
|
||||||
value={
|
value={
|
||||||
isSharedPage
|
(isSharedPage && sharingUrl) ||
|
||||||
? sharingUrl
|
`${
|
||||||
: `${location.protocol}//${location.hostname}/...`
|
baseUrl ||
|
||||||
|
`${location.protocol}${
|
||||||
|
location.port ? `:${location.port}` : ''
|
||||||
|
}//${location.hostname}`
|
||||||
|
}/...`
|
||||||
}
|
}
|
||||||
readOnly
|
readOnly
|
||||||
/>
|
/>
|
||||||
@@ -151,6 +157,7 @@ export const AffineSharePage = (props: ShareMenuProps) => {
|
|||||||
onClick={onClickCopyLink}
|
onClick={onClickCopyLink}
|
||||||
data-testid="share-menu-copy-link-button"
|
data-testid="share-menu-copy-link-button"
|
||||||
style={{ padding: '4px 12px', whiteSpace: 'nowrap' }}
|
style={{ padding: '4px 12px', whiteSpace: 'nowrap' }}
|
||||||
|
disabled={!sharingUrl}
|
||||||
>
|
>
|
||||||
{t.Copy()}
|
{t.Copy()}
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
+34
-27
@@ -1,4 +1,5 @@
|
|||||||
import { toast } from '@affine/component';
|
import { toast } from '@affine/component';
|
||||||
|
import { useServerBaseUrl } from '@affine/core/hooks/affine/use-server-config';
|
||||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||||
import { useCallback, useMemo } from 'react';
|
import { useCallback, useMemo } from 'react';
|
||||||
|
|
||||||
@@ -10,22 +11,27 @@ type UseSharingUrl = {
|
|||||||
urlType: UrlType;
|
urlType: UrlType;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const generateUrl = ({
|
const useGenerateUrl = ({ workspaceId, pageId, urlType }: UseSharingUrl) => {
|
||||||
workspaceId,
|
// to generate a private url like https://app.affine.app/workspace/123/456
|
||||||
pageId,
|
// to generate a public url like https://app.affine.app/share/123/456
|
||||||
urlType,
|
// or https://app.affine.app/share/123/456?mode=edgeless
|
||||||
}: UseSharingUrl) => {
|
|
||||||
// to generate a private url like https://affine.app/workspace/123/456
|
|
||||||
// to generate a public url like https://affine.app/share/123/456
|
|
||||||
// or https://affine.app/share/123/456?mode=edgeless
|
|
||||||
|
|
||||||
const { protocol, hostname, port } = window.location;
|
const baseUrl = useServerBaseUrl();
|
||||||
const url = new URL(
|
|
||||||
`${protocol}//${hostname}${
|
const url = useMemo(() => {
|
||||||
port ? `:${port}` : ''
|
// baseUrl is null when running in electron and without network
|
||||||
}/${urlType}/${workspaceId}/${pageId}`
|
if (!baseUrl) return null;
|
||||||
);
|
|
||||||
return url.toString();
|
try {
|
||||||
|
return new URL(
|
||||||
|
`${baseUrl}/${urlType}/${workspaceId}/${pageId}`
|
||||||
|
).toString();
|
||||||
|
} catch (e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}, [baseUrl, pageId, urlType, workspaceId]);
|
||||||
|
|
||||||
|
return url;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useSharingUrl = ({
|
export const useSharingUrl = ({
|
||||||
@@ -34,20 +40,21 @@ export const useSharingUrl = ({
|
|||||||
urlType,
|
urlType,
|
||||||
}: UseSharingUrl) => {
|
}: UseSharingUrl) => {
|
||||||
const t = useAFFiNEI18N();
|
const t = useAFFiNEI18N();
|
||||||
const sharingUrl = useMemo(
|
const sharingUrl = useGenerateUrl({ workspaceId, pageId, urlType });
|
||||||
() => generateUrl({ workspaceId, pageId, urlType }),
|
|
||||||
[workspaceId, pageId, urlType]
|
|
||||||
);
|
|
||||||
|
|
||||||
const onClickCopyLink = useCallback(() => {
|
const onClickCopyLink = useCallback(() => {
|
||||||
navigator.clipboard
|
if (sharingUrl) {
|
||||||
.writeText(sharingUrl)
|
navigator.clipboard
|
||||||
.then(() => {
|
.writeText(sharingUrl)
|
||||||
toast(t['Copied link to clipboard']());
|
.then(() => {
|
||||||
})
|
toast(t['Copied link to clipboard']());
|
||||||
.catch(err => {
|
})
|
||||||
console.error(err);
|
.catch(err => {
|
||||||
});
|
console.error(err);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
toast('Network not available');
|
||||||
|
}
|
||||||
}, [sharingUrl, t]);
|
}, [sharingUrl, t]);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
+27
-2
@@ -9,7 +9,7 @@ const errorHandler: Middleware = useSWRNext => (key, fetcher, config) => {
|
|||||||
return useSWRNext(key, wrappedFetcher.bind(null, fetcher), config);
|
return useSWRNext(key, wrappedFetcher.bind(null, fetcher), config);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useServerFlavor = () => {
|
const useServerConfig = () => {
|
||||||
const { data: config, error } = useQueryImmutable(
|
const { data: config, error } = useQueryImmutable(
|
||||||
{ query: serverConfigQuery },
|
{ query: serverConfigQuery },
|
||||||
{
|
{
|
||||||
@@ -18,10 +18,20 @@ export const useServerFlavor = () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (error || !config) {
|
if (error || !config) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return config.serverConfig;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useServerFlavor = () => {
|
||||||
|
const config = useServerConfig();
|
||||||
|
|
||||||
|
if (!config) {
|
||||||
return 'local';
|
return 'local';
|
||||||
}
|
}
|
||||||
|
|
||||||
return config.serverConfig.flavor;
|
return config.flavor;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useSelfHosted = () => {
|
export const useSelfHosted = () => {
|
||||||
@@ -29,3 +39,18 @@ export const useSelfHosted = () => {
|
|||||||
|
|
||||||
return ['local', 'selfhosted'].includes(serverFlavor);
|
return ['local', 'selfhosted'].includes(serverFlavor);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const useServerBaseUrl = () => {
|
||||||
|
const config = useServerConfig();
|
||||||
|
|
||||||
|
if (!config) {
|
||||||
|
if (environment.isDesktop) {
|
||||||
|
// don't use window.location in electron
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const { protocol, hostname, port } = window.location;
|
||||||
|
return `${protocol}//${hostname}${port ? `:${port}` : ''}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return config.baseUrl;
|
||||||
|
};
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
'use client';
|
|
||||||
import { useMemo } from 'react';
|
|
||||||
|
|
||||||
export function useShareLink(workspaceId: string): string {
|
|
||||||
return useMemo(() => {
|
|
||||||
if (environment.isServer) {
|
|
||||||
throw new Error('useShareLink is not available on server side');
|
|
||||||
}
|
|
||||||
if (environment.isDesktop) {
|
|
||||||
return '???';
|
|
||||||
} else {
|
|
||||||
return origin + '/share/' + workspaceId;
|
|
||||||
}
|
|
||||||
}, [workspaceId]);
|
|
||||||
}
|
|
||||||
@@ -2,7 +2,7 @@ import { type SubscriptionQuery, subscriptionQuery } from '@affine/graphql';
|
|||||||
import { useQuery } from '@affine/workspace/affine/gql';
|
import { useQuery } from '@affine/workspace/affine/gql';
|
||||||
import { useAsyncCallback } from '@toeverything/hooks/affine-async-hooks';
|
import { useAsyncCallback } from '@toeverything/hooks/affine-async-hooks';
|
||||||
|
|
||||||
import { useSelfHosted } from './affine/use-server-flavor';
|
import { useSelfHosted } from './affine/use-server-config';
|
||||||
|
|
||||||
export type Subscription = NonNullable<
|
export type Subscription = NonNullable<
|
||||||
NonNullable<SubscriptionQuery['currentUser']>['subscription']
|
NonNullable<SubscriptionQuery['currentUser']>['subscription']
|
||||||
|
|||||||
@@ -655,6 +655,7 @@ query serverConfig {
|
|||||||
serverConfig {
|
serverConfig {
|
||||||
version
|
version
|
||||||
flavor
|
flavor
|
||||||
|
baseUrl
|
||||||
}
|
}
|
||||||
}`,
|
}`,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,5 +2,6 @@ query serverConfig {
|
|||||||
serverConfig {
|
serverConfig {
|
||||||
version
|
version
|
||||||
flavor
|
flavor
|
||||||
|
baseUrl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -632,6 +632,7 @@ export type ServerConfigQuery = {
|
|||||||
__typename?: 'ServerConfigType';
|
__typename?: 'ServerConfigType';
|
||||||
version: string;
|
version: string;
|
||||||
flavor: string;
|
flavor: string;
|
||||||
|
baseUrl: string;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user