mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-11 20:08:37 +00:00
fix(server): blank screen on mobile (#8460)
Co-authored-by: forehalo <forehalo@gmail.com>
This commit is contained in:
@@ -24,6 +24,10 @@ export async function createApp() {
|
||||
logger: AFFiNE.affine.stable ? ['log'] : ['verbose'],
|
||||
});
|
||||
|
||||
if (AFFiNE.server.path) {
|
||||
app.setGlobalPrefix(AFFiNE.server.path);
|
||||
}
|
||||
|
||||
app.use(serverTimingAndCache);
|
||||
|
||||
app.use(
|
||||
|
||||
@@ -18,7 +18,6 @@ interface RenderOptions {
|
||||
}
|
||||
|
||||
interface HtmlAssets {
|
||||
html: string;
|
||||
css: string[];
|
||||
js: string[];
|
||||
publicPath: string;
|
||||
@@ -27,7 +26,6 @@ interface HtmlAssets {
|
||||
}
|
||||
|
||||
const defaultAssets: HtmlAssets = {
|
||||
html: '',
|
||||
css: [],
|
||||
js: [],
|
||||
publicPath: '/',
|
||||
@@ -152,9 +150,15 @@ export class DocRendererController {
|
||||
return null;
|
||||
}
|
||||
|
||||
// @TODO(@forehalo): pre-compile html template to accelerate serializing
|
||||
_render(opts: RenderOptions | null, assets: HtmlAssets): string {
|
||||
if (!opts && assets.html) {
|
||||
return assets.html;
|
||||
// TODO(@forehalo): how can we enable the type reference to @affine/env
|
||||
const env: Record<string, any> = {
|
||||
publicPath: assets.publicPath,
|
||||
};
|
||||
|
||||
if (this.config.isSelfhosted) {
|
||||
env.isSelfHosted = true;
|
||||
}
|
||||
|
||||
const title = opts?.title
|
||||
@@ -182,7 +186,7 @@ export class DocRendererController {
|
||||
|
||||
<title>${title}</title>
|
||||
<meta name="theme-color" content="#fafafa" />
|
||||
<link rel="preconnect" href="${assets.publicPath}">
|
||||
${assets.publicPath.startsWith('/') ? '' : `<link rel="preconnect" href="${assets.publicPath}">`}
|
||||
<link rel="manifest" href="/manifest.json" />
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
|
||||
<link rel="icon" sizes="192x192" href="/favicon-192.png" />
|
||||
@@ -199,6 +203,10 @@ export class DocRendererController {
|
||||
<meta property="og:title" content="${title}" />
|
||||
<meta property="og:description" content="${summary}" />
|
||||
<meta property="og:image" content="${image}" />
|
||||
<meta name="renderer" content="ssr" />
|
||||
${Object.entries(env)
|
||||
.map(([key, val]) => `<meta name="env:${key}" content="${val}" />`)
|
||||
.join('\n')}
|
||||
${assets.css.map(url => `<link rel="stylesheet" href="${url}" />`).join('\n')}
|
||||
</head>
|
||||
<body>
|
||||
@@ -214,11 +222,20 @@ export class DocRendererController {
|
||||
*/
|
||||
private readHtmlAssets(path: string): HtmlAssets {
|
||||
const manifestPath = join(path, 'assets-manifest.json');
|
||||
const htmlPath = join(path, 'index.html');
|
||||
|
||||
try {
|
||||
const assets = JSON.parse(readFileSync(manifestPath, 'utf-8'));
|
||||
assets.html = readFileSync(htmlPath, 'utf-8');
|
||||
const assets: HtmlAssets = JSON.parse(
|
||||
readFileSync(manifestPath, 'utf-8')
|
||||
);
|
||||
|
||||
const publicPath = this.config.isSelfhosted
|
||||
? this.config.server.host + '/'
|
||||
: assets.publicPath;
|
||||
|
||||
assets.publicPath = publicPath;
|
||||
assets.js = assets.js.map(path => publicPath + path);
|
||||
assets.css = assets.css.map(path => publicPath + path);
|
||||
|
||||
return assets;
|
||||
} catch (e) {
|
||||
if (this.config.node.prod) {
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
import { HttpAdapterHost } from '@nestjs/core';
|
||||
import type { Application, Request, Response } from 'express';
|
||||
import { static as serveStatic } from 'express';
|
||||
import isMobile from 'is-mobile';
|
||||
|
||||
import { Config } from '../../fundamentals';
|
||||
import { AuthModule } from '../auth';
|
||||
@@ -58,50 +59,106 @@ export class SelfhostModule implements OnModuleInit {
|
||||
) {}
|
||||
|
||||
onModuleInit() {
|
||||
// selfhost static file location
|
||||
// web => 'static/selfhost'
|
||||
// admin => 'static/admin/selfhost'
|
||||
// mobile => 'static/mobile/selfhost'
|
||||
const staticPath = join(this.config.projectRoot, 'static');
|
||||
// in command line mode
|
||||
if (!this.adapterHost.httpAdapter) {
|
||||
return;
|
||||
}
|
||||
|
||||
const app = this.adapterHost.httpAdapter.getInstance<Application>();
|
||||
// for example, '/affine' in host [//host.com/affine]
|
||||
const basePath = this.config.server.path;
|
||||
const staticPath = join(this.config.projectRoot, 'static');
|
||||
|
||||
// web => {
|
||||
// affine: 'static/index.html',
|
||||
// selfhost: 'static/selfhost.html'
|
||||
// }
|
||||
// admin => {
|
||||
// affine: 'static/admin/index.html',
|
||||
// selfhost: 'static/admin/selfhost.html'
|
||||
// }
|
||||
// mobile => {
|
||||
// affine: 'static/mobile/index.html',
|
||||
// selfhost: 'static/mobile/selfhost.html'
|
||||
// }
|
||||
// NOTE(@forehalo):
|
||||
// the order following routes should be respected,
|
||||
// otherwise the app won't work properly.
|
||||
|
||||
// START REGION: /admin
|
||||
// do not allow '/index.html' url, redirect to '/'
|
||||
app.get(basePath + '/admin/index.html', (_req, res) => {
|
||||
res.redirect(basePath + '/admin');
|
||||
return res.redirect(basePath + '/admin');
|
||||
});
|
||||
|
||||
// serve all static files
|
||||
app.use(
|
||||
basePath + '/admin',
|
||||
serveStatic(join(staticPath, 'admin', 'selfhost'), {
|
||||
basePath,
|
||||
serveStatic(join(staticPath, 'admin'), {
|
||||
redirect: false,
|
||||
index: false,
|
||||
fallthrough: true,
|
||||
})
|
||||
);
|
||||
|
||||
// fallback all unknown routes
|
||||
app.get(
|
||||
[basePath + '/admin', basePath + '/admin/*'],
|
||||
this.check.use,
|
||||
(_req, res) => {
|
||||
res.sendFile(join(staticPath, 'admin', 'selfhost', 'index.html'));
|
||||
res.sendFile(
|
||||
join(
|
||||
staticPath,
|
||||
'admin',
|
||||
this.config.isSelfhosted ? 'selfhost.html' : 'index.html'
|
||||
)
|
||||
);
|
||||
}
|
||||
);
|
||||
// END REGION
|
||||
|
||||
app.get(basePath + '/index.html', (_req, res) => {
|
||||
res.redirect(basePath);
|
||||
});
|
||||
// START REGION: /mobile
|
||||
// serve all static files
|
||||
app.use(
|
||||
basePath,
|
||||
serveStatic(join(staticPath, 'selfhost'), {
|
||||
serveStatic(join(staticPath, 'mobile'), {
|
||||
redirect: false,
|
||||
index: false,
|
||||
fallthrough: true,
|
||||
})
|
||||
);
|
||||
app.get('*', this.check.use, (_req, res) => {
|
||||
res.sendFile(join(staticPath, 'selfhost', 'index.html'));
|
||||
// END REGION
|
||||
|
||||
// START REGION: /
|
||||
// do not allow '/index.html' url, redirect to '/'
|
||||
app.get(basePath + '/index.html', (_req, res) => {
|
||||
return res.redirect(basePath);
|
||||
});
|
||||
|
||||
// serve all static files
|
||||
app.use(
|
||||
basePath,
|
||||
serveStatic(staticPath, {
|
||||
redirect: false,
|
||||
index: false,
|
||||
fallthrough: true,
|
||||
})
|
||||
);
|
||||
|
||||
// fallback all unknown routes
|
||||
app.get([basePath, basePath + '/*'], this.check.use, (req, res) => {
|
||||
const mobile = isMobile({
|
||||
ua: req.headers['user-agent'] ?? undefined,
|
||||
});
|
||||
|
||||
return res.sendFile(
|
||||
join(
|
||||
staticPath,
|
||||
mobile ? 'mobile' : '',
|
||||
this.config.isSelfhosted ? 'selfhost.html' : 'index.html'
|
||||
)
|
||||
);
|
||||
});
|
||||
// END REGION
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import { defineStartupConfig, ModuleConfig } from '../../fundamentals/config';
|
||||
export interface ServerStartupConfigurations {
|
||||
/**
|
||||
* Base url of AFFiNE server, used for generating external urls.
|
||||
* default to be `[AFFiNE.protocol]://[AFFiNE.host][:AFFiNE.port]?[AFFiNE.path]` if not specified
|
||||
* default to be `[AFFiNE.protocol]://[AFFiNE.host][:AFFiNE.port]/[AFFiNE.path]` if not specified
|
||||
*/
|
||||
externalUrl: string;
|
||||
/**
|
||||
|
||||
@@ -17,12 +17,17 @@ const test = ava as TestFn<{
|
||||
db: PrismaClient;
|
||||
}>;
|
||||
|
||||
const mobileUAString =
|
||||
'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Mobile Safari/537.36';
|
||||
|
||||
function initTestStaticFiles(staticPath: string) {
|
||||
const files = {
|
||||
'selfhost/index.html': `<!DOCTYPE html><html><body>AFFiNE</body><script src="main.js"/></html>`,
|
||||
'selfhost/main.js': `const name = 'affine'`,
|
||||
'admin/selfhost/index.html': `<!DOCTYPE html><html><body>AFFiNE Admin</body><script src="/admin/main.js"/></html>`,
|
||||
'admin/selfhost/main.js': `const name = 'affine-admin'`,
|
||||
'selfhost.html': `<!DOCTYPE html><html><body>AFFiNE</body><script src="main.a.js"/></html>`,
|
||||
'main.a.js': `const name = 'affine'`,
|
||||
'admin/selfhost.html': `<!DOCTYPE html><html><body>AFFiNE Admin</body><script src="/admin/main.b.js"/></html>`,
|
||||
'admin/main.b.js': `const name = 'affine-admin'`,
|
||||
'mobile/selfhost.html': `<!DOCTYPE html><html><body>AFFiNE mobile</body><script src="/mobile/main.c.js"/></html>`,
|
||||
'mobile/main.c.js': `const name = 'affine-mobile'`,
|
||||
};
|
||||
|
||||
for (const [filename, content] of Object.entries(files)) {
|
||||
@@ -35,6 +40,7 @@ function initTestStaticFiles(staticPath: string) {
|
||||
test.before('init selfhost server', async t => {
|
||||
// @ts-expect-error override
|
||||
AFFiNE.isSelfhosted = true;
|
||||
AFFiNE.flavor.renderer = true;
|
||||
const { app } = await createTestingApp({
|
||||
imports: [buildAppModule()],
|
||||
});
|
||||
@@ -54,7 +60,7 @@ test.beforeEach(async t => {
|
||||
server._initialized = false;
|
||||
});
|
||||
|
||||
test.afterEach.always(async t => {
|
||||
test.after.always(async t => {
|
||||
await t.context.app.close();
|
||||
});
|
||||
|
||||
@@ -70,19 +76,28 @@ test('do not allow visit index.html directly', async t => {
|
||||
.expect(302);
|
||||
|
||||
t.is(res.header.location, '/admin');
|
||||
|
||||
res = await request(t.context.app.getHttpServer())
|
||||
.get('/mobile/index.html')
|
||||
.expect(302);
|
||||
});
|
||||
|
||||
test('should always return static asset files', async t => {
|
||||
let res = await request(t.context.app.getHttpServer())
|
||||
.get('/main.js')
|
||||
.get('/main.a.js')
|
||||
.expect(200);
|
||||
t.is(res.text, "const name = 'affine'");
|
||||
|
||||
res = await request(t.context.app.getHttpServer())
|
||||
.get('/admin/main.js')
|
||||
.get('/main.b.js')
|
||||
.expect(200);
|
||||
t.is(res.text, "const name = 'affine-admin'");
|
||||
|
||||
res = await request(t.context.app.getHttpServer())
|
||||
.get('/main.c.js')
|
||||
.expect(200);
|
||||
t.is(res.text, "const name = 'affine-mobile'");
|
||||
|
||||
await t.context.db.user.create({
|
||||
data: {
|
||||
name: 'test',
|
||||
@@ -91,14 +106,19 @@ test('should always return static asset files', async t => {
|
||||
});
|
||||
|
||||
res = await request(t.context.app.getHttpServer())
|
||||
.get('/main.js')
|
||||
.get('/main.a.js')
|
||||
.expect(200);
|
||||
t.is(res.text, "const name = 'affine'");
|
||||
|
||||
res = await request(t.context.app.getHttpServer())
|
||||
.get('/admin/main.js')
|
||||
.get('/main.b.js')
|
||||
.expect(200);
|
||||
t.is(res.text, "const name = 'affine-admin'");
|
||||
|
||||
res = await request(t.context.app.getHttpServer())
|
||||
.get('/main.c.js')
|
||||
.expect(200);
|
||||
t.is(res.text, "const name = 'affine-mobile'");
|
||||
});
|
||||
|
||||
test('should be able to call apis', async t => {
|
||||
@@ -167,3 +187,19 @@ test('should redirect to admin if initialized', async t => {
|
||||
|
||||
t.is(res.header.location, '/admin');
|
||||
});
|
||||
|
||||
test('should return mobile assets if visited by mobile', async t => {
|
||||
await t.context.db.user.create({
|
||||
data: {
|
||||
name: 'test',
|
||||
email: 'test@affine.pro',
|
||||
},
|
||||
});
|
||||
|
||||
const res = await request(t.context.app.getHttpServer())
|
||||
.get('/')
|
||||
.set('user-agent', mobileUAString)
|
||||
.expect(200);
|
||||
|
||||
t.true(res.text.includes('AFFiNE mobile'));
|
||||
});
|
||||
|
||||
94
packages/backend/server/tests/doc/renderer.spec.ts
Normal file
94
packages/backend/server/tests/doc/renderer.spec.ts
Normal file
@@ -0,0 +1,94 @@
|
||||
import { mkdirSync, writeFileSync } from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
import type { INestApplication } from '@nestjs/common';
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
import type { TestFn } from 'ava';
|
||||
import ava from 'ava';
|
||||
import request from 'supertest';
|
||||
|
||||
import { DocRendererModule } from '../../src/core/doc-renderer';
|
||||
import { createTestingApp } from '../utils';
|
||||
|
||||
const test = ava as TestFn<{
|
||||
app: INestApplication;
|
||||
db: PrismaClient;
|
||||
}>;
|
||||
|
||||
const mobileUAString =
|
||||
'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Mobile Safari/537.36';
|
||||
|
||||
function initTestStaticFiles(staticPath: string) {
|
||||
const files = {
|
||||
'main.a.js': `const name = 'affine'`,
|
||||
'assets-manifest.json': JSON.stringify({
|
||||
js: ['main.a.js'],
|
||||
css: [],
|
||||
publicPath: 'https://app.affine.pro/',
|
||||
gitHash: '',
|
||||
description: '',
|
||||
}),
|
||||
'admin/main.b.js': `const name = 'affine-admin'`,
|
||||
'mobile/main.c.js': `const name = 'affine-mobile'`,
|
||||
'mobile/assets-manifest.json': JSON.stringify({
|
||||
js: ['main.c.js'],
|
||||
css: [],
|
||||
publicPath: 'https://app.affine.pro/',
|
||||
gitHash: '',
|
||||
description: '',
|
||||
}),
|
||||
};
|
||||
|
||||
for (const [filename, content] of Object.entries(files)) {
|
||||
const filePath = path.join(staticPath, filename);
|
||||
mkdirSync(path.dirname(filePath), { recursive: true });
|
||||
writeFileSync(filePath, content);
|
||||
}
|
||||
}
|
||||
|
||||
test.before('init selfhost server', async t => {
|
||||
const staticPath = path.join(
|
||||
fileURLToPath(import.meta.url),
|
||||
'../../../static'
|
||||
);
|
||||
initTestStaticFiles(staticPath);
|
||||
|
||||
const { app } = await createTestingApp({
|
||||
imports: [DocRendererModule],
|
||||
});
|
||||
|
||||
t.context.app = app;
|
||||
t.context.db = t.context.app.get(PrismaClient);
|
||||
});
|
||||
|
||||
test.after.always(async t => {
|
||||
await t.context.app.close();
|
||||
});
|
||||
|
||||
test('should render correct html', async t => {
|
||||
const res = await request(t.context.app.getHttpServer())
|
||||
.get('/workspace/xxxx/xxx')
|
||||
.expect(200);
|
||||
|
||||
t.true(
|
||||
res.text.includes(
|
||||
`<script src="https://app.affine.pro/main.a.js"></script>`
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
test('should render correct mobile html', async t => {
|
||||
const res = await request(t.context.app.getHttpServer())
|
||||
.get('/workspace/xxxx/xxx')
|
||||
.set('user-agent', mobileUAString)
|
||||
.expect(200);
|
||||
|
||||
t.true(
|
||||
res.text.includes(
|
||||
`<script src="https://app.affine.pro/main.c.js"></script>`
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
test.todo('should render correct page preview');
|
||||
69
packages/common/env/src/global.ts
vendored
69
packages/common/env/src/global.ts
vendored
@@ -31,12 +31,12 @@ export type BUILD_CONFIG_TYPE = {
|
||||
// see: tools/workers
|
||||
imageProxyUrl: string;
|
||||
linkPreviewUrl: string;
|
||||
|
||||
// TODO(@forehalo): remove
|
||||
isSelfHosted: boolean;
|
||||
};
|
||||
|
||||
export type Environment = {
|
||||
// Variant
|
||||
isSelfHosted: boolean;
|
||||
|
||||
// Device
|
||||
isLinux: boolean;
|
||||
isMacOs: boolean;
|
||||
@@ -47,8 +47,10 @@ export type Environment = {
|
||||
isMobile: boolean;
|
||||
isChrome: boolean;
|
||||
isPwa: boolean;
|
||||
|
||||
chromeVersion?: number;
|
||||
|
||||
// runtime configs
|
||||
publicPath: string;
|
||||
};
|
||||
|
||||
export function setupGlobal() {
|
||||
@@ -56,24 +58,25 @@ export function setupGlobal() {
|
||||
return;
|
||||
}
|
||||
|
||||
let environment: Environment;
|
||||
let environment: Environment = {
|
||||
isLinux: false,
|
||||
isMacOs: false,
|
||||
isSafari: false,
|
||||
isWindows: false,
|
||||
isFireFox: false,
|
||||
isChrome: false,
|
||||
isIOS: false,
|
||||
isPwa: false,
|
||||
isMobile: false,
|
||||
isSelfHosted: false,
|
||||
publicPath: '/',
|
||||
};
|
||||
|
||||
if (!globalThis.navigator) {
|
||||
environment = {
|
||||
isLinux: false,
|
||||
isMacOs: false,
|
||||
isSafari: false,
|
||||
isWindows: false,
|
||||
isFireFox: false,
|
||||
isChrome: false,
|
||||
isIOS: false,
|
||||
isPwa: false,
|
||||
isMobile: false,
|
||||
};
|
||||
} else {
|
||||
if (globalThis.navigator) {
|
||||
const uaHelper = new UaHelper(globalThis.navigator);
|
||||
|
||||
environment = {
|
||||
...environment,
|
||||
isMobile: uaHelper.isMobile,
|
||||
isLinux: uaHelper.isLinux,
|
||||
isMacOs: uaHelper.isMacOs,
|
||||
@@ -96,7 +99,35 @@ export function setupGlobal() {
|
||||
}
|
||||
}
|
||||
|
||||
globalThis.environment = environment;
|
||||
applyEnvironmentOverrides(environment);
|
||||
|
||||
globalThis.environment = environment;
|
||||
globalThis.$AFFINE_SETUP = true;
|
||||
}
|
||||
|
||||
function applyEnvironmentOverrides(environment: Environment) {
|
||||
if (typeof document === 'undefined') {
|
||||
return;
|
||||
}
|
||||
|
||||
const metaTags = document.querySelectorAll('meta');
|
||||
|
||||
metaTags.forEach(meta => {
|
||||
if (!meta.name.startsWith('env:')) {
|
||||
return;
|
||||
}
|
||||
|
||||
const name = meta.name.substring(4);
|
||||
|
||||
// all environments should have default value
|
||||
// so ignore non-defined overrides
|
||||
if (name in environment) {
|
||||
// @ts-expect-error safe
|
||||
environment[name] =
|
||||
// @ts-expect-error safe
|
||||
typeof environment[name] === 'string'
|
||||
? meta.content
|
||||
: JSON.parse(meta.content);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import './global.css';
|
||||
import './setup';
|
||||
|
||||
import { createRoot } from 'react-dom/client';
|
||||
|
||||
|
||||
3
packages/frontend/admin/src/setup.ts
Normal file
3
packages/frontend/admin/src/setup.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
import { setupBrowser } from '@affine/core/bootstrap';
|
||||
|
||||
await setupBrowser();
|
||||
BIN
packages/frontend/core/public/fonts/BebasNeue-Light.woff
Normal file
BIN
packages/frontend/core/public/fonts/BebasNeue-Light.woff
Normal file
Binary file not shown.
BIN
packages/frontend/core/public/fonts/BebasNeue-Regular.woff
Normal file
BIN
packages/frontend/core/public/fonts/BebasNeue-Regular.woff
Normal file
Binary file not shown.
BIN
packages/frontend/core/public/fonts/Inter-Italic.woff
Normal file
BIN
packages/frontend/core/public/fonts/Inter-Italic.woff
Normal file
Binary file not shown.
BIN
packages/frontend/core/public/fonts/Inter-Light-BETA.woff
Normal file
BIN
packages/frontend/core/public/fonts/Inter-Light-BETA.woff
Normal file
Binary file not shown.
BIN
packages/frontend/core/public/fonts/Inter-LightItalic-BETA.woff
Normal file
BIN
packages/frontend/core/public/fonts/Inter-LightItalic-BETA.woff
Normal file
Binary file not shown.
BIN
packages/frontend/core/public/fonts/Inter-Regular.woff
Normal file
BIN
packages/frontend/core/public/fonts/Inter-Regular.woff
Normal file
Binary file not shown.
BIN
packages/frontend/core/public/fonts/Inter-SemiBold.woff
Normal file
BIN
packages/frontend/core/public/fonts/Inter-SemiBold.woff
Normal file
Binary file not shown.
BIN
packages/frontend/core/public/fonts/Inter-SemiBoldItalic.woff
Normal file
BIN
packages/frontend/core/public/fonts/Inter-SemiBoldItalic.woff
Normal file
Binary file not shown.
BIN
packages/frontend/core/public/fonts/Kalam-Bold.woff
Normal file
BIN
packages/frontend/core/public/fonts/Kalam-Bold.woff
Normal file
Binary file not shown.
BIN
packages/frontend/core/public/fonts/Kalam-Light.woff
Normal file
BIN
packages/frontend/core/public/fonts/Kalam-Light.woff
Normal file
Binary file not shown.
BIN
packages/frontend/core/public/fonts/Kalam-Regular.woff
Normal file
BIN
packages/frontend/core/public/fonts/Kalam-Regular.woff
Normal file
Binary file not shown.
BIN
packages/frontend/core/public/fonts/Lora-Bold.woff
Normal file
BIN
packages/frontend/core/public/fonts/Lora-Bold.woff
Normal file
Binary file not shown.
BIN
packages/frontend/core/public/fonts/Lora-BoldItalic.woff
Normal file
BIN
packages/frontend/core/public/fonts/Lora-BoldItalic.woff
Normal file
Binary file not shown.
BIN
packages/frontend/core/public/fonts/Lora-Italic.woff
Normal file
BIN
packages/frontend/core/public/fonts/Lora-Italic.woff
Normal file
Binary file not shown.
BIN
packages/frontend/core/public/fonts/Lora-Regular.woff
Normal file
BIN
packages/frontend/core/public/fonts/Lora-Regular.woff
Normal file
Binary file not shown.
BIN
packages/frontend/core/public/fonts/OrelegaOne-Regular.woff
Normal file
BIN
packages/frontend/core/public/fonts/OrelegaOne-Regular.woff
Normal file
Binary file not shown.
BIN
packages/frontend/core/public/fonts/Poppins-Italic.woff
Normal file
BIN
packages/frontend/core/public/fonts/Poppins-Italic.woff
Normal file
Binary file not shown.
BIN
packages/frontend/core/public/fonts/Poppins-Light.woff
Normal file
BIN
packages/frontend/core/public/fonts/Poppins-Light.woff
Normal file
Binary file not shown.
BIN
packages/frontend/core/public/fonts/Poppins-LightItalic.woff
Normal file
BIN
packages/frontend/core/public/fonts/Poppins-LightItalic.woff
Normal file
Binary file not shown.
BIN
packages/frontend/core/public/fonts/Poppins-Medium.woff
Normal file
BIN
packages/frontend/core/public/fonts/Poppins-Medium.woff
Normal file
Binary file not shown.
BIN
packages/frontend/core/public/fonts/Poppins-Regular.woff
Normal file
BIN
packages/frontend/core/public/fonts/Poppins-Regular.woff
Normal file
Binary file not shown.
BIN
packages/frontend/core/public/fonts/Poppins-SemiBold.woff
Normal file
BIN
packages/frontend/core/public/fonts/Poppins-SemiBold.woff
Normal file
Binary file not shown.
BIN
packages/frontend/core/public/fonts/Poppins-SemiBoldItalic.woff
Normal file
BIN
packages/frontend/core/public/fonts/Poppins-SemiBoldItalic.woff
Normal file
Binary file not shown.
BIN
packages/frontend/core/public/fonts/Satoshi-Bold.woff
Normal file
BIN
packages/frontend/core/public/fonts/Satoshi-Bold.woff
Normal file
Binary file not shown.
BIN
packages/frontend/core/public/fonts/Satoshi-BoldItalic.woff
Normal file
BIN
packages/frontend/core/public/fonts/Satoshi-BoldItalic.woff
Normal file
Binary file not shown.
BIN
packages/frontend/core/public/fonts/Satoshi-Italic.woff
Normal file
BIN
packages/frontend/core/public/fonts/Satoshi-Italic.woff
Normal file
Binary file not shown.
BIN
packages/frontend/core/public/fonts/Satoshi-Light.woff
Normal file
BIN
packages/frontend/core/public/fonts/Satoshi-Light.woff
Normal file
Binary file not shown.
BIN
packages/frontend/core/public/fonts/Satoshi-LightItalic.woff
Normal file
BIN
packages/frontend/core/public/fonts/Satoshi-LightItalic.woff
Normal file
Binary file not shown.
BIN
packages/frontend/core/public/fonts/Satoshi-Regular.woff
Normal file
BIN
packages/frontend/core/public/fonts/Satoshi-Regular.woff
Normal file
Binary file not shown.
@@ -4,11 +4,12 @@ import { setupEnvironment } from './app';
|
||||
import { polyfillBrowser, polyfillElectron } from './polyfill';
|
||||
|
||||
export function setupElectron() {
|
||||
polyfillElectron();
|
||||
setupEnvironment();
|
||||
polyfillElectron();
|
||||
}
|
||||
|
||||
export async function setupBrowser() {
|
||||
await polyfillBrowser();
|
||||
setupEnvironment();
|
||||
__webpack_public_path__ = environment.publicPath;
|
||||
await polyfillBrowser();
|
||||
}
|
||||
|
||||
@@ -5,12 +5,9 @@ import {
|
||||
|
||||
export function getFontConfigExtension() {
|
||||
return FontConfigExtension(
|
||||
BUILD_CONFIG.isSelfHosted
|
||||
? AffineCanvasTextFonts.map(font => ({
|
||||
...font,
|
||||
// self-hosted fonts are served from /assets
|
||||
url: '/assets/' + new URL(font.url).pathname.split('/').pop(),
|
||||
}))
|
||||
: AffineCanvasTextFonts
|
||||
AffineCanvasTextFonts.map(font => ({
|
||||
...font,
|
||||
url: environment.publicPath + 'fonts/' + font.url.split('/').pop(),
|
||||
}))
|
||||
);
|
||||
}
|
||||
|
||||
@@ -35,8 +35,8 @@ function createMixpanel() {
|
||||
appVersion: BUILD_CONFIG.appVersion,
|
||||
environment: BUILD_CONFIG.appBuildType,
|
||||
editorVersion: BUILD_CONFIG.editorVersion,
|
||||
isSelfHosted: BUILD_CONFIG.isSelfHosted,
|
||||
isDesktop: BUILD_CONFIG.isElectron,
|
||||
isSelfHosted: environment.isSelfHosted,
|
||||
});
|
||||
},
|
||||
reset() {
|
||||
|
||||
Reference in New Issue
Block a user