diff --git a/packages/backend/server/src/modules/config.ts b/packages/backend/server/src/modules/config.ts
index 5d9b05e790..7ebd5b5a4c 100644
--- a/packages/backend/server/src/modules/config.ts
+++ b/packages/backend/server/src/modules/config.ts
@@ -10,6 +10,9 @@ export class ServerConfigType {
@Field({ description: 'server flavor' })
flavor!: string;
+
+ @Field({ description: 'server base url' })
+ baseUrl!: string;
}
export class ServerConfigResolver {
@@ -20,6 +23,7 @@ export class ServerConfigResolver {
return {
version: AFFiNE.version,
flavor: SERVER_FLAVOR,
+ baseUrl: AFFiNE.baseUrl,
};
}
}
diff --git a/packages/backend/server/src/schema.gql b/packages/backend/server/src/schema.gql
index 6707d700df..e7a348b317 100644
--- a/packages/backend/server/src/schema.gql
+++ b/packages/backend/server/src/schema.gql
@@ -8,6 +8,9 @@ type ServerConfigType {
"""server flavor"""
flavor: String!
+
+ """server base url"""
+ baseUrl: String!
}
type UserQuotaHumanReadable {
diff --git a/packages/frontend/core/.webpack/config.ts b/packages/frontend/core/.webpack/config.ts
index 228180d684..438e71ea8c 100644
--- a/packages/frontend/core/.webpack/config.ts
+++ b/packages/frontend/core/.webpack/config.ts
@@ -391,7 +391,6 @@ export const createConfiguration: (
proxy: {
'/api/worker/': {
target: 'https://affine-worker.toeverything.workers.dev',
- pathRewrite: { '^/api/worker/': '/api/' },
changeOrigin: true,
secure: false,
},
diff --git a/packages/frontend/core/.webpack/runtime-config.ts b/packages/frontend/core/.webpack/runtime-config.ts
index c899a40a90..6faf651feb 100644
--- a/packages/frontend/core/.webpack/runtime-config.ts
+++ b/packages/frontend/core/.webpack/runtime-config.ts
@@ -33,7 +33,7 @@ export function getRuntimeConfig(buildFlags: BuildFlags): RuntimeConfig {
enablePayment: true,
enablePageHistory: false,
enableCopilot: false,
- serverUrlPrefix: 'https://insider.affine.pro', // Let insider be stable environment temporarily.
+ serverUrlPrefix: 'https://app.affine.pro',
editorFlags,
appVersion: packageJson.version,
editorVersion: packageJson.dependencies['@blocksuite/presets'],
diff --git a/packages/frontend/core/src/components/affine/new-workspace-setting-detail/index.tsx b/packages/frontend/core/src/components/affine/new-workspace-setting-detail/index.tsx
index 24ea8c997c..6a1acc2299 100644
--- a/packages/frontend/core/src/components/affine/new-workspace-setting-detail/index.tsx
+++ b/packages/frontend/core/src/components/affine/new-workspace-setting-detail/index.tsx
@@ -8,7 +8,7 @@ import { useAFFiNEI18N } from '@affine/i18n/hooks';
import { useWorkspace } from '@toeverything/hooks/use-workspace';
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 { EnableCloudPanel } from './enable-cloud';
import { ExportPanel } from './export';
diff --git a/packages/frontend/core/src/components/affine/setting-modal/account-setting/index.tsx b/packages/frontend/core/src/components/affine/setting-modal/account-setting/index.tsx
index 1bfd2d714d..49f5b88fcc 100644
--- a/packages/frontend/core/src/components/affine/setting-modal/account-setting/index.tsx
+++ b/packages/frontend/core/src/components/affine/setting-modal/account-setting/index.tsx
@@ -34,7 +34,7 @@ import {
openSignOutModalAtom,
} from '../../../../atoms';
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 { validateAndReduceImage } from '../../../../utils/reduce-image';
import { Upload } from '../../../pure/file-upload';
diff --git a/packages/frontend/core/src/components/affine/setting-modal/general-setting/index.tsx b/packages/frontend/core/src/components/affine/setting-modal/general-setting/index.tsx
index 2f63a3b1a4..31e344396f 100644
--- a/packages/frontend/core/src/components/affine/setting-modal/general-setting/index.tsx
+++ b/packages/frontend/core/src/components/affine/setting-modal/general-setting/index.tsx
@@ -8,7 +8,7 @@ import {
import type { ReactElement, SVGProps } from 'react';
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 { AppearanceSettings } from './appearance';
import { BillingSettings } from './billing';
diff --git a/packages/frontend/core/src/components/affine/share-page-modal/share-menu/share-export.tsx b/packages/frontend/core/src/components/affine/share-page-modal/share-menu/share-export.tsx
index 6ce92be6cd..f30b059819 100644
--- a/packages/frontend/core/src/components/affine/share-page-modal/share-menu/share-export.tsx
+++ b/packages/frontend/core/src/components/affine/share-page-modal/share-menu/share-export.tsx
@@ -19,7 +19,7 @@ export const ShareExport = ({
const t = useAFFiNEI18N();
const workspaceId = workspace.id;
const pageId = currentPage.id;
- const { onClickCopyLink } = useSharingUrl({
+ const { sharingUrl, onClickCopyLink } = useSharingUrl({
workspaceId,
pageId,
urlType: 'workspace',
@@ -57,6 +57,7 @@ export const ShareExport = ({
onClick={onClickCopyLink}
icon={}
type="plain"
+ disabled={!sharingUrl}
>
{t['com.affine.share-menu.copy-private-link']()}
diff --git a/packages/frontend/core/src/components/affine/share-page-modal/share-menu/share-page.tsx b/packages/frontend/core/src/components/affine/share-page-modal/share-menu/share-page.tsx
index 282685330d..db286f45eb 100644
--- a/packages/frontend/core/src/components/affine/share-page-modal/share-menu/share-page.tsx
+++ b/packages/frontend/core/src/components/affine/share-page-modal/share-menu/share-page.tsx
@@ -18,6 +18,7 @@ import { useCallback } from 'react';
import type { PageMode } from '../../../../atoms';
import { currentModeAtom } from '../../../../atoms/mode';
import { useIsSharedPage } from '../../../../hooks/affine/use-is-shared-page';
+import { useServerBaseUrl } from '../../../../hooks/affine/use-server-config';
import * as styles from './index.css';
import type { ShareMenuProps } from './share-menu';
import { useSharingUrl } from './use-share-url';
@@ -98,6 +99,7 @@ export const AffineSharePage = (props: ShareMenuProps) => {
pageId,
urlType: 'share',
});
+ const baseUrl = useServerBaseUrl();
const t = useAFFiNEI18N();
const onClickCreateLink = useCallback(() => {
@@ -140,9 +142,13 @@ export const AffineSharePage = (props: ShareMenuProps) => {
lineHeight: '20px',
}}
value={
- isSharedPage
- ? sharingUrl
- : `${location.protocol}//${location.hostname}/...`
+ (isSharedPage && sharingUrl) ||
+ `${
+ baseUrl ||
+ `${location.protocol}${
+ location.port ? `:${location.port}` : ''
+ }//${location.hostname}`
+ }/...`
}
readOnly
/>
@@ -151,6 +157,7 @@ export const AffineSharePage = (props: ShareMenuProps) => {
onClick={onClickCopyLink}
data-testid="share-menu-copy-link-button"
style={{ padding: '4px 12px', whiteSpace: 'nowrap' }}
+ disabled={!sharingUrl}
>
{t.Copy()}
diff --git a/packages/frontend/core/src/components/affine/share-page-modal/share-menu/use-share-url.ts b/packages/frontend/core/src/components/affine/share-page-modal/share-menu/use-share-url.ts
index c2f6772bc0..dc5328a74e 100644
--- a/packages/frontend/core/src/components/affine/share-page-modal/share-menu/use-share-url.ts
+++ b/packages/frontend/core/src/components/affine/share-page-modal/share-menu/use-share-url.ts
@@ -1,4 +1,5 @@
import { toast } from '@affine/component';
+import { useServerBaseUrl } from '@affine/core/hooks/affine/use-server-config';
import { useAFFiNEI18N } from '@affine/i18n/hooks';
import { useCallback, useMemo } from 'react';
@@ -10,22 +11,27 @@ type UseSharingUrl = {
urlType: UrlType;
};
-export const generateUrl = ({
- workspaceId,
- pageId,
- urlType,
-}: 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 useGenerateUrl = ({ workspaceId, pageId, urlType }: UseSharingUrl) => {
+ // to generate a private url like https://app.affine.app/workspace/123/456
+ // to generate a public url like https://app.affine.app/share/123/456
+ // or https://app.affine.app/share/123/456?mode=edgeless
- const { protocol, hostname, port } = window.location;
- const url = new URL(
- `${protocol}//${hostname}${
- port ? `:${port}` : ''
- }/${urlType}/${workspaceId}/${pageId}`
- );
- return url.toString();
+ const baseUrl = useServerBaseUrl();
+
+ const url = useMemo(() => {
+ // baseUrl is null when running in electron and without network
+ if (!baseUrl) return null;
+
+ try {
+ return new URL(
+ `${baseUrl}/${urlType}/${workspaceId}/${pageId}`
+ ).toString();
+ } catch (e) {
+ return null;
+ }
+ }, [baseUrl, pageId, urlType, workspaceId]);
+
+ return url;
};
export const useSharingUrl = ({
@@ -34,20 +40,21 @@ export const useSharingUrl = ({
urlType,
}: UseSharingUrl) => {
const t = useAFFiNEI18N();
- const sharingUrl = useMemo(
- () => generateUrl({ workspaceId, pageId, urlType }),
- [workspaceId, pageId, urlType]
- );
+ const sharingUrl = useGenerateUrl({ workspaceId, pageId, urlType });
const onClickCopyLink = useCallback(() => {
- navigator.clipboard
- .writeText(sharingUrl)
- .then(() => {
- toast(t['Copied link to clipboard']());
- })
- .catch(err => {
- console.error(err);
- });
+ if (sharingUrl) {
+ navigator.clipboard
+ .writeText(sharingUrl)
+ .then(() => {
+ toast(t['Copied link to clipboard']());
+ })
+ .catch(err => {
+ console.error(err);
+ });
+ } else {
+ toast('Network not available');
+ }
}, [sharingUrl, t]);
return {
diff --git a/packages/frontend/core/src/hooks/affine/use-server-flavor.ts b/packages/frontend/core/src/hooks/affine/use-server-config.ts
similarity index 60%
rename from packages/frontend/core/src/hooks/affine/use-server-flavor.ts
rename to packages/frontend/core/src/hooks/affine/use-server-config.ts
index 25a4be6535..89f84b336c 100644
--- a/packages/frontend/core/src/hooks/affine/use-server-flavor.ts
+++ b/packages/frontend/core/src/hooks/affine/use-server-config.ts
@@ -9,7 +9,7 @@ const errorHandler: Middleware = useSWRNext => (key, fetcher, config) => {
return useSWRNext(key, wrappedFetcher.bind(null, fetcher), config);
};
-export const useServerFlavor = () => {
+const useServerConfig = () => {
const { data: config, error } = useQueryImmutable(
{ query: serverConfigQuery },
{
@@ -18,10 +18,20 @@ export const useServerFlavor = () => {
);
if (error || !config) {
+ return null;
+ }
+
+ return config.serverConfig;
+};
+
+export const useServerFlavor = () => {
+ const config = useServerConfig();
+
+ if (!config) {
return 'local';
}
- return config.serverConfig.flavor;
+ return config.flavor;
};
export const useSelfHosted = () => {
@@ -29,3 +39,18 @@ export const useSelfHosted = () => {
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;
+};
diff --git a/packages/frontend/core/src/hooks/affine/use-share-link.ts b/packages/frontend/core/src/hooks/affine/use-share-link.ts
deleted file mode 100644
index 58e4fb37b9..0000000000
--- a/packages/frontend/core/src/hooks/affine/use-share-link.ts
+++ /dev/null
@@ -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]);
-}
diff --git a/packages/frontend/core/src/hooks/use-subscription.ts b/packages/frontend/core/src/hooks/use-subscription.ts
index 9ec556cb79..f7095033ea 100644
--- a/packages/frontend/core/src/hooks/use-subscription.ts
+++ b/packages/frontend/core/src/hooks/use-subscription.ts
@@ -2,7 +2,7 @@ import { type SubscriptionQuery, subscriptionQuery } from '@affine/graphql';
import { useQuery } from '@affine/workspace/affine/gql';
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<
NonNullable['subscription']
diff --git a/packages/frontend/graphql/src/graphql/index.ts b/packages/frontend/graphql/src/graphql/index.ts
index 5d2e01f89d..9178e0f355 100644
--- a/packages/frontend/graphql/src/graphql/index.ts
+++ b/packages/frontend/graphql/src/graphql/index.ts
@@ -655,6 +655,7 @@ query serverConfig {
serverConfig {
version
flavor
+ baseUrl
}
}`,
};
diff --git a/packages/frontend/graphql/src/graphql/server-config.gql b/packages/frontend/graphql/src/graphql/server-config.gql
index 6f7a99a477..b18c3a8e96 100644
--- a/packages/frontend/graphql/src/graphql/server-config.gql
+++ b/packages/frontend/graphql/src/graphql/server-config.gql
@@ -2,5 +2,6 @@ query serverConfig {
serverConfig {
version
flavor
+ baseUrl
}
}
diff --git a/packages/frontend/graphql/src/schema.ts b/packages/frontend/graphql/src/schema.ts
index cc7c293213..7f55ef17ff 100644
--- a/packages/frontend/graphql/src/schema.ts
+++ b/packages/frontend/graphql/src/schema.ts
@@ -632,6 +632,7 @@ export type ServerConfigQuery = {
__typename?: 'ServerConfigType';
version: string;
flavor: string;
+ baseUrl: string;
};
};