mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-12 04:18:54 +00:00
fix: ws prefix url in electron (#1896)
This commit is contained in:
45
.github/workflows/build.yml
vendored
45
.github/workflows/build.yml
vendored
@@ -81,51 +81,6 @@ jobs:
|
|||||||
path: ./apps/web/.next
|
path: ./apps/web/.next
|
||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
|
|
||||||
build-macos:
|
|
||||||
name: Build macOS desktop app
|
|
||||||
runs-on: macos-latest
|
|
||||||
environment: development
|
|
||||||
needs:
|
|
||||||
- build
|
|
||||||
- install-all
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
arch: [arm64]
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- name: Setup Node.js
|
|
||||||
uses: ./.github/actions/setup-node
|
|
||||||
with:
|
|
||||||
electron-workspace-install: true
|
|
||||||
|
|
||||||
- name: Download artifact
|
|
||||||
uses: actions/download-artifact@v3
|
|
||||||
with:
|
|
||||||
name: next-js
|
|
||||||
path: ./apps/web/.next
|
|
||||||
|
|
||||||
- name: install Rust stable
|
|
||||||
uses: dtolnay/rust-toolchain@stable
|
|
||||||
|
|
||||||
- name: add arm64 target
|
|
||||||
if: matrix.arch == 'arm64'
|
|
||||||
run: rustup target add aarch64-apple-darwin
|
|
||||||
|
|
||||||
- name: Rust cache
|
|
||||||
uses: swatinem/rust-cache@v2
|
|
||||||
with:
|
|
||||||
workspaces: './packages/octobase-node -> target'
|
|
||||||
|
|
||||||
- name: make build
|
|
||||||
run: yarn make-macos-${{ matrix.arch }}
|
|
||||||
working-directory: apps/electron
|
|
||||||
|
|
||||||
- name: Upload Artifact
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: affine-darwin-${{ matrix.arch }}-builds
|
|
||||||
path: builds
|
|
||||||
|
|
||||||
storybook-test:
|
storybook-test:
|
||||||
name: Storybook Test
|
name: Storybook Test
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { fetch, ProxyAgent } from 'undici';
|
|||||||
|
|
||||||
const redirectUri = 'https://affine.pro/client/auth-callback';
|
const redirectUri = 'https://affine.pro/client/auth-callback';
|
||||||
|
|
||||||
export const oauthEndpoint = `https://accounts.google.com/o/oauth2/v2/auth?client_id=${process.env.AFFINE_GOOGLE_CLIENT_ID}&redirect_uri=${redirectUri}&response_type=code&scope=openid https://www.googleapis.com/auth/userinfo.email profile&access_type=offline`;
|
export const oauthEndpoint = `https://accounts.google.com/o/oauth2/v2/auth?client_id=${process.env.AFFINE_GOOGLE_CLIENT_ID}&redirect_uri=${redirectUri}&response_type=code&scope=openid https://www.googleapis.com/auth/userinfo.email profile&access_type=offline&customParameters={"prompt":"select_account"}`;
|
||||||
|
|
||||||
const tokenEndpoint = 'https://oauth2.googleapis.com/token';
|
const tokenEndpoint = 'https://oauth2.googleapis.com/token';
|
||||||
|
|
||||||
|
|||||||
@@ -88,5 +88,6 @@ export async function restoreOrCreateWindow() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
browserWindow.focus();
|
browserWindow.focus();
|
||||||
|
|
||||||
return browserWindow;
|
return browserWindow;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { protocol } from 'electron';
|
import { protocol, session } from 'electron';
|
||||||
import { join } from 'path';
|
import { join } from 'path';
|
||||||
|
|
||||||
export function registerProtocol() {
|
export function registerProtocol() {
|
||||||
@@ -20,4 +20,15 @@ export function registerProtocol() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
session.defaultSession.webRequest.onHeadersReceived(
|
||||||
|
(responseDetails, callback) => {
|
||||||
|
const { responseHeaders, url } = responseDetails;
|
||||||
|
if (responseHeaders) {
|
||||||
|
responseHeaders['Access-Control-Allow-Origin'] = ['*'];
|
||||||
|
}
|
||||||
|
|
||||||
|
callback({ responseHeaders });
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ const profileTarget = {
|
|||||||
dev: '100.84.105.99:11001',
|
dev: '100.84.105.99:11001',
|
||||||
test: '100.84.105.99:11001',
|
test: '100.84.105.99:11001',
|
||||||
stage: '',
|
stage: '',
|
||||||
prod: 'http://app.affine.pro',
|
prod: 'https://app.affine.pro',
|
||||||
local: '127.0.0.1:3000',
|
local: '127.0.0.1:3000',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { websocketPrefixUrl } from '@affine/env';
|
||||||
import { KeckProvider } from '@affine/workspace/affine/keck';
|
import { KeckProvider } from '@affine/workspace/affine/keck';
|
||||||
import { getLoginStorage } from '@affine/workspace/affine/login';
|
import { getLoginStorage } from '@affine/workspace/affine/login';
|
||||||
import type { AffineWebSocketProvider } from '@affine/workspace/type';
|
import type { AffineWebSocketProvider } from '@affine/workspace/type';
|
||||||
@@ -19,11 +20,8 @@ const createAffineWebSocketProvider = (
|
|||||||
webSocketProvider = null;
|
webSocketProvider = null;
|
||||||
},
|
},
|
||||||
connect: () => {
|
connect: () => {
|
||||||
const wsUrl = `${
|
|
||||||
window.location.protocol === 'https:' ? 'wss' : 'ws'
|
|
||||||
}://${window.location.host}/api/sync/`;
|
|
||||||
webSocketProvider = new KeckProvider(
|
webSocketProvider = new KeckProvider(
|
||||||
wsUrl,
|
websocketPrefixUrl + '/api/sync/',
|
||||||
blockSuiteWorkspace.id,
|
blockSuiteWorkspace.id,
|
||||||
blockSuiteWorkspace.doc,
|
blockSuiteWorkspace.doc,
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { prefixUrl } from '@affine/env';
|
||||||
import { currentAffineUserAtom } from '@affine/workspace/affine/atom';
|
import { currentAffineUserAtom } from '@affine/workspace/affine/atom';
|
||||||
import {
|
import {
|
||||||
clearLoginStorage,
|
clearLoginStorage,
|
||||||
@@ -24,7 +25,7 @@ import { PageDetailEditor } from '../../components/page-detail-editor';
|
|||||||
import { useAffineRefreshAuthToken } from '../../hooks/affine/use-affine-refresh-auth-token';
|
import { useAffineRefreshAuthToken } from '../../hooks/affine/use-affine-refresh-auth-token';
|
||||||
import { AffineSWRConfigProvider } from '../../providers/AffineSWRConfigProvider';
|
import { AffineSWRConfigProvider } from '../../providers/AffineSWRConfigProvider';
|
||||||
import { BlockSuiteWorkspace } from '../../shared';
|
import { BlockSuiteWorkspace } from '../../shared';
|
||||||
import { affineApis, prefixUrl } from '../../shared/apis';
|
import { affineApis } from '../../shared/apis';
|
||||||
import { initPage, toast } from '../../utils';
|
import { initPage, toast } from '../../utils';
|
||||||
import type { WorkspacePlugin } from '..';
|
import type { WorkspacePlugin } from '..';
|
||||||
import { QueryKey } from './fetcher';
|
import { QueryKey } from './fetcher';
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { DebugLogger } from '@affine/debug';
|
import { DebugLogger } from '@affine/debug';
|
||||||
import { config } from '@affine/env';
|
import { prefixUrl } from '@affine/env';
|
||||||
import {
|
import {
|
||||||
createUserApis,
|
createUserApis,
|
||||||
createWorkspaceApis,
|
createWorkspaceApis,
|
||||||
@@ -9,26 +9,6 @@ import type { LoginResponse } from '@affine/workspace/affine/login';
|
|||||||
import { parseIdToken, setLoginStorage } from '@affine/workspace/affine/login';
|
import { parseIdToken, setLoginStorage } from '@affine/workspace/affine/login';
|
||||||
import { jotaiStore } from '@affine/workspace/atom';
|
import { jotaiStore } from '@affine/workspace/atom';
|
||||||
|
|
||||||
import { isValidIPAddress } from '../utils';
|
|
||||||
|
|
||||||
let prefixUrl = '/';
|
|
||||||
if (typeof window === 'undefined' || environment.isDesktop) {
|
|
||||||
// SSR or Desktop
|
|
||||||
const serverAPI = config.serverAPI;
|
|
||||||
if (isValidIPAddress(serverAPI.split(':')[0])) {
|
|
||||||
// This is for Server side rendering support
|
|
||||||
prefixUrl = new URL('http://' + config.serverAPI + '/').origin;
|
|
||||||
} else {
|
|
||||||
prefixUrl = serverAPI;
|
|
||||||
}
|
|
||||||
prefixUrl = prefixUrl.endsWith('/') ? prefixUrl : prefixUrl + '/';
|
|
||||||
} else {
|
|
||||||
const params = new URLSearchParams(window.location.search);
|
|
||||||
params.get('prefixUrl') && (prefixUrl = params.get('prefixUrl') as string);
|
|
||||||
}
|
|
||||||
|
|
||||||
export { prefixUrl };
|
|
||||||
|
|
||||||
const affineApis = {} as ReturnType<typeof createUserApis> &
|
const affineApis = {} as ReturnType<typeof createUserApis> &
|
||||||
ReturnType<typeof createWorkspaceApis>;
|
ReturnType<typeof createWorkspaceApis>;
|
||||||
Object.assign(affineApis, createUserApis(prefixUrl));
|
Object.assign(affineApis, createUserApis(prefixUrl));
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
export * from './blocksuite';
|
export * from './blocksuite';
|
||||||
export * from './create-emotion-cache';
|
export * from './create-emotion-cache';
|
||||||
export * from './is-valid-ip-address';
|
|
||||||
export * from './string2color';
|
export * from './string2color';
|
||||||
export * from './toast';
|
export * from './toast';
|
||||||
|
|||||||
28
packages/env/src/api.ts
vendored
Normal file
28
packages/env/src/api.ts
vendored
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import { config, getEnvironment } from './config';
|
||||||
|
import { isValidIPAddress } from './is-valid-ip-address';
|
||||||
|
|
||||||
|
let prefixUrl = '/';
|
||||||
|
if (typeof window === 'undefined' || getEnvironment().isDesktop) {
|
||||||
|
// SSR or Desktop
|
||||||
|
const serverAPI = config.serverAPI;
|
||||||
|
if (isValidIPAddress(serverAPI.split(':')[0])) {
|
||||||
|
// This is for Server side rendering support
|
||||||
|
prefixUrl = new URL('http://' + config.serverAPI + '/').origin;
|
||||||
|
} else {
|
||||||
|
prefixUrl = serverAPI;
|
||||||
|
}
|
||||||
|
prefixUrl = prefixUrl.endsWith('/') ? prefixUrl : prefixUrl + '/';
|
||||||
|
} else {
|
||||||
|
const params = new URLSearchParams(window.location.search);
|
||||||
|
if (params.get('prefixUrl')) {
|
||||||
|
prefixUrl = params.get('prefixUrl') as string;
|
||||||
|
} else {
|
||||||
|
prefixUrl = window.location.origin + '/';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const apiUrl = new URL(prefixUrl);
|
||||||
|
const wsProtocol = apiUrl.protocol === 'https:' ? 'wss' : 'ws';
|
||||||
|
const websocketPrefixUrl = `${wsProtocol}://${apiUrl.host}`;
|
||||||
|
|
||||||
|
export { prefixUrl, websocketPrefixUrl };
|
||||||
174
packages/env/src/config.ts
vendored
Normal file
174
packages/env/src/config.ts
vendored
Normal file
@@ -0,0 +1,174 @@
|
|||||||
|
import { assertEquals } from '@blocksuite/global/utils';
|
||||||
|
import getConfig from 'next/config';
|
||||||
|
import { z } from 'zod';
|
||||||
|
|
||||||
|
import { getUaHelper } from './ua-helper';
|
||||||
|
|
||||||
|
export const publicRuntimeConfigSchema = z.object({
|
||||||
|
PROJECT_NAME: z.string(),
|
||||||
|
BUILD_DATE: z.string(),
|
||||||
|
gitVersion: z.string(),
|
||||||
|
hash: z.string(),
|
||||||
|
serverAPI: z.string(),
|
||||||
|
editorVersion: z.string(),
|
||||||
|
enableIndexedDBProvider: z.boolean(),
|
||||||
|
enableBroadCastChannelProvider: z.boolean(),
|
||||||
|
prefetchWorkspace: z.boolean(),
|
||||||
|
enableDebugPage: z.boolean(),
|
||||||
|
// expose internal api to globalThis, **development only**
|
||||||
|
exposeInternal: z.boolean(),
|
||||||
|
enableSubpage: z.boolean(),
|
||||||
|
enableChangeLog: z.boolean(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export type PublicRuntimeConfig = z.infer<typeof publicRuntimeConfigSchema>;
|
||||||
|
|
||||||
|
const { publicRuntimeConfig: config } =
|
||||||
|
getConfig() ??
|
||||||
|
({
|
||||||
|
publicRuntimeConfig: {},
|
||||||
|
} as {
|
||||||
|
publicRuntimeConfig: PublicRuntimeConfig;
|
||||||
|
});
|
||||||
|
|
||||||
|
publicRuntimeConfigSchema.parse(config);
|
||||||
|
|
||||||
|
type BrowserBase = {
|
||||||
|
/**
|
||||||
|
* @example https://app.affine.pro
|
||||||
|
* @example http://localhost:3000
|
||||||
|
*/
|
||||||
|
origin: string;
|
||||||
|
isDesktop: boolean;
|
||||||
|
isBrowser: true;
|
||||||
|
isServer: false;
|
||||||
|
isDebug: boolean;
|
||||||
|
|
||||||
|
// browser special properties
|
||||||
|
isLinux: boolean;
|
||||||
|
isMacOs: boolean;
|
||||||
|
isIOS: boolean;
|
||||||
|
isSafari: boolean;
|
||||||
|
isWindows: boolean;
|
||||||
|
isFireFox: boolean;
|
||||||
|
isMobile: boolean;
|
||||||
|
isChrome: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
type NonChromeBrowser = BrowserBase & {
|
||||||
|
isChrome: false;
|
||||||
|
};
|
||||||
|
|
||||||
|
type ChromeBrowser = BrowserBase & {
|
||||||
|
isSafari: false;
|
||||||
|
isFireFox: false;
|
||||||
|
isChrome: true;
|
||||||
|
chromeVersion: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
type Browser = NonChromeBrowser | ChromeBrowser;
|
||||||
|
|
||||||
|
type Server = {
|
||||||
|
isDesktop: false;
|
||||||
|
isBrowser: false;
|
||||||
|
isServer: true;
|
||||||
|
isDebug: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
interface Desktop extends ChromeBrowser {
|
||||||
|
isDesktop: true;
|
||||||
|
isBrowser: true;
|
||||||
|
isServer: false;
|
||||||
|
isDebug: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type Environment = Browser | Server | Desktop;
|
||||||
|
|
||||||
|
let environment: Environment | null = null;
|
||||||
|
|
||||||
|
export function getEnvironment() {
|
||||||
|
if (environment) {
|
||||||
|
return environment;
|
||||||
|
}
|
||||||
|
const isDebug = process.env.NODE_ENV === 'development';
|
||||||
|
if (typeof window === 'undefined') {
|
||||||
|
environment = {
|
||||||
|
isDesktop: false,
|
||||||
|
isBrowser: false,
|
||||||
|
isServer: true,
|
||||||
|
isDebug,
|
||||||
|
} satisfies Server;
|
||||||
|
} else {
|
||||||
|
const uaHelper = getUaHelper();
|
||||||
|
|
||||||
|
environment = {
|
||||||
|
origin: window.location.origin,
|
||||||
|
isDesktop: window.appInfo?.electron,
|
||||||
|
isBrowser: true,
|
||||||
|
isServer: false,
|
||||||
|
isDebug,
|
||||||
|
isLinux: uaHelper.isLinux,
|
||||||
|
isMacOs: uaHelper.isMacOs,
|
||||||
|
isSafari: uaHelper.isSafari,
|
||||||
|
isWindows: uaHelper.isWindows,
|
||||||
|
isFireFox: uaHelper.isFireFox,
|
||||||
|
isMobile: uaHelper.isMobile,
|
||||||
|
isChrome: uaHelper.isChrome,
|
||||||
|
isIOS: uaHelper.isIOS,
|
||||||
|
} as Browser;
|
||||||
|
// Chrome on iOS is still Safari
|
||||||
|
if (environment.isChrome && !environment.isIOS) {
|
||||||
|
assertEquals(environment.isSafari, false);
|
||||||
|
assertEquals(environment.isFireFox, false);
|
||||||
|
environment = {
|
||||||
|
...environment,
|
||||||
|
isSafari: false,
|
||||||
|
isFireFox: false,
|
||||||
|
isChrome: true,
|
||||||
|
chromeVersion: uaHelper.getChromeVersion(),
|
||||||
|
} satisfies ChromeBrowser;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
globalThis.environment = environment;
|
||||||
|
return environment;
|
||||||
|
}
|
||||||
|
|
||||||
|
function printBuildInfo() {
|
||||||
|
console.group('Build info');
|
||||||
|
console.log('Project:', config.PROJECT_NAME);
|
||||||
|
console.log(
|
||||||
|
'Build date:',
|
||||||
|
config.BUILD_DATE ? new Date(config.BUILD_DATE).toLocaleString() : 'Unknown'
|
||||||
|
);
|
||||||
|
console.log('Editor Version:', config.editorVersion);
|
||||||
|
|
||||||
|
console.log('Version:', config.gitVersion);
|
||||||
|
console.log(
|
||||||
|
'AFFiNE is an open source project, you can view its source code on GitHub!'
|
||||||
|
);
|
||||||
|
console.log(`https://github.com/toeverything/AFFiNE/tree/${config.hash}`);
|
||||||
|
console.groupEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
// eslint-disable-next-line no-var
|
||||||
|
var environment: Environment;
|
||||||
|
// eslint-disable-next-line no-var
|
||||||
|
var $AFFINE_SETUP: boolean | undefined;
|
||||||
|
// eslint-disable-next-line no-var
|
||||||
|
var editorVersion: string | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setupGlobal() {
|
||||||
|
if (globalThis.$AFFINE_SETUP) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
globalThis.environment = getEnvironment();
|
||||||
|
if (getEnvironment().isBrowser) {
|
||||||
|
printBuildInfo();
|
||||||
|
globalThis.editorVersion = config.editorVersion;
|
||||||
|
}
|
||||||
|
globalThis.$AFFINE_SETUP = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
export { config };
|
||||||
176
packages/env/src/index.ts
vendored
176
packages/env/src/index.ts
vendored
@@ -1,175 +1,3 @@
|
|||||||
import { assertEquals } from '@blocksuite/global/utils';
|
export * from './api';
|
||||||
import getConfig from 'next/config';
|
export * from './config';
|
||||||
import { z } from 'zod';
|
|
||||||
|
|
||||||
import { getUaHelper } from './ua-helper';
|
|
||||||
|
|
||||||
export const publicRuntimeConfigSchema = z.object({
|
|
||||||
PROJECT_NAME: z.string(),
|
|
||||||
BUILD_DATE: z.string(),
|
|
||||||
gitVersion: z.string(),
|
|
||||||
hash: z.string(),
|
|
||||||
serverAPI: z.string(),
|
|
||||||
editorVersion: z.string(),
|
|
||||||
enableIndexedDBProvider: z.boolean(),
|
|
||||||
enableBroadCastChannelProvider: z.boolean(),
|
|
||||||
prefetchWorkspace: z.boolean(),
|
|
||||||
enableDebugPage: z.boolean(),
|
|
||||||
// expose internal api to globalThis, **development only**
|
|
||||||
exposeInternal: z.boolean(),
|
|
||||||
enableSubpage: z.boolean(),
|
|
||||||
enableChangeLog: z.boolean(),
|
|
||||||
});
|
|
||||||
|
|
||||||
export type PublicRuntimeConfig = z.infer<typeof publicRuntimeConfigSchema>;
|
|
||||||
|
|
||||||
const { publicRuntimeConfig: config } =
|
|
||||||
getConfig() ??
|
|
||||||
({
|
|
||||||
publicRuntimeConfig: {},
|
|
||||||
} as {
|
|
||||||
publicRuntimeConfig: PublicRuntimeConfig;
|
|
||||||
});
|
|
||||||
|
|
||||||
publicRuntimeConfigSchema.parse(config);
|
|
||||||
|
|
||||||
type BrowserBase = {
|
|
||||||
/**
|
|
||||||
* @example https://app.affine.pro
|
|
||||||
* @example http://localhost:3000
|
|
||||||
*/
|
|
||||||
origin: string;
|
|
||||||
isDesktop: boolean;
|
|
||||||
isBrowser: true;
|
|
||||||
isServer: false;
|
|
||||||
isDebug: boolean;
|
|
||||||
|
|
||||||
// browser special properties
|
|
||||||
isLinux: boolean;
|
|
||||||
isMacOs: boolean;
|
|
||||||
isIOS: boolean;
|
|
||||||
isSafari: boolean;
|
|
||||||
isWindows: boolean;
|
|
||||||
isFireFox: boolean;
|
|
||||||
isMobile: boolean;
|
|
||||||
isChrome: boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
type NonChromeBrowser = BrowserBase & {
|
|
||||||
isChrome: false;
|
|
||||||
};
|
|
||||||
|
|
||||||
type ChromeBrowser = BrowserBase & {
|
|
||||||
isSafari: false;
|
|
||||||
isFireFox: false;
|
|
||||||
isChrome: true;
|
|
||||||
chromeVersion: number;
|
|
||||||
};
|
|
||||||
|
|
||||||
type Browser = NonChromeBrowser | ChromeBrowser;
|
|
||||||
|
|
||||||
type Server = {
|
|
||||||
isDesktop: false;
|
|
||||||
isBrowser: false;
|
|
||||||
isServer: true;
|
|
||||||
isDebug: boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
interface Desktop extends ChromeBrowser {
|
|
||||||
isDesktop: true;
|
|
||||||
isBrowser: true;
|
|
||||||
isServer: false;
|
|
||||||
isDebug: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type Environment = Browser | Server | Desktop;
|
|
||||||
|
|
||||||
let environment: Environment | null = null;
|
|
||||||
|
|
||||||
export function getEnvironment() {
|
|
||||||
if (environment) {
|
|
||||||
return environment;
|
|
||||||
}
|
|
||||||
const isDebug = process.env.NODE_ENV === 'development';
|
|
||||||
if (typeof window === 'undefined') {
|
|
||||||
environment = {
|
|
||||||
isDesktop: false,
|
|
||||||
isBrowser: false,
|
|
||||||
isServer: true,
|
|
||||||
isDebug,
|
|
||||||
} satisfies Server;
|
|
||||||
} else {
|
|
||||||
const uaHelper = getUaHelper();
|
|
||||||
|
|
||||||
environment = {
|
|
||||||
origin: window.location.origin,
|
|
||||||
isDesktop: window.appInfo?.electron,
|
|
||||||
isBrowser: true,
|
|
||||||
isServer: false,
|
|
||||||
isDebug,
|
|
||||||
isLinux: uaHelper.isLinux,
|
|
||||||
isMacOs: uaHelper.isMacOs,
|
|
||||||
isSafari: uaHelper.isSafari,
|
|
||||||
isWindows: uaHelper.isWindows,
|
|
||||||
isFireFox: uaHelper.isFireFox,
|
|
||||||
isMobile: uaHelper.isMobile,
|
|
||||||
isChrome: uaHelper.isChrome,
|
|
||||||
isIOS: uaHelper.isIOS,
|
|
||||||
} as Browser;
|
|
||||||
// Chrome on iOS is still Safari
|
|
||||||
if (environment.isChrome && !environment.isIOS) {
|
|
||||||
assertEquals(environment.isSafari, false);
|
|
||||||
assertEquals(environment.isFireFox, false);
|
|
||||||
environment = {
|
|
||||||
...environment,
|
|
||||||
isSafari: false,
|
|
||||||
isFireFox: false,
|
|
||||||
isChrome: true,
|
|
||||||
chromeVersion: uaHelper.getChromeVersion(),
|
|
||||||
} satisfies ChromeBrowser;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
globalThis.environment = environment;
|
|
||||||
return environment;
|
|
||||||
}
|
|
||||||
|
|
||||||
function printBuildInfo() {
|
|
||||||
console.group('Build info');
|
|
||||||
console.log('Project:', config.PROJECT_NAME);
|
|
||||||
console.log(
|
|
||||||
'Build date:',
|
|
||||||
config.BUILD_DATE ? new Date(config.BUILD_DATE).toLocaleString() : 'Unknown'
|
|
||||||
);
|
|
||||||
console.log('Editor Version:', config.editorVersion);
|
|
||||||
|
|
||||||
console.log('Version:', config.gitVersion);
|
|
||||||
console.log(
|
|
||||||
'AFFiNE is an open source project, you can view its source code on GitHub!'
|
|
||||||
);
|
|
||||||
console.log(`https://github.com/toeverything/AFFiNE/tree/${config.hash}`);
|
|
||||||
console.groupEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
declare global {
|
|
||||||
// eslint-disable-next-line no-var
|
|
||||||
var environment: Environment;
|
|
||||||
// eslint-disable-next-line no-var
|
|
||||||
var $AFFINE_SETUP: boolean | undefined;
|
|
||||||
// eslint-disable-next-line no-var
|
|
||||||
var editorVersion: string | undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function setupGlobal() {
|
|
||||||
if (globalThis.$AFFINE_SETUP) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
globalThis.environment = getEnvironment();
|
|
||||||
if (getEnvironment().isBrowser) {
|
|
||||||
printBuildInfo();
|
|
||||||
globalThis.editorVersion = config.editorVersion;
|
|
||||||
}
|
|
||||||
globalThis.$AFFINE_SETUP = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
export { config };
|
|
||||||
export * from './constant';
|
export * from './constant';
|
||||||
|
|||||||
@@ -167,9 +167,16 @@ export function createAffineAuth(prefix = '/') {
|
|||||||
}
|
}
|
||||||
let provider: AuthProvider;
|
let provider: AuthProvider;
|
||||||
switch (method) {
|
switch (method) {
|
||||||
case SignMethod.Google:
|
case SignMethod.Google: {
|
||||||
provider = new GoogleAuthProvider();
|
const googleProvider = new GoogleAuthProvider();
|
||||||
|
// make sure the user has a chance to select an account
|
||||||
|
// https://developers.google.com/identity/openid-connect/openid-connect#prompt
|
||||||
|
googleProvider.setCustomParameters({
|
||||||
|
prompt: 'select_account',
|
||||||
|
});
|
||||||
|
provider = googleProvider;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case SignMethod.GitHub:
|
case SignMethod.GitHub:
|
||||||
provider = new GithubAuthProvider();
|
provider = new GithubAuthProvider();
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { DebugLogger } from '@affine/debug';
|
import { DebugLogger } from '@affine/debug';
|
||||||
|
import { websocketPrefixUrl } from '@affine/env/api';
|
||||||
import {
|
import {
|
||||||
workspaceDetailSchema,
|
workspaceDetailSchema,
|
||||||
workspaceSchema,
|
workspaceSchema,
|
||||||
@@ -61,11 +62,7 @@ export function createAffineGlobalChannel(
|
|||||||
let dispose: Disposable | undefined = undefined;
|
let dispose: Disposable | undefined = undefined;
|
||||||
const apis = {
|
const apis = {
|
||||||
connect: () => {
|
connect: () => {
|
||||||
client = new WebsocketClient(
|
client = new WebsocketClient(websocketPrefixUrl + '/api/global/sync/');
|
||||||
`${window.location.protocol === 'https:' ? 'wss' : 'ws'}://${
|
|
||||||
window.location.host
|
|
||||||
}/api/global/sync`
|
|
||||||
);
|
|
||||||
client.connect(handleMessage);
|
client.connect(handleMessage);
|
||||||
dispose = storageChangeSlot.on(() => {
|
dispose = storageChangeSlot.on(() => {
|
||||||
apis.disconnect();
|
apis.disconnect();
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { config } from '@affine/env';
|
import { config, websocketPrefixUrl } from '@affine/env';
|
||||||
import { KeckProvider } from '@affine/workspace/affine/keck';
|
import { KeckProvider } from '@affine/workspace/affine/keck';
|
||||||
import {
|
import {
|
||||||
getLoginStorage,
|
getLoginStorage,
|
||||||
@@ -41,11 +41,8 @@ const createAffineWebSocketProvider = (
|
|||||||
apis.disconnect();
|
apis.disconnect();
|
||||||
apis.connect();
|
apis.connect();
|
||||||
});
|
});
|
||||||
const wsUrl = `${
|
|
||||||
window.location.protocol === 'https:' ? 'wss' : 'ws'
|
|
||||||
}://${window.location.host}/api/sync/`;
|
|
||||||
webSocketProvider = new KeckProvider(
|
webSocketProvider = new KeckProvider(
|
||||||
wsUrl,
|
websocketPrefixUrl + '/api/sync/',
|
||||||
blockSuiteWorkspace.id,
|
blockSuiteWorkspace.id,
|
||||||
blockSuiteWorkspace.doc,
|
blockSuiteWorkspace.doc,
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user