mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-10 19:38:39 +00:00
Compare commits
287 Commits
v0.6.1-bet
...
v0.7.0-can
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
32f064c2de | ||
|
|
39704bc812 | ||
|
|
a421265483 | ||
|
|
e6214cb6ec | ||
|
|
ba7d34bce5 | ||
|
|
ace3c37fcc | ||
|
|
5ba2dff008 | ||
|
|
dff8a0db7d | ||
|
|
ccda45bdd2 | ||
|
|
eeb536d460 | ||
|
|
1e6e0336c3 | ||
|
|
f2ac2e5b84 | ||
|
|
af6f431c15 | ||
|
|
01ae21e1fa | ||
|
|
34141958eb | ||
|
|
c194cff0bd | ||
|
|
6b6f2d6910 | ||
|
|
2e975e79dd | ||
|
|
c5a295a87b | ||
|
|
119b4cdf10 | ||
|
|
bf6af934f6 | ||
|
|
1971749449 | ||
|
|
b383ce36cd | ||
|
|
fc9a9f479b | ||
|
|
227174db1b | ||
|
|
9f129075dd | ||
|
|
935b4f847c | ||
|
|
ec99a0ce05 | ||
|
|
7ba5f82aef | ||
|
|
546d5764e6 | ||
|
|
6f411bd459 | ||
|
|
29d8f61c90 | ||
|
|
bedf838fe5 | ||
|
|
fda89b05e7 | ||
|
|
de8af5f114 | ||
|
|
14db45ae95 | ||
|
|
27b14af388 | ||
|
|
18dc427bc3 | ||
|
|
1ad2e629ac | ||
|
|
05288be934 | ||
|
|
05b73a59be | ||
|
|
f3fd5ff76b | ||
|
|
4958d096b0 | ||
|
|
7f2006488e | ||
|
|
008a05a470 | ||
|
|
3d7721d59d | ||
|
|
35fb10c95b | ||
|
|
c4c4ec6a67 | ||
|
|
f4be15baec | ||
|
|
17b40b68df | ||
|
|
cd5c4b5cb7 | ||
|
|
d28c887237 | ||
|
|
541011ba90 | ||
|
|
fc658f4a95 | ||
|
|
84f68fc2c0 | ||
|
|
f78760cb83 | ||
|
|
8f6db00402 | ||
|
|
d00d0bd951 | ||
|
|
8f5cd13e78 | ||
|
|
3b4cfc642f | ||
|
|
5807f34935 | ||
|
|
efae4cccd6 | ||
|
|
b461a684ad | ||
|
|
b95808a052 | ||
|
|
1716e7a397 | ||
|
|
acda594cba | ||
|
|
94d20f1bdc | ||
|
|
f9079bb681 | ||
|
|
0d07ff2390 | ||
|
|
42bab6990e | ||
|
|
89a566a645 | ||
|
|
7af5bd3894 | ||
|
|
a57c27679d | ||
|
|
68a72b2dfc | ||
|
|
602f795133 | ||
|
|
5df89a925b | ||
|
|
23126e1ff6 | ||
|
|
e1f715f837 | ||
|
|
fbcaed40e7 | ||
|
|
88757ce488 | ||
|
|
fc9462eee9 | ||
|
|
e1314730be | ||
|
|
36978dbed6 | ||
|
|
53d1991211 | ||
|
|
1ea445ab15 | ||
|
|
78410f531a | ||
|
|
96c0321696 | ||
|
|
0895f1fb30 | ||
|
|
b6188f4b11 | ||
|
|
2ed1a7b219 | ||
|
|
9bee6bd5cc | ||
|
|
198f30c86d | ||
|
|
454f1887cf | ||
|
|
4e1e4e9435 | ||
|
|
f7768563e1 | ||
|
|
6aa0e71b84 | ||
|
|
f1b3a10969 | ||
|
|
90e70ed986 | ||
|
|
094a479c2a | ||
|
|
20f1d487c8 | ||
|
|
4c9bda1406 | ||
|
|
d5debc0bf5 | ||
|
|
f5aee7c360 | ||
|
|
248cd9a8ab | ||
|
|
06abb702f5 | ||
|
|
ee289706ec | ||
|
|
6cbf310a5a | ||
|
|
855fd8a73a | ||
|
|
8dbd354659 | ||
|
|
1c7ae04f4f | ||
|
|
0bb6e362bf | ||
|
|
617350fc7d | ||
|
|
2713340532 | ||
|
|
31d552ab7e | ||
|
|
e11326f05f | ||
|
|
6648fe4dcc | ||
|
|
f669164674 | ||
|
|
c6d8904ca2 | ||
|
|
8c5a1e2de3 | ||
|
|
395414c336 | ||
|
|
96f653ea19 | ||
|
|
fa089de40d | ||
|
|
4175f5391e | ||
|
|
61c417992a | ||
|
|
befae6bc9b | ||
|
|
e7eb13e966 | ||
|
|
88eaaf9ce4 | ||
|
|
20cc082a02 | ||
|
|
402d12a0e1 | ||
|
|
58ba11e13c | ||
|
|
cb6ca52b03 | ||
|
|
cd2ab73e5d | ||
|
|
b16e725514 | ||
|
|
004fcc8e80 | ||
|
|
a01a3ef011 | ||
|
|
20cf45270d | ||
|
|
f3ac12254c | ||
|
|
e0eb216b9b | ||
|
|
90afed1e74 | ||
|
|
83d2ed8ace | ||
|
|
a0b64ca3e3 | ||
|
|
b9fc5ad769 | ||
|
|
ef1a44a413 | ||
|
|
798dc49da4 | ||
|
|
902081d44e | ||
|
|
7969b73979 | ||
|
|
c8734bd6ee | ||
|
|
6d3c273ffd | ||
|
|
f4b3830a0e | ||
|
|
36534f1915 | ||
|
|
7dcbe64d4e | ||
|
|
60057c666d | ||
|
|
60a83f4907 | ||
|
|
b11ce2c8d2 | ||
|
|
3b8f2c1ac3 | ||
|
|
be065e2de3 | ||
|
|
675c737e48 | ||
|
|
1255384cab | ||
|
|
3d423c3299 | ||
|
|
ad4737850d | ||
|
|
9dcacd413c | ||
|
|
c1998eddf3 | ||
|
|
db3f63e8f2 | ||
|
|
e562ca1011 | ||
|
|
f6adf93f90 | ||
|
|
053eba5d98 | ||
|
|
49f1ba676f | ||
|
|
48c109e149 | ||
|
|
259d7988d9 | ||
|
|
0a49258ddd | ||
|
|
fd35d3427e | ||
|
|
ef0a20b358 | ||
|
|
f01997f8ee | ||
|
|
281a068cfb | ||
|
|
fe5be0cb47 | ||
|
|
8aab1d6459 | ||
|
|
2eaaeef4a7 | ||
|
|
5fbfabb3b2 | ||
|
|
ec64260b6a | ||
|
|
2e23a4830b | ||
|
|
41a3d6f62f | ||
|
|
752bc9ca0e | ||
|
|
c08f6fdba4 | ||
|
|
b23b7e896b | ||
|
|
d68b421a4b | ||
|
|
1f510799e2 | ||
|
|
66ea97c7c9 | ||
|
|
ee300e7b60 | ||
|
|
ef2d135e9b | ||
|
|
c82fb89d57 | ||
|
|
725bf63a32 | ||
|
|
c1ca578f7d | ||
|
|
530dd5ff7f | ||
|
|
11370bc07e | ||
|
|
1c53daf1c4 | ||
|
|
b2556db33b | ||
|
|
89310c9b97 | ||
|
|
8e09af910f | ||
|
|
885aea3425 | ||
|
|
a616150f2d | ||
|
|
d80dae8a89 | ||
|
|
34ff08b92b | ||
|
|
2f7b51d7ff | ||
|
|
b7cee3185e | ||
|
|
1c5455e6ed | ||
|
|
2d303fd5d3 | ||
|
|
fbe2543c03 | ||
|
|
d6b640726e | ||
|
|
f875b37641 | ||
|
|
53c4fc6dfa | ||
|
|
6c310249d9 | ||
|
|
02e1f528bf | ||
|
|
c870104370 | ||
|
|
627d8ef787 | ||
|
|
5563823a7a | ||
|
|
d6804bb0fd | ||
|
|
1350633690 | ||
|
|
50196d8fde | ||
|
|
2e0ccb53ec | ||
|
|
1498ee405b | ||
|
|
cb863c4afa | ||
|
|
2629d39501 | ||
|
|
38305cd984 | ||
|
|
93116c24f2 | ||
|
|
017b9c8615 | ||
|
|
9ce3a96862 | ||
|
|
a0ff520ba4 | ||
|
|
a8b8986d89 | ||
|
|
8ffc096fee | ||
|
|
7e457f7b4c | ||
|
|
aedf2d339e | ||
|
|
ffd5ae52b3 | ||
|
|
3093194da8 | ||
|
|
68b4f792f0 | ||
|
|
e2c6e4f9fc | ||
|
|
9ff7dbffb7 | ||
|
|
0c561da061 | ||
|
|
06951319a6 | ||
|
|
0bfcab4067 | ||
|
|
2c4db4fa16 | ||
|
|
23b4f9ee12 | ||
|
|
e5330b1917 | ||
|
|
183611a556 | ||
|
|
7786456ba4 | ||
|
|
f4bf7e3ddf | ||
|
|
05d88215d1 | ||
|
|
b240a70e51 | ||
|
|
00fd468e9b | ||
|
|
b5a7f8b7eb | ||
|
|
f03277fd17 | ||
|
|
ee93071149 | ||
|
|
21fdced2bd | ||
|
|
10b4558947 | ||
|
|
0fbed5d9d6 | ||
|
|
8d117123d7 | ||
|
|
063ffda09d | ||
|
|
39c83bd25b | ||
|
|
4444c3d1a6 | ||
|
|
717dd93f37 | ||
|
|
c58673c55f | ||
|
|
768e55072d | ||
|
|
8c84daec2b | ||
|
|
e54a5b6128 | ||
|
|
ee1e50f391 | ||
|
|
268636c440 | ||
|
|
06fa0cdb60 | ||
|
|
73dbb39009 | ||
|
|
47848cb5da | ||
|
|
eff6a03a51 | ||
|
|
08f6a41ef4 | ||
|
|
6d1345ffe5 | ||
|
|
689f615b11 | ||
|
|
f82ea5d9c4 | ||
|
|
dc4979a80c | ||
|
|
1f48bc4301 | ||
|
|
beabd1e050 | ||
|
|
19e20a6a20 | ||
|
|
e4f13ddae4 | ||
|
|
752d0545ca | ||
|
|
08341d3d6c | ||
|
|
ef665df330 | ||
|
|
b38017cd23 | ||
|
|
0c550a2827 | ||
|
|
87ffdad862 | ||
|
|
c6e8024e16 | ||
|
|
4200b3c3e5 | ||
|
|
10976a9257 |
52
.eslintrc.js
52
.eslintrc.js
@@ -80,19 +80,15 @@ const config = {
|
||||
'react',
|
||||
'@typescript-eslint',
|
||||
'simple-import-sort',
|
||||
'sonarjs',
|
||||
'import',
|
||||
'unused-imports',
|
||||
'unicorn',
|
||||
],
|
||||
rules: {
|
||||
'array-callback-return': 'error',
|
||||
'no-undef': 'off',
|
||||
'no-empty': 'off',
|
||||
'no-func-assign': 'off',
|
||||
'no-cond-assign': 'off',
|
||||
'no-constant-binary-expression': 'error',
|
||||
'no-constructor-return': 'error',
|
||||
'react/prop-types': 'off',
|
||||
'@typescript-eslint/consistent-type-imports': 'error',
|
||||
'@typescript-eslint/no-non-null-assertion': 'error',
|
||||
@@ -142,21 +138,6 @@ const config = {
|
||||
ignore: ['^\\[[a-zA-Z0-9-_]+\\]\\.tsx$'],
|
||||
},
|
||||
],
|
||||
'sonarjs/no-all-duplicated-branches': 'error',
|
||||
'sonarjs/no-element-overwrite': 'error',
|
||||
'sonarjs/no-empty-collection': 'error',
|
||||
'sonarjs/no-extra-arguments': 'error',
|
||||
'sonarjs/no-identical-conditions': 'error',
|
||||
'sonarjs/no-identical-expressions': 'error',
|
||||
'sonarjs/no-ignored-return': 'error',
|
||||
'sonarjs/no-one-iteration-loop': 'error',
|
||||
'sonarjs/no-use-of-empty-return-value': 'error',
|
||||
'sonarjs/non-existent-operator': 'error',
|
||||
'sonarjs/no-collapsible-if': 'error',
|
||||
'sonarjs/no-same-line-conditional': 'error',
|
||||
'sonarjs/no-duplicated-branches': 'error',
|
||||
'sonarjs/no-collection-size-mischeck': 'error',
|
||||
'sonarjs/no-useless-catch': 'error',
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
@@ -171,27 +152,6 @@ const config = {
|
||||
'@typescript-eslint/no-var-requires': 0,
|
||||
},
|
||||
},
|
||||
...allPackages.map(pkg => ({
|
||||
files: [`${pkg}/src/**/*.ts`, `${pkg}/src/**/*.tsx`],
|
||||
parserOptions: {
|
||||
project: resolve(__dirname, './tsconfig.eslint.json'),
|
||||
},
|
||||
rules: {
|
||||
'@typescript-eslint/no-restricted-imports': [
|
||||
'error',
|
||||
{
|
||||
patterns: createPattern(pkg),
|
||||
},
|
||||
],
|
||||
'@typescript-eslint/no-floating-promises': [
|
||||
'error',
|
||||
{
|
||||
ignoreVoid: false,
|
||||
ignoreIIFE: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
})),
|
||||
{
|
||||
files: [
|
||||
'**/__tests__/**/*',
|
||||
@@ -213,9 +173,19 @@ const config = {
|
||||
'ts-check': false,
|
||||
},
|
||||
],
|
||||
'@typescript-eslint/no-floating-promises': 0,
|
||||
},
|
||||
},
|
||||
...allPackages.map(pkg => ({
|
||||
files: [`${pkg}/src/**/*.ts`, `${pkg}/src/**/*.tsx`],
|
||||
rules: {
|
||||
'@typescript-eslint/no-restricted-imports': [
|
||||
'error',
|
||||
{
|
||||
patterns: createPattern(pkg),
|
||||
},
|
||||
],
|
||||
},
|
||||
})),
|
||||
],
|
||||
};
|
||||
|
||||
|
||||
5
.github/workflows/build.yml
vendored
5
.github/workflows/build.yml
vendored
@@ -341,11 +341,6 @@ jobs:
|
||||
name: affine
|
||||
fail_ci_if_error: true
|
||||
|
||||
- name: Run desktop tests
|
||||
if: ${{ matrix.spec.test && matrix.spec.os != 'ubuntu-latest' }}
|
||||
run: yarn test
|
||||
working-directory: apps/electron
|
||||
|
||||
- name: Upload test results
|
||||
if: ${{ failure() }}
|
||||
uses: actions/upload-artifact@v3
|
||||
|
||||
2
.github/workflows/nightly-build.yml
vendored
2
.github/workflows/nightly-build.yml
vendored
@@ -56,7 +56,7 @@ jobs:
|
||||
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
|
||||
API_SERVER_PROFILE: prod
|
||||
ENABLE_TEST_PROPERTIES: false
|
||||
ENABLE_IMAGE_PREVIEW_MODAL: true
|
||||
ENABLE_IMAGE_PREVIEW_MODAL: false
|
||||
ENABLE_BOOKMARK_OPERATION: true
|
||||
RELEASE_VERSION: ${{ needs.set-build-version.outputs.version }}
|
||||
|
||||
|
||||
2
.github/workflows/release-desktop-app.yml
vendored
2
.github/workflows/release-desktop-app.yml
vendored
@@ -56,7 +56,7 @@ jobs:
|
||||
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
|
||||
API_SERVER_PROFILE: prod
|
||||
ENABLE_TEST_PROPERTIES: false
|
||||
ENABLE_IMAGE_PREVIEW_MODAL: true
|
||||
ENABLE_IMAGE_PREVIEW_MODAL: false
|
||||
ENABLE_BOOKMARK_OPERATION: true
|
||||
RELEASE_VERSION: ${{ github.event.inputs.version }}
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
|
||||
const { z } = require('zod');
|
||||
|
||||
const {
|
||||
@@ -52,6 +51,8 @@ module.exports = {
|
||||
teamId: process.env.APPLE_TEAM_ID,
|
||||
}
|
||||
: undefined,
|
||||
// do we need the following line?
|
||||
extraResource: ['./resources/app-update.yml'],
|
||||
},
|
||||
makers: [
|
||||
{
|
||||
@@ -103,27 +104,6 @@ module.exports = {
|
||||
// so stable and canary will not share the same app data
|
||||
packageJson.productName = productName;
|
||||
},
|
||||
prePackage: async () => {
|
||||
const { rm, cp } = require('node:fs/promises');
|
||||
const { resolve } = require('node:path');
|
||||
|
||||
await rm(
|
||||
resolve(__dirname, './node_modules/@toeverything/plugin-infra'),
|
||||
{
|
||||
recursive: true,
|
||||
force: true,
|
||||
}
|
||||
);
|
||||
|
||||
await cp(
|
||||
resolve(__dirname, '../../packages/plugin-infra'),
|
||||
resolve(__dirname, './node_modules/@toeverything/plugin-infra'),
|
||||
{
|
||||
recursive: true,
|
||||
force: true,
|
||||
}
|
||||
);
|
||||
},
|
||||
generateAssets: async (_, platform, arch) => {
|
||||
if (process.env.SKIP_GENERATE_ASSETS) {
|
||||
return;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@affine/electron",
|
||||
"private": true,
|
||||
"version": "0.6.1-beta.0",
|
||||
"version": "0.7.0-canary.13",
|
||||
"author": "affine",
|
||||
"repository": {
|
||||
"url": "https://github.com/toeverything/AFFiNE",
|
||||
@@ -29,10 +29,6 @@
|
||||
"devDependencies": {
|
||||
"@affine-test/kit": "workspace:*",
|
||||
"@affine/native": "workspace:*",
|
||||
"@blocksuite/blocks": "0.0.0-20230607055421-9b20fcaf-nightly",
|
||||
"@blocksuite/editor": "0.0.0-20230607055421-9b20fcaf-nightly",
|
||||
"@blocksuite/lit": "0.0.0-20230607055421-9b20fcaf-nightly",
|
||||
"@blocksuite/store": "0.0.0-20230607055421-9b20fcaf-nightly",
|
||||
"@electron-forge/cli": "^6.1.1",
|
||||
"@electron-forge/core": "^6.1.1",
|
||||
"@electron-forge/core-utils": "^6.1.1",
|
||||
@@ -52,19 +48,17 @@
|
||||
"electron-window-state": "^5.0.3",
|
||||
"esbuild": "^0.17.19",
|
||||
"fs-extra": "^11.1.1",
|
||||
"jotai": "^2.1.1",
|
||||
"playwright": "=1.33.0",
|
||||
"ts-node": "^10.9.1",
|
||||
"undici": "^5.22.1",
|
||||
"uuid": "^9.0.0",
|
||||
"which": "^3.0.1",
|
||||
"zx": "^7.2.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@toeverything/plugin-infra": "workspace:*",
|
||||
"async-call-rpc": "^6.3.1",
|
||||
"cheerio": "^1.0.0-rc.12",
|
||||
"electron-updater": "^5.3.0",
|
||||
"link-preview-js": "^3.0.4",
|
||||
"lodash-es": "^4.17.21",
|
||||
"nanoid": "^4.0.2",
|
||||
"rxjs": "^7.8.1",
|
||||
|
||||
@@ -63,7 +63,7 @@ export const config = () => {
|
||||
bundle: true,
|
||||
target: `node${NODE_MAJOR_VERSION}`,
|
||||
platform: 'node',
|
||||
external: ['@toeverything/plugin-infra', 'async-call-rpc'],
|
||||
external: ['electron', 'electron-updater', '@toeverything/plugin-infra'],
|
||||
define: define,
|
||||
format: 'cjs',
|
||||
loader: {
|
||||
|
||||
@@ -5,7 +5,6 @@ import path, { resolve } from 'node:path';
|
||||
|
||||
import electronPath from 'electron';
|
||||
import * as esbuild from 'esbuild';
|
||||
import which from 'which';
|
||||
|
||||
import { config, electronDir, rootDir } from './common.mjs';
|
||||
|
||||
@@ -68,9 +67,9 @@ function spawnOrReloadElectron() {
|
||||
}
|
||||
|
||||
const common = config();
|
||||
const yarnPath = which.sync('yarn');
|
||||
|
||||
async function watchPlugins() {
|
||||
spawn(yarnPath, ['dev'], {
|
||||
spawn('yarn', ['dev'], {
|
||||
stdio: 'inherit',
|
||||
cwd: resolve(rootDir, './packages/plugin-infra'),
|
||||
});
|
||||
|
||||
@@ -32,6 +32,10 @@ if (releaseVersionEnv && electronPackageJson.version !== releaseVersionEnv) {
|
||||
}
|
||||
// copy web dist files to electron dist
|
||||
|
||||
// step 1: clean up
|
||||
await cleanup();
|
||||
echo('Clean up done');
|
||||
|
||||
if (process.platform === 'win32') {
|
||||
$.shell = 'powershell.exe';
|
||||
$.prefix = '';
|
||||
@@ -39,7 +43,7 @@ if (process.platform === 'win32') {
|
||||
|
||||
cd(repoRootDir);
|
||||
|
||||
// step 1: build web (nextjs) dist
|
||||
// step 2: build web (nextjs) dist
|
||||
if (!process.env.SKIP_WEB_BUILD) {
|
||||
process.env.ENABLE_LEGACY_PROVIDER = 'false';
|
||||
await $`yarn nx build @affine/web`;
|
||||
@@ -63,7 +67,7 @@ if (!process.env.SKIP_WEB_BUILD) {
|
||||
await fs.move(affineWebOutDir, publicAffineOutDir, { overwrite: true });
|
||||
}
|
||||
|
||||
// step 2: update app-updater.yml content with build type in resources folder
|
||||
// step 3: update app-updater.yml content with build type in resources folder
|
||||
if (process.env.BUILD_TYPE === 'internal') {
|
||||
const appUpdaterYml = path.join(publicDistDir, 'app-update.yml');
|
||||
const appUpdaterYmlContent = await fs.readFile(appUpdaterYml, 'utf-8');
|
||||
@@ -73,3 +77,14 @@ if (process.env.BUILD_TYPE === 'internal') {
|
||||
);
|
||||
await fs.writeFile(appUpdaterYml, newAppUpdaterYmlContent);
|
||||
}
|
||||
|
||||
/// --------
|
||||
/// --------
|
||||
/// --------
|
||||
async function cleanup() {
|
||||
if (!process.env.SKIP_WEB_BUILD) {
|
||||
await fs.emptyDir(publicAffineOutDir);
|
||||
}
|
||||
await fs.remove(path.join(electronRootDir, 'dist'));
|
||||
await fs.remove(path.join(electronRootDir, 'out'));
|
||||
}
|
||||
|
||||
@@ -110,9 +110,7 @@ export async function saveDBFileAs(
|
||||
|
||||
await fs.copyFile(db.path, filePath);
|
||||
logger.log('saved', filePath);
|
||||
mainRPC.showItemInFolder(filePath).catch(err => {
|
||||
console.error(err);
|
||||
});
|
||||
mainRPC.showItemInFolder(filePath);
|
||||
return { filePath };
|
||||
} catch (err) {
|
||||
logger.error('saveDBFileAs', err);
|
||||
|
||||
@@ -64,9 +64,7 @@ function setupRendererConnection(rendererPort: Electron.MessagePortMain) {
|
||||
for (const [key, eventRegister] of Object.entries(namespaceEvents)) {
|
||||
const subscription = eventRegister((...args: any[]) => {
|
||||
const chan = `${namespace}:${key}`;
|
||||
rpc.postEvent(chan, ...args).catch(err => {
|
||||
console.error(err);
|
||||
});
|
||||
rpc.postEvent(chan, ...args);
|
||||
});
|
||||
process.on('exit', () => {
|
||||
subscription();
|
||||
|
||||
@@ -60,9 +60,9 @@ app.on('activate', restoreOrCreateWindow);
|
||||
app
|
||||
.whenReady()
|
||||
.then(registerProtocol)
|
||||
.then(registerPlugin)
|
||||
.then(registerHandlers)
|
||||
.then(registerEvents)
|
||||
.then(registerPlugin)
|
||||
.then(ensureHelperProcess)
|
||||
.then(restoreOrCreateWindow)
|
||||
.then(createApplicationMenu)
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { join, resolve } from 'node:path';
|
||||
import { Worker } from 'node:worker_threads';
|
||||
|
||||
import { logger } from '@affine/electron/main/logger';
|
||||
import { AsyncCall } from 'async-call-rpc';
|
||||
import { ipcMain } from 'electron';
|
||||
|
||||
@@ -14,30 +13,23 @@ declare global {
|
||||
var asyncCall: Record<string, (...args: any) => PromiseLike<any>>;
|
||||
}
|
||||
|
||||
export function registerPlugin() {
|
||||
export async function registerPlugin() {
|
||||
const pluginWorkerPath = join(__dirname, './workers/plugin.worker.js');
|
||||
const asyncCall = AsyncCall<
|
||||
Record<string, (...args: any) => PromiseLike<any>>
|
||||
>(
|
||||
{
|
||||
log: (...args: any[]) => {
|
||||
logger.log('Plugin Worker', ...args);
|
||||
},
|
||||
},
|
||||
{},
|
||||
{
|
||||
channel: new MessageEventChannel(new Worker(pluginWorkerPath)),
|
||||
}
|
||||
);
|
||||
globalThis.asyncCall = asyncCall;
|
||||
logger.info('import plugin manager');
|
||||
import('@toeverything/plugin-infra/manager')
|
||||
.then(({ rootStore, affinePluginsAtom }) => {
|
||||
logger.info('import plugin manager');
|
||||
await import('@toeverything/plugin-infra/manager').then(
|
||||
({ rootStore, affinePluginsAtom }) => {
|
||||
const bookmarkPluginPath = join(
|
||||
process.env.PLUGIN_DIR ?? resolve(__dirname, './plugins'),
|
||||
'./bookmark-block/index.mjs'
|
||||
);
|
||||
logger.info('bookmark plugin path:', bookmarkPluginPath);
|
||||
import('file://' + bookmarkPluginPath);
|
||||
let dispose: () => void = () => {
|
||||
// noop
|
||||
@@ -46,9 +38,7 @@ export function registerPlugin() {
|
||||
dispose();
|
||||
const plugins = rootStore.get(affinePluginsAtom);
|
||||
Object.values(plugins).forEach(plugin => {
|
||||
logger.info('register plugin', plugin.definition.id);
|
||||
plugin.definition.commands.forEach(command => {
|
||||
logger.info('register plugin command', command);
|
||||
ipcMain.handle(command, (event, ...args) =>
|
||||
asyncCall[command](...args)
|
||||
);
|
||||
@@ -57,14 +47,11 @@ export function registerPlugin() {
|
||||
dispose = () => {
|
||||
Object.values(plugins).forEach(plugin => {
|
||||
plugin.definition.commands.forEach(command => {
|
||||
logger.info('unregister plugin command', command);
|
||||
ipcMain.removeHandler(command);
|
||||
});
|
||||
});
|
||||
};
|
||||
});
|
||||
})
|
||||
.catch(error => {
|
||||
logger.error('import plugin manager error', error);
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -11,59 +11,33 @@ if (!parentPort) {
|
||||
throw new Error('parentPort is undefined');
|
||||
}
|
||||
|
||||
const mainThread = AsyncCall<{
|
||||
log: (...args: any[]) => Promise<void>;
|
||||
}>(commandProxy, {
|
||||
AsyncCall(commandProxy, {
|
||||
channel: new MessageEventChannel(parentPort),
|
||||
});
|
||||
|
||||
globalThis.console.log = mainThread.log;
|
||||
globalThis.console.error = mainThread.log;
|
||||
globalThis.console.info = mainThread.log;
|
||||
globalThis.console.debug = mainThread.log;
|
||||
globalThis.console.warn = mainThread.log;
|
||||
|
||||
console.log('import plugin infra');
|
||||
|
||||
import('@toeverything/plugin-infra/manager')
|
||||
.then(({ rootStore, affinePluginsAtom }) => {
|
||||
import('@toeverything/plugin-infra/manager').then(
|
||||
({ rootStore, affinePluginsAtom }) => {
|
||||
const bookmarkPluginPath = join(
|
||||
process.env.PLUGIN_DIR ?? resolve(__dirname, '../plugins'),
|
||||
'./bookmark-block/index.mjs'
|
||||
);
|
||||
|
||||
console.log('import bookmark plugin', bookmarkPluginPath);
|
||||
|
||||
import('file://' + bookmarkPluginPath).catch(console.log);
|
||||
import('file://' + bookmarkPluginPath);
|
||||
rootStore.sub(affinePluginsAtom, () => {
|
||||
const plugins = rootStore.get(affinePluginsAtom);
|
||||
Object.values(plugins).forEach(plugin => {
|
||||
console.log('handle plugin', plugin.definition.id);
|
||||
if (plugin.serverAdapter) {
|
||||
try {
|
||||
plugin.serverAdapter({
|
||||
registerCommand: (command, fn) => {
|
||||
console.log('register command', command);
|
||||
commandProxy[command] = fn;
|
||||
},
|
||||
unregisterCommand: command => {
|
||||
console.log('unregister command', command);
|
||||
delete commandProxy[command];
|
||||
},
|
||||
});
|
||||
} catch (e) {
|
||||
console.log(
|
||||
'error when handle plugin',
|
||||
plugin.definition.id,
|
||||
`${e}`
|
||||
);
|
||||
}
|
||||
} else {
|
||||
console.log('no server adapter, skipping.');
|
||||
plugin.serverAdapter({
|
||||
registerCommand: (command, fn) => {
|
||||
console.log('register command', command);
|
||||
commandProxy[command] = fn;
|
||||
},
|
||||
unregisterCommand: command => {
|
||||
delete commandProxy[command];
|
||||
},
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
})
|
||||
.catch(err => {
|
||||
console.error(err);
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
@@ -50,6 +50,4 @@ import { contextBridge, ipcRenderer } from 'electron';
|
||||
} catch (error) {
|
||||
console.error('Failed to expose affine APIs to window object!', error);
|
||||
}
|
||||
})().catch(err => {
|
||||
console.error('Failed to bootstrap preload script!', err);
|
||||
});
|
||||
})();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@affine/server",
|
||||
"private": true,
|
||||
"version": "0.6.1-beta.0",
|
||||
"version": "0.7.0-canary.13",
|
||||
"description": "Affine Node.js server",
|
||||
"type": "module",
|
||||
"bin": {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@affine/web",
|
||||
"private": true,
|
||||
"version": "0.6.1-beta.0",
|
||||
"version": "0.7.0-canary.13",
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
"build": "next build",
|
||||
|
||||
@@ -75,9 +75,7 @@ export function useHistoryAtom() {
|
||||
if (forward) {
|
||||
const target = Math.min(prev.stack.length - 1, prev.current + 1);
|
||||
const url = prev.stack[target];
|
||||
router.push(url).catch(err => {
|
||||
console.error(err);
|
||||
});
|
||||
void router.push(url);
|
||||
return {
|
||||
...prev,
|
||||
current: target,
|
||||
@@ -86,9 +84,7 @@ export function useHistoryAtom() {
|
||||
} else {
|
||||
const target = Math.max(0, prev.current - 1);
|
||||
const url = prev.stack[target];
|
||||
router.push(url).catch(err => {
|
||||
console.error(err);
|
||||
});
|
||||
void router.push(url);
|
||||
return {
|
||||
...prev,
|
||||
current: target,
|
||||
|
||||
@@ -49,24 +49,19 @@ rootWorkspacesMetadataAtom.onMount = setAtom => {
|
||||
}, 0);
|
||||
|
||||
if (environment.isDesktop) {
|
||||
window.apis?.workspace
|
||||
.list()
|
||||
.then(workspaceIDs => {
|
||||
if (abortController.signal.aborted) return;
|
||||
const newMetadata = workspaceIDs.map(w => ({
|
||||
id: w[0],
|
||||
flavour: WorkspaceFlavour.LOCAL,
|
||||
}));
|
||||
setAtom(metadata => {
|
||||
return [
|
||||
...metadata,
|
||||
...newMetadata.filter(m => !metadata.find(m2 => m2.id === m.id)),
|
||||
];
|
||||
});
|
||||
})
|
||||
.catch(err => {
|
||||
console.error(err);
|
||||
window.apis?.workspace.list().then(workspaceIDs => {
|
||||
if (abortController.signal.aborted) return;
|
||||
const newMetadata = workspaceIDs.map(w => ({
|
||||
id: w[0],
|
||||
flavour: WorkspaceFlavour.LOCAL,
|
||||
}));
|
||||
setAtom(metadata => {
|
||||
return [
|
||||
...metadata,
|
||||
...newMetadata.filter(m => !metadata.find(m2 => m2.id === m.id)),
|
||||
];
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return () => {
|
||||
|
||||
@@ -116,14 +116,9 @@ const useDefaultDBLocation = () => {
|
||||
const [defaultDBLocation, setDefaultDBLocation] = useState('');
|
||||
|
||||
useEffect(() => {
|
||||
window.apis?.db
|
||||
.getDefaultStorageLocation()
|
||||
.then(dir => {
|
||||
setDefaultDBLocation(dir);
|
||||
})
|
||||
.catch(err => {
|
||||
console.error(err);
|
||||
});
|
||||
window.apis?.db.getDefaultStorageLocation().then(dir => {
|
||||
setDefaultDBLocation(dir);
|
||||
});
|
||||
}, []);
|
||||
|
||||
return defaultDBLocation;
|
||||
@@ -286,9 +281,7 @@ export const CreateWorkspaceModal = ({
|
||||
}
|
||||
onClose();
|
||||
}
|
||||
})().catch(err => {
|
||||
console.error(err);
|
||||
});
|
||||
})();
|
||||
} else if (mode === 'new') {
|
||||
setStep(environment.isDesktop ? 'set-db-location' : 'name-workspace');
|
||||
} else {
|
||||
|
||||
@@ -12,7 +12,7 @@ import { useBlockSuiteWorkspaceAvatarUrl } from '@toeverything/hooks/use-block-s
|
||||
import { useBlockSuiteWorkspaceName } from '@toeverything/hooks/use-block-suite-workspace-name';
|
||||
import clsx from 'clsx';
|
||||
import type React from 'react';
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
import { useIsWorkspaceOwner } from '../../../../../hooks/affine/use-is-workspace-owner';
|
||||
import { Upload } from '../../../../pure/file-upload';
|
||||
@@ -27,14 +27,9 @@ const useShowOpenDBFile = (workspaceId: string) => {
|
||||
const [show, setShow] = useState(false);
|
||||
useEffect(() => {
|
||||
if (window.apis && window.events && environment.isDesktop) {
|
||||
window.apis.workspace
|
||||
.getMeta(workspaceId)
|
||||
.then(meta => {
|
||||
setShow(!!meta.secondaryDBPath);
|
||||
})
|
||||
.catch(err => {
|
||||
console.error(err);
|
||||
});
|
||||
window.apis.workspace.getMeta(workspaceId).then(meta => {
|
||||
setShow(!!meta.secondaryDBPath);
|
||||
});
|
||||
return window.events.workspace.onMetaChange((newMeta: any) => {
|
||||
if (newMeta.workspaceId === workspaceId) {
|
||||
const meta = newMeta.meta;
|
||||
@@ -59,11 +54,35 @@ export const GeneralPanel: React.FC<PanelProps> = ({
|
||||
const isOwner = useIsWorkspaceOwner(workspace);
|
||||
const t = useAFFiNEI18N();
|
||||
|
||||
const showOpenFolder = useShowOpenDBFile(workspace.id);
|
||||
|
||||
const handleUpdateWorkspaceName = (name: string) => {
|
||||
setName(name);
|
||||
toast(t['Update workspace name success']());
|
||||
};
|
||||
|
||||
const [moveToInProgress, setMoveToInProgress] = useState<boolean>(false);
|
||||
|
||||
const handleMoveTo = async () => {
|
||||
if (moveToInProgress) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
setMoveToInProgress(true);
|
||||
const result = await window.apis?.dialog.moveDBFile(workspace.id);
|
||||
if (!result?.error && !result?.canceled) {
|
||||
toast(t['Move folder success']());
|
||||
} else if (result?.error) {
|
||||
// @ts-expect-error: result.error is dynamic
|
||||
toast(t[result.error]());
|
||||
}
|
||||
} catch (err) {
|
||||
toast(t['UNKNOWN_ERROR']());
|
||||
} finally {
|
||||
setMoveToInProgress(false);
|
||||
}
|
||||
};
|
||||
|
||||
const [, update] = useBlockSuiteWorkspaceAvatarUrl(
|
||||
workspace.blockSuiteWorkspace
|
||||
);
|
||||
@@ -118,7 +137,9 @@ export const GeneralPanel: React.FC<PanelProps> = ({
|
||||
placeholder={t['Workspace Name']()}
|
||||
maxLength={64}
|
||||
minLength={0}
|
||||
onChange={setInput}
|
||||
onChange={newName => {
|
||||
setInput(newName);
|
||||
}}
|
||||
></StyledInput>
|
||||
</div>
|
||||
|
||||
@@ -137,7 +158,63 @@ export const GeneralPanel: React.FC<PanelProps> = ({
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<DesktopClientOnly workspaceId={workspace.id} />
|
||||
|
||||
{environment.isDesktop && (
|
||||
<div className={style.row}>
|
||||
<div className={style.col}>
|
||||
<div className={style.settingItemLabel}>
|
||||
{t['Storage Folder']()}
|
||||
</div>
|
||||
<div className={style.settingItemLabelHint}>
|
||||
{t['Storage Folder Hint']()}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={style.col}>
|
||||
{showOpenFolder && (
|
||||
<div
|
||||
className={style.storageTypeWrapper}
|
||||
onClick={() => {
|
||||
if (environment.isDesktop) {
|
||||
window.apis?.dialog.revealDBFile(workspace.id);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<FolderIcon color="var(--affine-primary-color)" />
|
||||
<div className={style.storageTypeLabelWrapper}>
|
||||
<div className={style.storageTypeLabel}>
|
||||
{t['Open folder']()}
|
||||
</div>
|
||||
<div className={style.storageTypeLabelHint}>
|
||||
{t['Open folder hint']()}
|
||||
</div>
|
||||
</div>
|
||||
<ArrowRightSmallIcon color="var(--affine-primary-color)" />
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div
|
||||
data-testid="move-folder"
|
||||
data-disabled={moveToInProgress}
|
||||
className={style.storageTypeWrapper}
|
||||
onClick={handleMoveTo}
|
||||
>
|
||||
<MoveToIcon color="var(--affine-primary-color)" />
|
||||
<div className={style.storageTypeLabelWrapper}>
|
||||
<div className={style.storageTypeLabel}>
|
||||
{t['Move folder']()}
|
||||
</div>
|
||||
<div className={style.storageTypeLabelHint}>
|
||||
{t['Move folder hint']()}
|
||||
</div>
|
||||
</div>
|
||||
<ArrowRightSmallIcon color="var(--affine-primary-color)" />
|
||||
</div>
|
||||
</div>
|
||||
<div className={style.col}></div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className={style.row}>
|
||||
<div className={style.col}>
|
||||
<div className={style.settingItemLabel}>
|
||||
@@ -196,81 +273,3 @@ export const GeneralPanel: React.FC<PanelProps> = ({
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
function DesktopClientOnly({ workspaceId }: { workspaceId: string }) {
|
||||
const t = useAFFiNEI18N();
|
||||
const showOpenFolder = useShowOpenDBFile(workspaceId);
|
||||
const onRevealDBFile = useCallback(() => {
|
||||
if (environment.isDesktop) {
|
||||
window.apis?.dialog.revealDBFile(workspaceId).catch(err => {
|
||||
console.error(err);
|
||||
});
|
||||
}
|
||||
}, [workspaceId]);
|
||||
const [moveToInProgress, setMoveToInProgress] = useState<boolean>(false);
|
||||
const handleMoveTo = useCallback(() => {
|
||||
if (moveToInProgress) {
|
||||
return;
|
||||
}
|
||||
setMoveToInProgress(true);
|
||||
window.apis?.dialog
|
||||
.moveDBFile(workspaceId)
|
||||
.then(result => {
|
||||
if (!result?.error && !result?.canceled) {
|
||||
toast(t['Move folder success']());
|
||||
} else if (result?.error) {
|
||||
// @ts-expect-error: result.error is dynamic
|
||||
toast(t[result.error]());
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
toast(t['UNKNOWN_ERROR']());
|
||||
})
|
||||
.finally(() => {
|
||||
setMoveToInProgress(false);
|
||||
});
|
||||
}, [moveToInProgress, t, workspaceId]);
|
||||
const openFolderNode = showOpenFolder ? (
|
||||
<div className={style.storageTypeWrapper} onClick={onRevealDBFile}>
|
||||
<FolderIcon color="var(--affine-primary-color)" />
|
||||
<div className={style.storageTypeLabelWrapper}>
|
||||
<div className={style.storageTypeLabel}>{t['Open folder']()}</div>
|
||||
<div className={style.storageTypeLabelHint}>
|
||||
{t['Open folder hint']()}
|
||||
</div>
|
||||
</div>
|
||||
<ArrowRightSmallIcon color="var(--affine-primary-color)" />
|
||||
</div>
|
||||
) : null;
|
||||
return (
|
||||
<div className={style.row}>
|
||||
<div className={style.col}>
|
||||
<div className={style.settingItemLabel}>{t['Storage Folder']()}</div>
|
||||
<div className={style.settingItemLabelHint}>
|
||||
{t['Storage Folder Hint']()}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={style.col}>
|
||||
{openFolderNode}
|
||||
|
||||
<div
|
||||
data-testid="move-folder"
|
||||
data-disabled={moveToInProgress}
|
||||
className={style.storageTypeWrapper}
|
||||
onClick={handleMoveTo}
|
||||
>
|
||||
<MoveToIcon color="var(--affine-primary-color)" />
|
||||
<div className={style.storageTypeLabelWrapper}>
|
||||
<div className={style.storageTypeLabel}>{t['Move folder']()}</div>
|
||||
<div className={style.storageTypeLabelHint}>
|
||||
{t['Move folder hint']()}
|
||||
</div>
|
||||
</div>
|
||||
<ArrowRightSmallIcon color="var(--affine-primary-color)" />
|
||||
</div>
|
||||
</div>
|
||||
<div className={style.col}></div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -9,9 +9,7 @@ const LanguageMenuContent: FC = () => {
|
||||
const i18n = useI18N();
|
||||
const changeLanguage = useCallback(
|
||||
(event: string) => {
|
||||
i18n.changeLanguage(event).catch(err => {
|
||||
console.error(err);
|
||||
});
|
||||
void i18n.changeLanguage(event);
|
||||
},
|
||||
[i18n]
|
||||
);
|
||||
|
||||
@@ -11,14 +11,7 @@ import { affinePluginsAtom } from '@toeverything/plugin-infra/manager';
|
||||
import type { PluginUIAdapter } from '@toeverything/plugin-infra/type';
|
||||
import { useAtom, useAtomValue } from 'jotai';
|
||||
import type { FC, HTMLAttributes, PropsWithChildren, ReactNode } from 'react';
|
||||
import {
|
||||
forwardRef,
|
||||
memo,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useState,
|
||||
} from 'react';
|
||||
import { forwardRef, memo, useEffect, useMemo, useState } from 'react';
|
||||
|
||||
import { guideDownloadClientTipAtom } from '../../../atoms/guide';
|
||||
import { contentLayoutAtom } from '../../../atoms/layout';
|
||||
@@ -106,41 +99,32 @@ const HeaderRightItems: Record<HeaderRightItemName, HeaderItem> = {
|
||||
},
|
||||
[HeaderRightItemName.WindowsAppControls]: {
|
||||
Component: () => {
|
||||
const handleMinimizeApp = useCallback(() => {
|
||||
window.apis?.ui.handleMinimizeApp().catch(err => {
|
||||
console.error(err);
|
||||
});
|
||||
}, []);
|
||||
const handleMaximizeApp = useCallback(() => {
|
||||
window.apis?.ui.handleMaximizeApp().catch(err => {
|
||||
console.error(err);
|
||||
});
|
||||
}, []);
|
||||
const handleCloseApp = useCallback(() => {
|
||||
window.apis?.ui.handleCloseApp().catch(err => {
|
||||
console.error(err);
|
||||
});
|
||||
}, []);
|
||||
return (
|
||||
<div className={styles.windowAppControlsWrapper}>
|
||||
<button
|
||||
data-type="minimize"
|
||||
className={styles.windowAppControl}
|
||||
onClick={handleMinimizeApp}
|
||||
onClick={() => {
|
||||
window.apis?.ui.handleMinimizeApp();
|
||||
}}
|
||||
>
|
||||
<MinusIcon />
|
||||
</button>
|
||||
<button
|
||||
data-type="maximize"
|
||||
className={styles.windowAppControl}
|
||||
onClick={handleMaximizeApp}
|
||||
onClick={() => {
|
||||
window.apis?.ui.handleMaximizeApp();
|
||||
}}
|
||||
>
|
||||
<RoundedRectangleIcon />
|
||||
</button>
|
||||
<button
|
||||
data-type="close"
|
||||
className={styles.windowAppControl}
|
||||
onClick={handleCloseApp}
|
||||
onClick={() => {
|
||||
window.apis?.ui.handleCloseApp();
|
||||
}}
|
||||
>
|
||||
<CloseIcon />
|
||||
</button>
|
||||
|
||||
@@ -109,7 +109,7 @@ const EditorWrapper = memo(function EditorWrapper({
|
||||
);
|
||||
const disposes = uiDecorators.map(ui => ui(editor));
|
||||
return () => {
|
||||
disposes.forEach(fn => fn());
|
||||
disposes.map(fn => fn());
|
||||
dispose();
|
||||
};
|
||||
},
|
||||
|
||||
@@ -54,9 +54,7 @@ export const Footer: React.FC<FooterProps> = ({
|
||||
title: query,
|
||||
});
|
||||
onClose();
|
||||
jumpToPage(blockSuiteWorkspace.id, page.id).catch(err => {
|
||||
console.error(err);
|
||||
});
|
||||
void jumpToPage(blockSuiteWorkspace.id, page.id);
|
||||
}, [blockSuiteWorkspace, createPage, jumpToPage, onClose, query])}
|
||||
>
|
||||
<StyledModalFooterContent>
|
||||
|
||||
@@ -107,9 +107,7 @@ export const RootAppSidebar = ({
|
||||
const [sidebarOpen, setSidebarOpen] = useAtom(appSidebarOpenAtom);
|
||||
useEffect(() => {
|
||||
if (environment.isDesktop && typeof sidebarOpen === 'boolean') {
|
||||
window.apis?.ui.handleSidebarVisibilityChange(sidebarOpen).catch(err => {
|
||||
console.error(err);
|
||||
});
|
||||
window.apis?.ui.handleSidebarVisibilityChange(sidebarOpen);
|
||||
}
|
||||
}, [sidebarOpen]);
|
||||
|
||||
|
||||
@@ -80,10 +80,15 @@ export function WorkspaceHeader({
|
||||
{t['Workspace Settings']()}
|
||||
</WorkspaceTitle>
|
||||
);
|
||||
} else if (
|
||||
currentEntry.subPath === WorkspaceSubPath.SHARED ||
|
||||
currentEntry.subPath === WorkspaceSubPath.TRASH
|
||||
) {
|
||||
} else if (currentEntry.subPath === WorkspaceSubPath.SHARED) {
|
||||
return (
|
||||
<WorkspaceModeFilterTab
|
||||
workspace={currentWorkspace}
|
||||
currentPage={null}
|
||||
isPublic={false}
|
||||
/>
|
||||
);
|
||||
} else if (currentEntry.subPath === WorkspaceSubPath.TRASH) {
|
||||
return (
|
||||
<WorkspaceModeFilterTab
|
||||
workspace={currentWorkspace}
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
WorkspaceFallback,
|
||||
} from '@affine/component/workspace';
|
||||
import { DebugLogger } from '@affine/debug';
|
||||
import { config, DEFAULT_HELLO_WORLD_PAGE_ID, env } from '@affine/env';
|
||||
import { config, DEFAULT_HELLO_WORLD_PAGE_ID } from '@affine/env';
|
||||
import { initEmptyPage, initPageWithPreloading } from '@affine/env/blocksuite';
|
||||
import type { BackgroundProvider } from '@affine/env/workspace';
|
||||
import { WorkspaceFlavour } from '@affine/env/workspace';
|
||||
@@ -48,7 +48,6 @@ import {
|
||||
publicWorkspaceAtom,
|
||||
publicWorkspaceIdAtom,
|
||||
} from '../atoms/public-workspace';
|
||||
import type { IslandItemNames } from '../components/pure/help-island';
|
||||
import { HelpIsland } from '../components/pure/help-island';
|
||||
import {
|
||||
DROPPABLE_SIDEBAR_TRASH,
|
||||
@@ -175,9 +174,7 @@ export const CurrentWorkspaceContext = ({
|
||||
useEffect(() => {
|
||||
const id = setTimeout(() => {
|
||||
if (!exist) {
|
||||
push('/').catch(err => {
|
||||
console.error(err);
|
||||
});
|
||||
void push('/');
|
||||
globalThis.HALTING_PROBLEM_TIMEOUT <<= 1;
|
||||
}
|
||||
}, globalThis.HALTING_PROBLEM_TIMEOUT);
|
||||
@@ -322,9 +319,7 @@ export const WorkspaceLayoutInner: FC<PropsWithChildren> = ({ children }) => {
|
||||
}
|
||||
if (!router.query.pageId) {
|
||||
setCurrentPageId(pageId);
|
||||
jumpToPage(currentWorkspace.id, pageId).catch(err => {
|
||||
console.error(err);
|
||||
});
|
||||
void jumpToPage(currentWorkspace.id, pageId);
|
||||
}
|
||||
}
|
||||
//#endregion
|
||||
@@ -358,9 +353,7 @@ export const WorkspaceLayoutInner: FC<PropsWithChildren> = ({ children }) => {
|
||||
}
|
||||
);
|
||||
setCurrentPageId(currentPageId);
|
||||
jumpToPage(currentWorkspace.id, page.id).catch(err => {
|
||||
console.error(err);
|
||||
});
|
||||
void jumpToPage(currentWorkspace.id, page.id);
|
||||
}
|
||||
}, [
|
||||
currentPageId,
|
||||
@@ -408,10 +401,6 @@ export const WorkspaceLayoutInner: FC<PropsWithChildren> = ({ children }) => {
|
||||
);
|
||||
const t = useAFFiNEI18N();
|
||||
|
||||
const showList: IslandItemNames[] = env.isDesktop
|
||||
? ['whatNew', 'contact', 'guide']
|
||||
: ['whatNew', 'contact'];
|
||||
|
||||
const handleDragEnd = useCallback(
|
||||
(e: DragEndEvent) => {
|
||||
// Drag page into trash folder
|
||||
@@ -466,7 +455,9 @@ export const WorkspaceLayoutInner: FC<PropsWithChildren> = ({ children }) => {
|
||||
</div>
|
||||
{!isPublicWorkspace && (
|
||||
<HelpIsland
|
||||
showList={router.query.pageId ? undefined : showList}
|
||||
showList={
|
||||
router.query.pageId ? undefined : ['whatNew', 'contact']
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</ToolContainer>
|
||||
|
||||
@@ -39,31 +39,21 @@ const IndexPageInner = () => {
|
||||
nonTrashPages.at(0)?.id;
|
||||
if (pageId) {
|
||||
logger.debug('Found target workspace. Jump to page', pageId);
|
||||
jumpToPage(targetWorkspace.id, pageId, RouteLogic.REPLACE).catch(
|
||||
err => {
|
||||
console.error(err);
|
||||
}
|
||||
);
|
||||
void jumpToPage(targetWorkspace.id, pageId, RouteLogic.REPLACE);
|
||||
} else {
|
||||
const clearId = setTimeout(() => {
|
||||
dispose.dispose();
|
||||
logger.debug('Found target workspace. Jump to all pages');
|
||||
jumpToSubPath(
|
||||
void jumpToSubPath(
|
||||
targetWorkspace.id,
|
||||
WorkspaceSubPath.ALL,
|
||||
RouteLogic.REPLACE
|
||||
).catch(err => {
|
||||
console.error(err);
|
||||
});
|
||||
);
|
||||
}, 1000);
|
||||
const dispose =
|
||||
targetWorkspace.blockSuiteWorkspace.slots.pageAdded.once(pageId => {
|
||||
clearTimeout(clearId);
|
||||
jumpToPage(targetWorkspace.id, pageId, RouteLogic.REPLACE).catch(
|
||||
err => {
|
||||
console.error(err);
|
||||
}
|
||||
);
|
||||
void jumpToPage(targetWorkspace.id, pageId, RouteLogic.REPLACE);
|
||||
});
|
||||
return () => {
|
||||
clearTimeout(clearId);
|
||||
|
||||
@@ -11,7 +11,7 @@ import { atomWithStorage } from 'jotai/utils';
|
||||
import Head from 'next/head';
|
||||
import type { NextRouter } from 'next/router';
|
||||
import { useRouter } from 'next/router';
|
||||
import React, { useCallback } from 'react';
|
||||
import React, { useCallback, useEffect } from 'react';
|
||||
|
||||
import { getUIAdapter } from '../../../adapters/workspace';
|
||||
import { PageLoading } from '../../../components/pure/loading';
|
||||
@@ -30,7 +30,7 @@ function useTabRouterSync(
|
||||
router: NextRouter,
|
||||
currentTab: SettingPanel,
|
||||
setCurrentTab: (tab: SettingPanel) => void
|
||||
): void {
|
||||
) {
|
||||
if (!router.isReady) {
|
||||
return;
|
||||
}
|
||||
@@ -39,30 +39,37 @@ function useTabRouterSync(
|
||||
? router.query.currentTab
|
||||
: null;
|
||||
if (
|
||||
(queryCurrentTab !== null &&
|
||||
settingPanelValues.indexOf(queryCurrentTab as SettingPanel) === -1) ||
|
||||
settingPanelValues.indexOf(currentTab as SettingPanel) === -1
|
||||
queryCurrentTab !== null &&
|
||||
settingPanelValues.indexOf(queryCurrentTab as SettingPanel) === -1
|
||||
) {
|
||||
setCurrentTab(settingPanel.General);
|
||||
router
|
||||
.replace({
|
||||
pathname: router.pathname,
|
||||
query: {
|
||||
...router.query,
|
||||
currentTab: settingPanel.General,
|
||||
},
|
||||
})
|
||||
.catch(console.error);
|
||||
void router.replace({
|
||||
pathname: router.pathname,
|
||||
query: {
|
||||
...router.query,
|
||||
currentTab: settingPanel.General,
|
||||
},
|
||||
});
|
||||
return;
|
||||
} else if (settingPanelValues.indexOf(currentTab as SettingPanel) === -1) {
|
||||
setCurrentTab(settingPanel.General);
|
||||
void router.replace({
|
||||
pathname: router.pathname,
|
||||
query: {
|
||||
...router.query,
|
||||
currentTab: settingPanel.General,
|
||||
},
|
||||
});
|
||||
return;
|
||||
} else if (queryCurrentTab !== currentTab) {
|
||||
router
|
||||
.replace({
|
||||
pathname: router.pathname,
|
||||
query: {
|
||||
...router.query,
|
||||
currentTab: currentTab,
|
||||
},
|
||||
})
|
||||
.catch(console.error);
|
||||
void router.replace({
|
||||
pathname: router.pathname,
|
||||
query: {
|
||||
...router.query,
|
||||
currentTab: currentTab,
|
||||
},
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,24 +78,20 @@ const SettingPage: NextPageWithLayout = () => {
|
||||
const [currentWorkspace] = useCurrentWorkspace();
|
||||
const t = useAFFiNEI18N();
|
||||
const [currentTab, setCurrentTab] = useAtom(settingPanelAtom);
|
||||
useEffect(() => {});
|
||||
const onChangeTab = useCallback(
|
||||
(tab: SettingPanel) => {
|
||||
setCurrentTab(tab as SettingPanel);
|
||||
router
|
||||
.push({
|
||||
pathname: router.pathname,
|
||||
query: {
|
||||
...router.query,
|
||||
currentTab: tab,
|
||||
},
|
||||
})
|
||||
.catch(err => {
|
||||
console.error(err);
|
||||
});
|
||||
void router.push({
|
||||
pathname: router.pathname,
|
||||
query: {
|
||||
...router.query,
|
||||
currentTab: tab,
|
||||
},
|
||||
});
|
||||
},
|
||||
[router, setCurrentTab]
|
||||
);
|
||||
|
||||
useTabRouterSync(router, currentTab, setCurrentTab);
|
||||
|
||||
const helper = useAppHelper();
|
||||
@@ -99,11 +102,11 @@ const SettingPage: NextPageWithLayout = () => {
|
||||
return helper.deleteWorkspace(workspaceId);
|
||||
}, [currentWorkspace, helper]);
|
||||
const onTransformWorkspace = useOnTransformWorkspace();
|
||||
if (
|
||||
!router.isReady ||
|
||||
currentWorkspace === null ||
|
||||
settingPanelValues.indexOf(currentTab as SettingPanel) === -1
|
||||
) {
|
||||
if (!router.isReady) {
|
||||
return <PageLoading />;
|
||||
} else if (currentWorkspace === null) {
|
||||
return <PageLoading />;
|
||||
} else if (settingPanelValues.indexOf(currentTab as SettingPanel) === -1) {
|
||||
return <PageLoading />;
|
||||
}
|
||||
const { SettingsDetail, Header } = getUIAdapter(currentWorkspace.flavour);
|
||||
|
||||
@@ -31,7 +31,9 @@ const TrashPage: NextPageWithLayout = () => {
|
||||
},
|
||||
[currentWorkspace, jumpToPage]
|
||||
);
|
||||
if (!router.isReady || currentWorkspace === null) {
|
||||
if (!router.isReady) {
|
||||
return <PageLoading />;
|
||||
} else if (currentWorkspace === null) {
|
||||
return <PageLoading />;
|
||||
}
|
||||
// todo(himself65): refactor to plugin
|
||||
|
||||
16
nx.json
16
nx.json
@@ -12,17 +12,13 @@
|
||||
"affected": {
|
||||
"defaultBase": "master"
|
||||
},
|
||||
"implicitDependencies": {
|
||||
"package.json": {
|
||||
"dependencies": "*",
|
||||
"devDependencies": "*"
|
||||
},
|
||||
"tsconfig.json": "*",
|
||||
"nx.json": "*"
|
||||
},
|
||||
"namedInputs": {
|
||||
"default": ["{projectRoot}/**/*"],
|
||||
"production": ["!{projectRoot}/**/*.spec.tsx"]
|
||||
"default": ["{projectRoot}/**/*", "sharedGlobals"],
|
||||
"sharedGlobals": [
|
||||
"{workspaceRoot}/tsconfig.json",
|
||||
"{workspaceRoot}/nx.json"
|
||||
],
|
||||
"production": ["default"]
|
||||
},
|
||||
"targetDefaults": {
|
||||
"build": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@affine/monorepo",
|
||||
"version": "0.6.1-beta.0",
|
||||
"version": "0.7.0-canary.13",
|
||||
"private": true,
|
||||
"author": "toeverything",
|
||||
"license": "MPL-2.0",
|
||||
@@ -72,7 +72,6 @@
|
||||
"eslint-plugin-react": "^7.32.2",
|
||||
"eslint-plugin-react-hooks": "^4.6.0",
|
||||
"eslint-plugin-simple-import-sort": "^10.0.0",
|
||||
"eslint-plugin-sonarjs": "^0.19.0",
|
||||
"eslint-plugin-unicorn": "^47.0.0",
|
||||
"eslint-plugin-unused-imports": "^2.0.0",
|
||||
"fake-indexeddb": "4.0.1",
|
||||
|
||||
@@ -15,5 +15,5 @@
|
||||
"dependencies": {
|
||||
"dotenv": "^16.1.4"
|
||||
},
|
||||
"version": "0.6.1-beta.0"
|
||||
"version": "0.7.0-canary.13"
|
||||
}
|
||||
|
||||
@@ -66,5 +66,5 @@
|
||||
"vite": "^4.3.9",
|
||||
"yjs": "^13.6.1"
|
||||
},
|
||||
"version": "0.6.1-beta.0"
|
||||
"version": "0.7.0-canary.13"
|
||||
}
|
||||
|
||||
@@ -49,9 +49,7 @@ export const updateAvailableAtom = atomWithObservable(() => {
|
||||
return rpcToObservable(null as any | null, {
|
||||
event: window.events?.updater.onUpdateAvailable,
|
||||
onSubscribe: () => {
|
||||
window.apis?.updater.checkForUpdatesAndNotify().catch(err => {
|
||||
console.error(err);
|
||||
});
|
||||
window.apis?.updater.checkForUpdatesAndNotify();
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
@@ -65,10 +65,7 @@ export function AppUpdaterButton({ className, style }: AddPageButtonProps) {
|
||||
}, [currentVersion, setChangelogCheckAtom]);
|
||||
const onClickUpdate = useCallback(() => {
|
||||
if (updateReady) {
|
||||
window.apis?.updater.quitAndInstall().catch(err => {
|
||||
// TODO: add error toast here
|
||||
console.error(err);
|
||||
});
|
||||
window.apis?.updater.quitAndInstall();
|
||||
} else if (updateAvailable) {
|
||||
if (updateAvailable.allowAutoUpdate) {
|
||||
// wait for download to finish
|
||||
|
||||
@@ -1,210 +0,0 @@
|
||||
import type { MouseEvent as ReactMouseEvent, RefObject } from 'react';
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
|
||||
interface UseZoomControlsProps {
|
||||
zoomRef: RefObject<HTMLDivElement>;
|
||||
imageRef: RefObject<HTMLImageElement>;
|
||||
}
|
||||
|
||||
export const useZoomControls = ({
|
||||
zoomRef,
|
||||
imageRef,
|
||||
}: UseZoomControlsProps) => {
|
||||
const [currentScale, setCurrentScale] = useState<number>(1);
|
||||
const [isZoomedBigger, setIsZoomedBigger] = useState<boolean>(false);
|
||||
const [isDragging, setIsDragging] = useState<boolean>(false);
|
||||
const [mouseX, setMouseX] = useState<number>(0);
|
||||
const [mouseY, setMouseY] = useState<number>(0);
|
||||
const [dragBeforeX, setDragBeforeX] = useState<number>(0);
|
||||
const [dragBeforeY, setDragBeforeY] = useState<number>(0);
|
||||
const [imagePos, setImagePos] = useState<{ x: number; y: number }>({
|
||||
x: 0,
|
||||
y: 0,
|
||||
});
|
||||
|
||||
const zoomIn = useCallback(() => {
|
||||
const image = imageRef.current;
|
||||
|
||||
if (image && currentScale < 2) {
|
||||
const newScale = currentScale + 0.1;
|
||||
setCurrentScale(newScale);
|
||||
image.style.width = `${image.naturalWidth * newScale}px`;
|
||||
image.style.height = `${image.naturalHeight * newScale}px`;
|
||||
}
|
||||
}, [imageRef, currentScale]);
|
||||
|
||||
const zoomOut = useCallback(() => {
|
||||
const image = imageRef.current;
|
||||
if (image && currentScale > 0.2) {
|
||||
const newScale = currentScale - 0.1;
|
||||
setCurrentScale(newScale);
|
||||
image.style.width = `${image.naturalWidth * newScale}px`;
|
||||
image.style.height = `${image.naturalHeight * newScale}px`;
|
||||
const zoomedWidth = image.naturalWidth * newScale;
|
||||
const zoomedHeight = image.naturalHeight * newScale;
|
||||
const containerWidth = window.innerWidth;
|
||||
const containerHeight = window.innerHeight;
|
||||
if (zoomedWidth > containerWidth || zoomedHeight > containerHeight) {
|
||||
image.style.transform = `translate(0px, 0px)`;
|
||||
setImagePos({ x: 0, y: 0 });
|
||||
}
|
||||
}
|
||||
}, [imageRef, currentScale]);
|
||||
|
||||
const checkZoomSize = useCallback(() => {
|
||||
const { current: zoomArea } = zoomRef;
|
||||
if (zoomArea) {
|
||||
const image = zoomArea.querySelector('img');
|
||||
if (image) {
|
||||
const zoomedWidth = image.naturalWidth * currentScale;
|
||||
const zoomedHeight = image.naturalHeight * currentScale;
|
||||
const containerWidth = window.innerWidth;
|
||||
const containerHeight = window.innerHeight;
|
||||
setIsZoomedBigger(
|
||||
zoomedWidth > containerWidth || zoomedHeight > containerHeight
|
||||
);
|
||||
}
|
||||
}
|
||||
}, [currentScale, zoomRef]);
|
||||
|
||||
const resetZoom = useCallback(() => {
|
||||
const image = imageRef.current;
|
||||
if (image) {
|
||||
const viewportWidth = window.innerWidth;
|
||||
const viewportHeight = window.innerHeight;
|
||||
const margin = 0.2;
|
||||
|
||||
const availableWidth = viewportWidth * (1 - margin);
|
||||
const availableHeight = viewportHeight * (1 - margin);
|
||||
|
||||
const widthRatio = availableWidth / image.naturalWidth;
|
||||
const heightRatio = availableHeight / image.naturalHeight;
|
||||
|
||||
const newScale = Math.min(widthRatio, heightRatio);
|
||||
setCurrentScale(newScale);
|
||||
image.style.width = `${image.naturalWidth * newScale}px`;
|
||||
image.style.height = `${image.naturalHeight * newScale}px`;
|
||||
image.style.transform = 'translate(0px, 0px)';
|
||||
setImagePos({ x: 0, y: 0 });
|
||||
checkZoomSize();
|
||||
}
|
||||
}, [checkZoomSize, imageRef]);
|
||||
|
||||
const handleDragStart = useCallback(
|
||||
(event: ReactMouseEvent) => {
|
||||
event?.preventDefault();
|
||||
setIsDragging(true);
|
||||
const image = imageRef.current;
|
||||
if (image && isZoomedBigger) {
|
||||
image.style.cursor = 'grab';
|
||||
const rect = image.getBoundingClientRect();
|
||||
setDragBeforeX(rect.left);
|
||||
setDragBeforeY(rect.top);
|
||||
setMouseX(event.clientX);
|
||||
setMouseY(event.clientY);
|
||||
}
|
||||
},
|
||||
[imageRef, isZoomedBigger]
|
||||
);
|
||||
|
||||
const handleDrag = useCallback(
|
||||
(event: ReactMouseEvent) => {
|
||||
event?.preventDefault();
|
||||
const image = imageRef.current;
|
||||
|
||||
if (isDragging && image && isZoomedBigger) {
|
||||
image.style.cursor = 'grabbing';
|
||||
const currentX = imagePos.x;
|
||||
const currentY = imagePos.y;
|
||||
const newPosX = currentX + event.clientX - mouseX;
|
||||
const newPosY = currentY + event.clientY - mouseY;
|
||||
image.style.transform = `translate(${newPosX}px, ${newPosY}px)`;
|
||||
}
|
||||
},
|
||||
[
|
||||
imagePos.x,
|
||||
imagePos.y,
|
||||
imageRef,
|
||||
isDragging,
|
||||
isZoomedBigger,
|
||||
mouseX,
|
||||
mouseY,
|
||||
]
|
||||
);
|
||||
|
||||
const dragEndImpl = useCallback(() => {
|
||||
setIsDragging(false);
|
||||
|
||||
const image = imageRef.current;
|
||||
if (image && isZoomedBigger && isDragging) {
|
||||
image.style.cursor = 'pointer';
|
||||
const rect = image.getBoundingClientRect();
|
||||
const newPos = { x: rect.left, y: rect.top };
|
||||
const currentX = imagePos.x;
|
||||
const currentY = imagePos.y;
|
||||
const newPosX = currentX + newPos.x - dragBeforeX;
|
||||
const newPosY = currentY + newPos.y - dragBeforeY;
|
||||
setImagePos({ x: newPosX, y: newPosY });
|
||||
}
|
||||
}, [
|
||||
dragBeforeX,
|
||||
dragBeforeY,
|
||||
imagePos.x,
|
||||
imagePos.y,
|
||||
imageRef,
|
||||
isDragging,
|
||||
isZoomedBigger,
|
||||
]);
|
||||
|
||||
const handleDragEnd = useCallback(
|
||||
(event: ReactMouseEvent) => {
|
||||
event.preventDefault();
|
||||
dragEndImpl();
|
||||
},
|
||||
[dragEndImpl]
|
||||
);
|
||||
|
||||
const handleMouseUp = useCallback(() => {
|
||||
if (isDragging) {
|
||||
dragEndImpl();
|
||||
}
|
||||
}, [isDragging, dragEndImpl]);
|
||||
|
||||
useEffect(() => {
|
||||
const handleScroll = (event: WheelEvent) => {
|
||||
const { deltaY } = event;
|
||||
if (deltaY > 0) {
|
||||
zoomOut();
|
||||
} else if (deltaY < 0) {
|
||||
zoomIn();
|
||||
}
|
||||
};
|
||||
|
||||
const handleResize = () => {
|
||||
checkZoomSize();
|
||||
};
|
||||
|
||||
checkZoomSize();
|
||||
|
||||
window.addEventListener('wheel', handleScroll, { passive: false });
|
||||
window.addEventListener('resize', handleResize);
|
||||
window.addEventListener('mouseup', handleMouseUp);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('wheel', handleScroll);
|
||||
window.removeEventListener('resize', handleResize);
|
||||
window.removeEventListener('mouseup', handleMouseUp);
|
||||
};
|
||||
}, [zoomIn, zoomOut, checkZoomSize, handleMouseUp]);
|
||||
|
||||
return {
|
||||
zoomIn,
|
||||
zoomOut,
|
||||
resetZoom,
|
||||
isZoomedBigger,
|
||||
currentScale,
|
||||
handleDragStart,
|
||||
handleDrag,
|
||||
handleDragEnd,
|
||||
};
|
||||
};
|
||||
@@ -11,8 +11,7 @@ export const imagePreviewModalStyle = style({
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
// background: 'var(--affine-background-modal-color)',
|
||||
background: 'rgba(0,0,0,0.75)',
|
||||
background: 'var(--affine-background-modal-color)',
|
||||
});
|
||||
|
||||
export const imagePreviewModalCloseButtonStyle = style({
|
||||
@@ -21,9 +20,11 @@ export const imagePreviewModalCloseButtonStyle = style({
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
|
||||
height: '36px',
|
||||
width: '36px',
|
||||
borderRadius: '10px',
|
||||
|
||||
top: '0.5rem',
|
||||
right: '0.5rem',
|
||||
background: 'var(--affine-white)',
|
||||
@@ -32,97 +33,37 @@ export const imagePreviewModalCloseButtonStyle = style({
|
||||
cursor: 'pointer',
|
||||
color: 'var(--affine-icon-color)',
|
||||
transition: 'background 0.2s ease-in-out',
|
||||
zIndex: 1,
|
||||
});
|
||||
|
||||
export const imagePreviewModalGoStyle = style({
|
||||
height: '50%',
|
||||
color: 'var(--affine-white)',
|
||||
position: 'absolute',
|
||||
fontSize: '60px',
|
||||
lineHeight: '60px',
|
||||
fontWeight: 'bold',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
opacity: '0.2',
|
||||
padding: '0 15px',
|
||||
cursor: 'pointer',
|
||||
});
|
||||
|
||||
export const imageNavigationControlStyle = style({
|
||||
display: 'flex',
|
||||
height: '100%',
|
||||
zIndex: 2,
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
});
|
||||
|
||||
export const imagePreviewModalContainerStyle = style({
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
zIndex: 1,
|
||||
'@media': {
|
||||
'screen and (max-width: 768px)': {
|
||||
alignItems: 'center',
|
||||
},
|
||||
},
|
||||
position: 'absolute',
|
||||
top: '20%',
|
||||
});
|
||||
|
||||
export const imagePreviewModalCenterStyle = style({
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
});
|
||||
|
||||
export const imagePreviewModalCaptionStyle = style({
|
||||
color: 'var(--affine-white)',
|
||||
marginTop: '24px',
|
||||
'@media': {
|
||||
'screen and (max-width: 768px)': {
|
||||
textAlign: 'center',
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export const imagePreviewActionBarStyle = style({
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
padding: '16px 0',
|
||||
backgroundColor: 'var(--affine-white)',
|
||||
borderRadius: '8px',
|
||||
boxShadow: '2px 2px 4px rgba(0, 0, 0, 0.3)',
|
||||
maxWidth: 'max-content',
|
||||
});
|
||||
|
||||
export const groupStyle = style({
|
||||
display: 'inline-flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
backgroundColor: 'var(--affine-white)',
|
||||
borderLeft: '1px solid #E3E2E4',
|
||||
});
|
||||
|
||||
export const buttonStyle = style({
|
||||
paddingLeft: '10px',
|
||||
paddingRight: '10px',
|
||||
});
|
||||
|
||||
export const scaleIndicatorStyle = style({
|
||||
margin: '0 8px',
|
||||
});
|
||||
|
||||
export const imageBottomContainerStyle = style({
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
position: 'fixed',
|
||||
bottom: '28px',
|
||||
zIndex: baseTheme.zIndexModal + 1,
|
||||
});
|
||||
|
||||
export const captionStyle = style({
|
||||
export const imagePreviewModalImageStyle = style({
|
||||
background: 'transparent',
|
||||
maxWidth: '686px',
|
||||
color: 'var(--affine-white)',
|
||||
background: 'rgba(0,0,0,0.75)',
|
||||
padding: '10px',
|
||||
marginBottom: '21px',
|
||||
objectFit: 'contain',
|
||||
objectPosition: 'center',
|
||||
borderRadius: '4px',
|
||||
});
|
||||
|
||||
export const imagePreviewModalActionsStyle = style({
|
||||
position: 'absolute',
|
||||
bottom: '28px',
|
||||
background: 'var(--affine-white)',
|
||||
});
|
||||
|
||||
@@ -3,40 +3,19 @@ import '@blocksuite/blocks';
|
||||
|
||||
import type { EmbedBlockModel } from '@blocksuite/blocks';
|
||||
import { assertExists } from '@blocksuite/global/utils';
|
||||
import {
|
||||
ArrowLeftSmallIcon,
|
||||
ArrowRightSmallIcon,
|
||||
CopyIcon,
|
||||
DeleteIcon,
|
||||
DownloadIcon,
|
||||
MinusIcon,
|
||||
PlusIcon,
|
||||
ViewBarIcon,
|
||||
} from '@blocksuite/icons';
|
||||
import type { Workspace } from '@blocksuite/store';
|
||||
import clsx from 'clsx';
|
||||
import { useAtom } from 'jotai';
|
||||
import type { ReactElement } from 'react';
|
||||
import { Suspense, useCallback } from 'react';
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import useSWR from 'swr';
|
||||
|
||||
import Button from '../../ui/button/button';
|
||||
import { useZoomControls } from './hooks/use-zoom';
|
||||
import {
|
||||
buttonStyle,
|
||||
captionStyle,
|
||||
groupStyle,
|
||||
imageBottomContainerStyle,
|
||||
imageNavigationControlStyle,
|
||||
imagePreviewActionBarStyle,
|
||||
imagePreviewModalCaptionStyle,
|
||||
imagePreviewModalCenterStyle,
|
||||
imagePreviewModalCloseButtonStyle,
|
||||
imagePreviewModalContainerStyle,
|
||||
imagePreviewModalGoStyle,
|
||||
imagePreviewModalImageStyle,
|
||||
imagePreviewModalStyle,
|
||||
scaleIndicatorStyle,
|
||||
} from './index.css';
|
||||
import { previewBlockIdAtom } from './index.jotai';
|
||||
|
||||
@@ -52,46 +31,38 @@ const ImagePreviewModalImpl = (
|
||||
}
|
||||
): ReactElement | null => {
|
||||
const [blockId, setBlockId] = useAtom(previewBlockIdAtom);
|
||||
|
||||
const [bIsActionBarVisible, setBIsActionBarVisible] = useState(false);
|
||||
const [caption, setCaption] = useState(() => {
|
||||
const page = props.workspace.getPage(props.pageId);
|
||||
assertExists(page);
|
||||
const block = page.getBlockById(props.blockId) as EmbedBlockModel;
|
||||
const block = page.getBlockById(props.blockId) as EmbedBlockModel | null;
|
||||
assertExists(block);
|
||||
return block?.caption;
|
||||
return block.caption;
|
||||
});
|
||||
useEffect(() => {
|
||||
const page = props.workspace.getPage(props.pageId);
|
||||
assertExists(page);
|
||||
const block = page.getBlockById(props.blockId) as EmbedBlockModel;
|
||||
const block = page.getBlockById(props.blockId) as EmbedBlockModel | null;
|
||||
assertExists(block);
|
||||
setCaption(block?.caption);
|
||||
const disposable = block.propsUpdated.on(() => {
|
||||
setCaption(block.caption);
|
||||
});
|
||||
return () => {
|
||||
disposable.dispose();
|
||||
};
|
||||
}, [props.blockId, props.pageId, props.workspace]);
|
||||
const { data } = useSWR(['workspace', 'embed', props.pageId, props.blockId], {
|
||||
fetcher: ([_, __, pageId, blockId]) => {
|
||||
const page = props.workspace.getPage(pageId);
|
||||
assertExists(page);
|
||||
const block = page.getBlockById(blockId) as EmbedBlockModel;
|
||||
const block = page.getBlockById(blockId) as EmbedBlockModel | null;
|
||||
assertExists(block);
|
||||
return props.workspace.blobs.get(block?.sourceId);
|
||||
return props.workspace.blobs.get(block.sourceId);
|
||||
},
|
||||
suspense: true,
|
||||
});
|
||||
const zoomRef = useRef<HTMLDivElement | null>(null);
|
||||
const imageRef = useRef<HTMLImageElement | null>(null);
|
||||
const {
|
||||
zoomIn,
|
||||
zoomOut,
|
||||
isZoomedBigger,
|
||||
handleDrag,
|
||||
handleDragStart,
|
||||
handleDragEnd,
|
||||
resetZoom,
|
||||
currentScale,
|
||||
} = useZoomControls({ zoomRef, imageRef });
|
||||
const [prevData, setPrevData] = useState<string | null>(() => data);
|
||||
const [url, setUrl] = useState<string | null>(null);
|
||||
const imageRef = useRef<HTMLImageElement>(null);
|
||||
if (prevData !== data) {
|
||||
if (url) {
|
||||
URL.revokeObjectURL(url);
|
||||
@@ -105,224 +76,8 @@ const ImagePreviewModalImpl = (
|
||||
if (!url) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const nextImageHandler = (blockId: string | null) => {
|
||||
assertExists(blockId);
|
||||
const workspace = props.workspace;
|
||||
|
||||
const page = workspace.getPage(props.pageId);
|
||||
assertExists(page);
|
||||
const block = page.getBlockById(blockId);
|
||||
assertExists(block);
|
||||
const nextBlock = page
|
||||
.getNextSiblings(block)
|
||||
.find(
|
||||
(block): block is EmbedBlockModel => block.flavour === 'affine:embed'
|
||||
);
|
||||
if (nextBlock) {
|
||||
setBlockId(nextBlock.id);
|
||||
}
|
||||
};
|
||||
|
||||
const previousImageHandler = (blockId: string | null) => {
|
||||
assertExists(blockId);
|
||||
const workspace = props.workspace;
|
||||
const page = workspace.getPage(props.pageId);
|
||||
assertExists(page);
|
||||
const block = page.getBlockById(blockId);
|
||||
assertExists(block);
|
||||
const prevBlock = page
|
||||
.getPreviousSiblings(block)
|
||||
.findLast(
|
||||
(block): block is EmbedBlockModel => block.flavour === 'affine:embed'
|
||||
);
|
||||
if (prevBlock) {
|
||||
setBlockId(prevBlock.id);
|
||||
}
|
||||
};
|
||||
|
||||
const deleteHandler = (blockId: string) => {
|
||||
const workspace = props.workspace;
|
||||
|
||||
const page = workspace.getPage(props.pageId);
|
||||
assertExists(page);
|
||||
const block = page.getBlockById(blockId);
|
||||
assertExists(block);
|
||||
if (
|
||||
page
|
||||
.getPreviousSiblings(block)
|
||||
.findLast(
|
||||
(block): block is EmbedBlockModel => block.flavour === 'affine:embed'
|
||||
)
|
||||
) {
|
||||
const prevBlock = page
|
||||
.getPreviousSiblings(block)
|
||||
.findLast(
|
||||
(block): block is EmbedBlockModel => block.flavour === 'affine:embed'
|
||||
);
|
||||
if (prevBlock) {
|
||||
setBlockId(prevBlock.id);
|
||||
}
|
||||
} else if (
|
||||
page
|
||||
.getNextSiblings(block)
|
||||
.find(
|
||||
(block): block is EmbedBlockModel => block.flavour === 'affine:embed'
|
||||
)
|
||||
) {
|
||||
const nextBlock = page
|
||||
.getNextSiblings(block)
|
||||
.find(
|
||||
(block): block is EmbedBlockModel => block.flavour === 'affine:embed'
|
||||
);
|
||||
if (nextBlock) {
|
||||
const image = imageRef.current;
|
||||
resetZoom();
|
||||
if (image) {
|
||||
image.style.width = '100%'; // Reset the width to its original size
|
||||
image.style.height = 'auto'; // Reset the height to maintain aspect ratio
|
||||
}
|
||||
setBlockId(nextBlock.id);
|
||||
}
|
||||
} else {
|
||||
props.onClose();
|
||||
}
|
||||
page.deleteBlock(block);
|
||||
};
|
||||
|
||||
let actionbarTimeout: NodeJS.Timeout;
|
||||
|
||||
const downloadHandler = async (blockId: string | null) => {
|
||||
const workspace = props.workspace;
|
||||
const page = workspace.getPage(props.pageId);
|
||||
assertExists(page);
|
||||
if (typeof blockId === 'string') {
|
||||
const block = page.getBlockById(blockId) as EmbedBlockModel;
|
||||
assertExists(block);
|
||||
const store = await block.page.blobs;
|
||||
const url = store?.get(block.sourceId);
|
||||
const img = await url;
|
||||
if (!img) {
|
||||
return;
|
||||
}
|
||||
const arrayBuffer = await img.arrayBuffer();
|
||||
const buffer = new Uint8Array(arrayBuffer);
|
||||
let fileType: string;
|
||||
if (
|
||||
buffer[0] === 0x47 &&
|
||||
buffer[1] === 0x49 &&
|
||||
buffer[2] === 0x46 &&
|
||||
buffer[3] === 0x38
|
||||
) {
|
||||
fileType = 'image/gif';
|
||||
} else if (
|
||||
buffer[0] === 0x89 &&
|
||||
buffer[1] === 0x50 &&
|
||||
buffer[2] === 0x4e &&
|
||||
buffer[3] === 0x47
|
||||
) {
|
||||
fileType = 'image/png';
|
||||
} else if (
|
||||
buffer[0] === 0xff &&
|
||||
buffer[1] === 0xd8 &&
|
||||
buffer[2] === 0xff &&
|
||||
buffer[3] === 0xe0
|
||||
) {
|
||||
fileType = 'image/jpeg';
|
||||
} else {
|
||||
// unknown, fallback to png
|
||||
console.error('unknown image type');
|
||||
fileType = 'image/png';
|
||||
}
|
||||
const downloadUrl = URL.createObjectURL(
|
||||
new Blob([arrayBuffer], { type: fileType })
|
||||
);
|
||||
const a = document.createElement('a');
|
||||
const event = new MouseEvent('click');
|
||||
a.download = block.id;
|
||||
a.href = downloadUrl;
|
||||
a.dispatchEvent(event);
|
||||
|
||||
// cleanup
|
||||
a.remove();
|
||||
URL.revokeObjectURL(downloadUrl);
|
||||
}
|
||||
};
|
||||
|
||||
const handleMouseEnter = () => {
|
||||
clearTimeout(actionbarTimeout);
|
||||
setBIsActionBarVisible(true);
|
||||
};
|
||||
|
||||
const handleMouseLeave = () => {
|
||||
actionbarTimeout = setTimeout(() => {
|
||||
setBIsActionBarVisible(false);
|
||||
}, 3000);
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
data-testid="image-preview-modal"
|
||||
className={imagePreviewModalStyle}
|
||||
onClick={event =>
|
||||
event.target === event.currentTarget ? props.onClose() : null
|
||||
}
|
||||
>
|
||||
{!isZoomedBigger ? (
|
||||
<div className={imageNavigationControlStyle}>
|
||||
<span
|
||||
className={imagePreviewModalGoStyle}
|
||||
style={{
|
||||
left: 0,
|
||||
}}
|
||||
onClick={() => {
|
||||
assertExists(blockId);
|
||||
previousImageHandler(blockId);
|
||||
}}
|
||||
>
|
||||
❮
|
||||
</span>
|
||||
<span
|
||||
className={imagePreviewModalGoStyle}
|
||||
style={{
|
||||
right: 0,
|
||||
}}
|
||||
onClick={() => {
|
||||
assertExists(blockId);
|
||||
nextImageHandler(blockId);
|
||||
}}
|
||||
>
|
||||
❯
|
||||
</span>
|
||||
</div>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
<div className={imagePreviewModalContainerStyle}>
|
||||
<div
|
||||
className={clsx('zoom-area', { 'zoomed-bigger': isZoomedBigger })}
|
||||
ref={zoomRef}
|
||||
>
|
||||
<div className={imagePreviewModalCenterStyle}>
|
||||
<img
|
||||
data-blob-id={props.blockId}
|
||||
src={url}
|
||||
alt={caption}
|
||||
ref={imageRef}
|
||||
draggable={isZoomedBigger}
|
||||
onMouseDown={handleDragStart}
|
||||
onMouseMove={handleDrag}
|
||||
onMouseUp={handleDragEnd}
|
||||
onMouseEnter={handleMouseEnter}
|
||||
onMouseLeave={handleMouseLeave}
|
||||
onLoad={resetZoom}
|
||||
/>
|
||||
{isZoomedBigger ? null : (
|
||||
<p className={imagePreviewModalCaptionStyle}>{caption}</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div data-testid="image-preview-modal" className={imagePreviewModalStyle}>
|
||||
<button
|
||||
onClick={() => {
|
||||
props.onClose();
|
||||
@@ -344,123 +99,67 @@ const ImagePreviewModalImpl = (
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
{bIsActionBarVisible ? (
|
||||
<div
|
||||
className={imageBottomContainerStyle}
|
||||
onMouseEnter={handleMouseEnter}
|
||||
onMouseLeave={handleMouseLeave}
|
||||
onClick={event => event.stopPropagation()}
|
||||
>
|
||||
{isZoomedBigger && caption !== '' ? (
|
||||
<p className={captionStyle}>{caption}</p>
|
||||
) : null}
|
||||
<div className={imagePreviewActionBarStyle}>
|
||||
<div>
|
||||
<Button
|
||||
icon={<ArrowLeftSmallIcon />}
|
||||
noBorder={true}
|
||||
className={buttonStyle}
|
||||
onClick={() => {
|
||||
assertExists(blockId);
|
||||
previousImageHandler(blockId);
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
icon={<ArrowRightSmallIcon />}
|
||||
noBorder={true}
|
||||
className={buttonStyle}
|
||||
onClick={() => {
|
||||
assertExists(blockId);
|
||||
nextImageHandler(blockId);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div className={groupStyle}>
|
||||
<Button
|
||||
icon={<ViewBarIcon />}
|
||||
noBorder={true}
|
||||
className={buttonStyle}
|
||||
onClick={() => resetZoom()}
|
||||
/>
|
||||
<Button
|
||||
icon={<MinusIcon />}
|
||||
noBorder={true}
|
||||
className={buttonStyle}
|
||||
onClick={zoomOut}
|
||||
/>
|
||||
<span className={scaleIndicatorStyle}>{`${(
|
||||
currentScale * 100
|
||||
).toFixed(0)}%`}</span>
|
||||
<Button
|
||||
icon={<PlusIcon />}
|
||||
noBorder={true}
|
||||
className={buttonStyle}
|
||||
onClick={() => zoomIn()}
|
||||
/>
|
||||
</div>
|
||||
<div className={groupStyle}>
|
||||
<Button
|
||||
icon={<DownloadIcon />}
|
||||
noBorder={true}
|
||||
className={buttonStyle}
|
||||
onClick={() => {
|
||||
assertExists(blockId);
|
||||
downloadHandler(blockId).catch(err => {
|
||||
console.error('Could not download image', err);
|
||||
});
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
icon={<CopyIcon />}
|
||||
noBorder={true}
|
||||
className={buttonStyle}
|
||||
onClick={() => {
|
||||
if (!imageRef.current) {
|
||||
return;
|
||||
}
|
||||
const canvas = document.createElement('canvas');
|
||||
canvas.width = imageRef.current.naturalWidth;
|
||||
canvas.height = imageRef.current.naturalHeight;
|
||||
const context = canvas.getContext('2d');
|
||||
if (!context) {
|
||||
console.warn('Could not get canvas context');
|
||||
return;
|
||||
}
|
||||
context.drawImage(imageRef.current, 0, 0);
|
||||
canvas.toBlob(blob => {
|
||||
if (!blob) {
|
||||
console.warn('Could not get blob');
|
||||
return;
|
||||
}
|
||||
const dataUrl = URL.createObjectURL(blob);
|
||||
navigator.clipboard
|
||||
.write([new ClipboardItem({ 'image/png': blob })])
|
||||
.then(() => {
|
||||
console.log('Image copied to clipboard');
|
||||
URL.revokeObjectURL(dataUrl);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error(
|
||||
'Error copying image to clipboard',
|
||||
error
|
||||
);
|
||||
URL.revokeObjectURL(dataUrl);
|
||||
});
|
||||
}, 'image/png');
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div className={groupStyle}>
|
||||
<Button
|
||||
icon={<DeleteIcon />}
|
||||
noBorder={true}
|
||||
className={buttonStyle}
|
||||
onClick={() => blockId && deleteHandler(blockId)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
<span
|
||||
className={imagePreviewModalGoStyle}
|
||||
style={{
|
||||
left: 0,
|
||||
}}
|
||||
onClick={() => {
|
||||
assertExists(blockId);
|
||||
const workspace = props.workspace;
|
||||
|
||||
const page = workspace.getPage(props.pageId);
|
||||
assertExists(page);
|
||||
const block = page.getBlockById(blockId);
|
||||
assertExists(block);
|
||||
const prevBlock = page
|
||||
.getPreviousSiblings(block)
|
||||
.findLast(
|
||||
(block): block is EmbedBlockModel =>
|
||||
block.flavour === 'affine:embed'
|
||||
);
|
||||
if (prevBlock) {
|
||||
setBlockId(prevBlock.id);
|
||||
}
|
||||
}}
|
||||
>
|
||||
❮
|
||||
</span>
|
||||
<div className={imagePreviewModalContainerStyle}>
|
||||
<img
|
||||
data-blob-id={props.blockId}
|
||||
alt={caption}
|
||||
className={imagePreviewModalImageStyle}
|
||||
ref={imageRef}
|
||||
src={url}
|
||||
/>
|
||||
</div>
|
||||
<span
|
||||
className={imagePreviewModalGoStyle}
|
||||
style={{
|
||||
right: 0,
|
||||
}}
|
||||
onClick={() => {
|
||||
assertExists(blockId);
|
||||
const workspace = props.workspace;
|
||||
|
||||
const page = workspace.getPage(props.pageId);
|
||||
assertExists(page);
|
||||
const block = page.getBlockById(blockId);
|
||||
assertExists(block);
|
||||
const nextBlock = page
|
||||
.getNextSiblings(block)
|
||||
.find(
|
||||
(block): block is EmbedBlockModel =>
|
||||
block.flavour === 'affine:embed'
|
||||
);
|
||||
if (nextBlock) {
|
||||
setBlockId(nextBlock.id);
|
||||
}
|
||||
}}
|
||||
>
|
||||
❯
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -9,15 +9,8 @@ export const CopyLink = ({ onItemClick, onSelect }: CommonMenuItemProps) => {
|
||||
const t = useAFFiNEI18N();
|
||||
|
||||
const copyUrl = useCallback(() => {
|
||||
navigator.clipboard
|
||||
.writeText(window.location.href)
|
||||
.then(() => {
|
||||
toast(t['Copied link to clipboard']());
|
||||
})
|
||||
.catch(err => {
|
||||
// TODO add error toast here
|
||||
console.error(err);
|
||||
});
|
||||
navigator.clipboard.writeText(window.location.href);
|
||||
toast(t['Copied link to clipboard']());
|
||||
}, [t]);
|
||||
|
||||
return (
|
||||
|
||||
@@ -35,13 +35,8 @@ const ExportToPdfMenuItem = ({
|
||||
if (result !== undefined) {
|
||||
return;
|
||||
}
|
||||
return contentParser.exportPdf();
|
||||
})
|
||||
.then(() => {
|
||||
contentParser.exportPdf();
|
||||
onSelect?.({ type: 'pdf' });
|
||||
})
|
||||
.catch(err => {
|
||||
console.error(err);
|
||||
});
|
||||
}, [currentEditor, onSelect]);
|
||||
if (currentEditor && currentEditor.mode === 'page') {
|
||||
@@ -71,9 +66,7 @@ const ExportToHtmlMenuItem = ({
|
||||
if (!contentParserRef.current) {
|
||||
contentParserRef.current = new ContentParser(currentEditor.page);
|
||||
}
|
||||
contentParserRef.current.exportHtml().catch(err => {
|
||||
console.error(err);
|
||||
});
|
||||
contentParserRef.current.exportHtml();
|
||||
onSelect?.({ type: 'html' });
|
||||
}, [onSelect, currentEditor]);
|
||||
return (
|
||||
@@ -130,9 +123,7 @@ const ExportToMarkdownMenuItem = ({
|
||||
if (!contentParserRef.current) {
|
||||
contentParserRef.current = new ContentParser(currentEditor.page);
|
||||
}
|
||||
contentParserRef.current.exportMarkdown().catch(err => {
|
||||
console.error(err);
|
||||
});
|
||||
contentParserRef.current.exportMarkdown();
|
||||
onSelect?.({ type: 'markdown' });
|
||||
}, [onSelect, currentEditor]);
|
||||
return (
|
||||
|
||||
@@ -10,11 +10,7 @@ const DesktopThemeSync = memo(function DesktopThemeSync() {
|
||||
const onceRef = useRef(false);
|
||||
if (lastThemeRef.current !== theme || !onceRef.current) {
|
||||
if (environment.isDesktop && theme) {
|
||||
window.apis?.ui
|
||||
.handleThemeChange(theme as 'dark' | 'light' | 'system')
|
||||
.catch(err => {
|
||||
console.error(err);
|
||||
});
|
||||
window.apis?.ui.handleThemeChange(theme as 'dark' | 'light' | 'system');
|
||||
}
|
||||
lastThemeRef.current = theme;
|
||||
onceRef.current = true;
|
||||
|
||||
@@ -8,5 +8,5 @@
|
||||
"devDependencies": {
|
||||
"@types/debug": "^4.1.8"
|
||||
},
|
||||
"version": "0.6.1-beta.0"
|
||||
"version": "0.7.0-canary.13"
|
||||
}
|
||||
|
||||
2
packages/env/package.json
vendored
2
packages/env/package.json
vendored
@@ -28,5 +28,5 @@
|
||||
"dependencies": {
|
||||
"lit": "^2.7.5"
|
||||
},
|
||||
"version": "0.6.1-beta.0"
|
||||
"version": "0.7.0-canary.13"
|
||||
}
|
||||
|
||||
2
packages/env/src/blocksuite/index.ts
vendored
2
packages/env/src/blocksuite/index.ts
vendored
@@ -3,7 +3,7 @@ import type { Page } from '@blocksuite/store';
|
||||
export async function initPageWithPreloading(page: Page) {
|
||||
const workspace = page.workspace;
|
||||
const { data } = await import('@affine/templates/preloading.json');
|
||||
await workspace.importPageSnapshot(data['space:hello-world'], page.id);
|
||||
await workspace.importPageSnapshot(data['space:Qmo9-1SGTB'], page.id);
|
||||
}
|
||||
|
||||
export function initEmptyPage(page: Page): void {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@affine/graphql",
|
||||
"version": "0.6.1-beta.0",
|
||||
"version": "0.7.0-canary.13",
|
||||
"description": "Autogenerated GraphQL client for affine.pro",
|
||||
"license": "MPL-2.0",
|
||||
"type": "module",
|
||||
|
||||
@@ -8,5 +8,5 @@
|
||||
"@affine/env": "workspace:*",
|
||||
"@toeverything/y-indexeddb": "workspace:*"
|
||||
},
|
||||
"version": "0.6.1-beta.0"
|
||||
"version": "0.7.0-canary.13"
|
||||
}
|
||||
|
||||
@@ -36,5 +36,5 @@
|
||||
"ts-node": "^10.9.1",
|
||||
"typescript": "^5.1.3"
|
||||
},
|
||||
"version": "0.6.1-beta.0"
|
||||
"version": "0.7.0-canary.13"
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"Copied link to clipboard": "Link in die Zwischenablage kopiert",
|
||||
"Local Workspace Description": "Alle Daten sind auf dem aktuellen Gerät gespeichert. Du kannst AFFiNE Cloud für diesen Workspace aktivieren, um deine Daten mit der Cloud zu synchronisieren.",
|
||||
"Download all data": "Alle Daten herunterladen",
|
||||
"It takes up little space on your device": "Es verbraucht nur wenig Speicherplatz auf deinem Gerät.",
|
||||
"It takes up little space on your device": "Es nimmt nur wenig Platz auf deinem Gerät ein.",
|
||||
"Help and Feedback": "Hilfe und Feedback",
|
||||
"Not now": "Vielleicht später",
|
||||
"Please make sure you are online": "Bitte stelle sicher, dass du online bist",
|
||||
@@ -189,13 +189,10 @@
|
||||
"Data sync mode": "Daten-Sync Modus",
|
||||
"Download core data": "Core Daten herunterladen",
|
||||
"Check Our Docs": "Sieh dir unsere Dokumentation an",
|
||||
"Get in touch! Join our communities": "Bleib mit uns in Kontakt und trete unseren Communitys bei!",
|
||||
"Get in touch! Join our communities": "Nimm teil! Treten Sie unseren Communities bei.",
|
||||
"Move to Trash": "In Papierkorb verschieben",
|
||||
"Placeholder of delete workspace": "Bitte zur Bestätigung den Workspace-Namen eingeben",
|
||||
"Access level": "Zugriffsberechtigung",
|
||||
"Loading Page": "Lade Seite",
|
||||
"Loading All Workspaces": "Lade alle Workspaces",
|
||||
"Discover what's new!": "Erfahre was neu ist!",
|
||||
"Move to": "Verschieben zu",
|
||||
"Disable": "Deaktivieren",
|
||||
"Open Workspace Settings": "Workspace Einstellungen öffnen",
|
||||
@@ -203,21 +200,18 @@
|
||||
"Workspace Not Found": "Workspace nicht gefunden",
|
||||
"Rename": "Umbenennen",
|
||||
"Page is Loading": "Seite lädt",
|
||||
"Discover what's new!": "Erfahre was neu ist!",
|
||||
"Loading All Workspaces": "Lade alle Workspaces",
|
||||
"Loading Page": "Lade Seite",
|
||||
"Create Shared Link Description": "Erstelle einen Link, den du leicht mit jedem teilen kannst.",
|
||||
"Back to Quick Search": "Zurück zur Schnellsuche",
|
||||
"Disable Public Link": "Öffentlichen Link deaktivieren",
|
||||
"Disable Public Link ?": "Öffentlichen Link deaktivieren ?",
|
||||
"Export Shared Pages Description": "Laden eine statische Kopie dieser Seite herunter, um sie mit anderen zu teilen.",
|
||||
"Favorite pages for easy access": "Favoriten-Seiten für schnellen Zugriff",
|
||||
"Move page to": "Seite verschieben nach...",
|
||||
"Navigation Path": "Navigationspfad",
|
||||
"Pivots": "Pivots",
|
||||
"RFP": "Seiten können frei zu Pivots hinzugefügt/entfernt werden und bleiben über \"Alle Seiten\" zugänglich.",
|
||||
"Remove from Pivots": "Von Pivots entfernen",
|
||||
"Router is Loading": "Router lädt",
|
||||
"Share Menu Public Workspace Description1": "Laden andere ein, dem Workspace beizutreten oder veröffentliche ihn im Internet.",
|
||||
"Share Menu Public Workspace Description2": "Der aktuelle Workspace wurde im Internet als öffentlicher Workspace veröffentlicht.",
|
||||
"View Navigation Path": "Navigationspfad ansehen",
|
||||
"Add a subpage inside": "Unterseite hinzufügen",
|
||||
"Disable Public Link Description": "Wenn du diesen öffentlichen Link deaktivierst, können andere Personen mit diesem Link nicht mehr auf diese Seite zugreifen.",
|
||||
"Disable Public Sharing": "Öffentliche Freigabe deaktivieren",
|
||||
@@ -227,8 +221,58 @@
|
||||
"Shared Pages Description": "Die öffentliche Freigabe der Seite erfordert den AFFiNE-Cloud-Dienst.",
|
||||
"Shared Pages In Public Workspace Description": "Der gesamte Workspace wird im Web veröffentlicht und kann über <1>Workspace Einstellungen</1> bearbeitet werden.",
|
||||
"emptySharedPages": "Freigegebene Seiten werden hier angezeigt.",
|
||||
"Recent": "Neueste",
|
||||
"Synced with AFFiNE Cloud": "Synchronisiert mit AFFiNE Cloud",
|
||||
"Successfully deleted": "Erfolgreich gelöscht",
|
||||
"You cannot delete the last workspace": "Du kannst den letzten Workspace nicht löschen"
|
||||
"You cannot delete the last workspace": "Du kannst den letzten Workspace nicht löschen",
|
||||
"Move page to": "Seite verschieben nach...",
|
||||
"Navigation Path": "Navigationspfad",
|
||||
"Recent": "Neueste",
|
||||
"Export Shared Pages Description": "Laden eine statische Kopie dieser Seite herunter, um sie mit anderen zu teilen.",
|
||||
"Share Menu Public Workspace Description1": "Laden andere ein, dem Workspace beizutreten oder veröffentliche ihn im Internet.",
|
||||
"Share Menu Public Workspace Description2": "Der aktuelle Workspace wurde im Internet als öffentlicher Workspace veröffentlicht.",
|
||||
"View Navigation Path": "Navigationspfad ansehen",
|
||||
"Delete Workspace Label Hint": "Wenn dieser Workspace gelöscht wird, wird sein gesamter Inhalt für alle Benutzer dauerhaft gelöscht. Niemand wird in der Lage sein, den Inhalt dieses Workspaces wiederherzustellen.",
|
||||
"Added Successfully": "Erfolgreich hinzugefügt",
|
||||
"Continue": "Fortfahren",
|
||||
"Create your own workspace": "Eigenen Workspace erstellen",
|
||||
"Created Successfully": "Erfolgreich erstellt",
|
||||
"Customize": "Anpassen",
|
||||
"FILE_ALREADY_EXISTS": "Datei existiert bereits",
|
||||
"Move folder": "Ordner verschieben",
|
||||
"Move folder hint": "Neuen Speicherort auswählen.",
|
||||
"Add Workspace Hint": "Auswählen, was du schon hast",
|
||||
"Change avatar hint": "Avatar von allen Mitgliedern ändern.",
|
||||
"Change workspace name hint": "Name von allen Mitgliedern ändern.",
|
||||
"DB_FILE_ALREADY_LOADED": "Datenbankdatei bereits geladen",
|
||||
"DB_FILE_INVALID": "Ungültige Datenbankdatei",
|
||||
"DB_FILE_PATH_INVALID": "Pfad der Datenbankdatei ungültig",
|
||||
"Default Location": "Standard-Speicherort",
|
||||
"Default db location hint": "Standardmäßig wird unter {{location}} gespeichert.",
|
||||
"Move folder success": "Ordnerverschiebung erfolgreich",
|
||||
"Open folder": "Ordner öffnen",
|
||||
"Save": "Speichern",
|
||||
"Set database location": "Datenbankstandort festlegen",
|
||||
"UNKNOWN_ERROR": "Unbekannter Fehler",
|
||||
"Open folder hint": "Prüfe, wo sich der Speicherordner befindet.",
|
||||
"Storage Folder": "Speicherordner",
|
||||
"Storage Folder Hint": "Speicherort überprüfen oder ändern.",
|
||||
"Sync across devices with AFFiNE Cloud": "Geräteübergreifende Synchronisierung mit AFFiNE Cloud",
|
||||
"Name Your Workspace": "Workspace benennen",
|
||||
"Update Available": "Update verfügbar",
|
||||
"com.affine.edgelessMode": "Edgeless-Modus",
|
||||
"com.affine.onboarding.title2": "Intuitive und robuste, blockbasierte Bearbeitung",
|
||||
"com.affine.onboarding.videoDescription1": "Wechsle mühelos zwischen dem Seitenmodus für die strukturierte Dokumentenerstellung und dem Whiteboard-Modus für den Ausdruck kreativer Ideen in freier Form.",
|
||||
"com.affine.onboarding.videoDescription2": "Verwende eine modulare Schnittstelle, um strukturierte Dokumente zu erstellen, indem du Textblöcke, Bilder und andere Inhalte einfach per Drag-and-drop anordnen kannst.",
|
||||
"com.affine.onboarding.title1": "Hyperfusion von Whiteboard und Dokumenten",
|
||||
"com.affine.pageMode": "Seitenmodus",
|
||||
"Update workspace name success": "Update vom Workspace-Namen erfolgreich",
|
||||
"Use on current device only": "Nur auf dem aktuellen Gerät verwenden",
|
||||
"Workspace database storage description": "Wähle den Ort, an dem du deinen Workspace erstellen möchten. Die Daten vom Workspace werden standardmäßig lokal gespeichert.",
|
||||
"dark": "dunkel",
|
||||
"system": "system",
|
||||
"Restart Install Client Update": "Neustart zum Installieren des Updates",
|
||||
"Add Workspace": "Workspace hinzufügen",
|
||||
"Export success": "Export erfolgreich",
|
||||
"light": "hell",
|
||||
"others": "Andere"
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
"No item": "No item",
|
||||
"Import": "Import",
|
||||
"Trash": "Trash",
|
||||
"others": "Others",
|
||||
"New Page": "New Page",
|
||||
"com.affine.write_with_a_blank_page": "Write with a blank page",
|
||||
"com.affine.new_edgeless": "New Edgeless",
|
||||
@@ -266,16 +265,12 @@
|
||||
"Move folder hint": "Select a new storage location.",
|
||||
"Storage Folder": "Storage Folder",
|
||||
"DB_FILE_INVALID": "Invalid Database file",
|
||||
"FILE_ALREADY_EXISTS": "File already exists",
|
||||
"Name Your Workspace": "Name Your Workspace",
|
||||
"Change avatar hint": "New avatar will be shown for everyone.",
|
||||
"Change workspace name hint": "New name will be shown for everyone.",
|
||||
"Delete Workspace Label Hint": "After deleting this Workspace, you will permanently delete all of its content for everyone. No one will be able to recover the content of this Workspace.",
|
||||
"DB_FILE_PATH_INVALID": "Database file path invalid",
|
||||
"Default db location hint": "By default will be saved to {{location}}",
|
||||
"light": "light",
|
||||
"dark": "dark",
|
||||
"system": "system",
|
||||
"com.affine.pageMode": "Page Mode",
|
||||
"com.affine.edgelessMode": "Edgeless Mode",
|
||||
"com.affine.onboarding.title1": "Hyper merged whiteboard and docs",
|
||||
|
||||
@@ -12,13 +12,13 @@
|
||||
"Retain cached cloud data": "保留缓存的云数据",
|
||||
"Workspace Owner": "工作区所有者",
|
||||
"Cloud Workspace": "云端工作区",
|
||||
"Cloud Workspace Description": "所有数据将被同步并保存在AFFiNE账户(<1>{{email}}</1>)中",
|
||||
"Copied link to clipboard": "复制链接到剪贴板",
|
||||
"Available Offline": "可供离线使用",
|
||||
"Back Home": "返回首页",
|
||||
"Enabled success": "启用成功",
|
||||
"Published Description": "当前工作区已被发布到Web,所有人都可以通过链接来查看此工作区内容。",
|
||||
"All data has been stored in the cloud": "所有数据已被保存在云端。",
|
||||
"Cloud Workspace Description": "所有数据将被同步并保存在 AFFiNE 账户(<1>{{email}}</1>)中",
|
||||
"Published Description": "当前工作区已被发布到 Web,所有人都可以通过链接来查看此工作区内容。",
|
||||
"Download data": "下载 {{CoreOrAll}} 数据",
|
||||
"Force Sign Out": "强制登出",
|
||||
"Joined Workspace": "加入工作区",
|
||||
@@ -73,18 +73,15 @@
|
||||
"Access level": "访问权限",
|
||||
"Added to Favorites": "已收藏",
|
||||
"Collaboration": "协作",
|
||||
"Collaboration Description": "与其他成员协作需要AFFiNE云服务支持。",
|
||||
"Continue with Google": "谷歌登录以继续",
|
||||
"Delete page?": "确定要删除页面?",
|
||||
"Delete permanently": "永久删除",
|
||||
"Delete permanently?": "是否永久删除?",
|
||||
"Edgeless": "无界",
|
||||
"Enable AFFiNE Cloud": "启用 AFFiNE 云服务",
|
||||
"Enable AFFiNE Cloud Description": "如启用,此工作区中的数据将通过AFFiNE Cloud进行备份和同步。",
|
||||
"Favorites": "收藏夹",
|
||||
"Get in touch!": "保持联络!",
|
||||
"Got it": "知道了",
|
||||
"How is AFFiNE Alpha different?": "AFFiNE Alpha有何不同?",
|
||||
"Invite": "邀请",
|
||||
"Invite Members": "邀请成员",
|
||||
"Invite placeholder": "搜索邮件(仅支持Gmail)",
|
||||
@@ -94,12 +91,16 @@
|
||||
"Leave Workspace": "退出工作区",
|
||||
"Leave Workspace Description": "退出后,您将无法再访问此工作区的内容。",
|
||||
"Link": "超链接(选定文本)",
|
||||
"Collaboration Description": "与其他成员协作需要 AFFiNE 云服务支持。",
|
||||
"Moved to Trash": "已移到垃圾箱",
|
||||
"My Workspaces": "我的工作区",
|
||||
"Enable AFFiNE Cloud Description": "如启用,此工作区中的数据将通过 AFFiNE Cloud 进行备份和同步。",
|
||||
"How is AFFiNE Alpha different?": "AFFiNE Alpha 有何不同?",
|
||||
"Non-Gmail": "不支持非 Gmail 邮箱",
|
||||
"Publishing": "发布到 web 需要 AFFiNE 云服务。",
|
||||
"New Page": "新建页面",
|
||||
"New Workspace": "新建工作区",
|
||||
"No item": "无项目",
|
||||
"Non-Gmail": "不支持非Gmail邮箱",
|
||||
"NotLoggedIn": "当前未登录",
|
||||
"Official Website": "官网",
|
||||
"Once deleted, you can't undo this action": "一旦删除,您将无法撤销此操作。",
|
||||
@@ -115,7 +116,6 @@
|
||||
"Pending": "待定",
|
||||
"Permanently deleted": "已永久删除",
|
||||
"Publish": "发布",
|
||||
"Publishing": "发布到web需要AFFiNE云服务。",
|
||||
"Publish to web": "发布到web",
|
||||
"Quick search": "快速搜索",
|
||||
"Quick search placeholder": "快速搜索...",
|
||||
|
||||
@@ -28,5 +28,5 @@
|
||||
"vite": "^4.3.9",
|
||||
"vite-plugin-dts": "^2.3.0"
|
||||
},
|
||||
"version": "0.6.1-beta.0"
|
||||
"version": "0.7.0-canary.13"
|
||||
}
|
||||
|
||||
@@ -21,5 +21,5 @@
|
||||
"@blocksuite/store": "*",
|
||||
"lottie-web": "*"
|
||||
},
|
||||
"version": "0.6.1-beta.0"
|
||||
"version": "0.7.0-canary.13"
|
||||
}
|
||||
|
||||
@@ -35,5 +35,5 @@
|
||||
"test": "cross-env TS_NODE_TRANSPILE_ONLY=1 TS_NODE_PROJECT=./tsconfig.json node --test --loader ts-node/esm --experimental-specifier-resolution=node ./__tests__/**/*.mts",
|
||||
"version": "napi version"
|
||||
},
|
||||
"version": "0.6.1-beta.0"
|
||||
"version": "0.7.0-canary.13"
|
||||
}
|
||||
|
||||
@@ -22,8 +22,7 @@
|
||||
"@blocksuite/editor": "0.0.0-20230607055421-9b20fcaf-nightly",
|
||||
"@blocksuite/global": "0.0.0-20230607055421-9b20fcaf-nightly",
|
||||
"@blocksuite/lit": "0.0.0-20230607055421-9b20fcaf-nightly",
|
||||
"@blocksuite/store": "0.0.0-20230607055421-9b20fcaf-nightly",
|
||||
"jotai": "^2.1.1"
|
||||
"@blocksuite/store": "0.0.0-20230607055421-9b20fcaf-nightly"
|
||||
},
|
||||
"devDependencies": {
|
||||
"jotai": "^2.1.1",
|
||||
@@ -40,5 +39,5 @@
|
||||
"react": "*",
|
||||
"react-dom": "*"
|
||||
},
|
||||
"version": "0.6.1-beta.0"
|
||||
"version": "0.7.0-canary.13"
|
||||
}
|
||||
|
||||
@@ -32,21 +32,15 @@ export function definePlugin<ID extends string>(
|
||||
|
||||
if (isServer) {
|
||||
if (serverAdapter) {
|
||||
console.log('register server adapter');
|
||||
serverAdapter
|
||||
.load()
|
||||
.then(({ default: adapter }) => {
|
||||
rootStore.set(affinePluginsAtom, plugins => ({
|
||||
...plugins,
|
||||
[definition.id]: {
|
||||
...basePlugin,
|
||||
serverAdapter: adapter,
|
||||
},
|
||||
}));
|
||||
})
|
||||
.catch(err => {
|
||||
console.error(err);
|
||||
});
|
||||
serverAdapter.load().then(({ default: adapter }) => {
|
||||
rootStore.set(affinePluginsAtom, plugins => ({
|
||||
...plugins,
|
||||
[definition.id]: {
|
||||
...basePlugin,
|
||||
serverAdapter: adapter,
|
||||
},
|
||||
}));
|
||||
});
|
||||
}
|
||||
} else if (isClient) {
|
||||
if (blockSuiteAdapter) {
|
||||
|
||||
@@ -47,5 +47,5 @@
|
||||
"@blocksuite/lit": "*",
|
||||
"@blocksuite/store": "*"
|
||||
},
|
||||
"version": "0.6.1-beta.0"
|
||||
"version": "0.7.0-canary.13"
|
||||
}
|
||||
|
||||
@@ -6,5 +6,5 @@
|
||||
"./*.md": "./*.md",
|
||||
"./preloading.json": "./preloading.json"
|
||||
},
|
||||
"version": "0.6.1-beta.0"
|
||||
"version": "0.7.0-canary.13"
|
||||
}
|
||||
|
||||
@@ -3,15 +3,12 @@
|
||||
"version": 1,
|
||||
"data": {
|
||||
"space:meta": {
|
||||
"name": "Demo Workspace",
|
||||
"pages": [
|
||||
{
|
||||
"id": "hello-world",
|
||||
"id": "Qmo9-1SGTB",
|
||||
"title": "AFFiNE - not just a note taking app",
|
||||
"createDate": 1686627549555,
|
||||
"subpageIds": [],
|
||||
"jumpOnce": false,
|
||||
"updatedDate": 1686627553606
|
||||
"createDate": 1685676956753,
|
||||
"subpageIds": []
|
||||
}
|
||||
],
|
||||
"versions": {
|
||||
@@ -27,15 +24,15 @@
|
||||
"affine:database": 1
|
||||
}
|
||||
},
|
||||
"space:hello-world": {
|
||||
"space:Qmo9-1SGTB": {
|
||||
"_9D75ibqvd": {
|
||||
"sys:id": "_9D75ibqvd",
|
||||
"sys:flavour": "affine:page",
|
||||
"sys:children": [
|
||||
"4-IQVC-U5A",
|
||||
"Y4oz3g1LB6",
|
||||
"VNbg-Wz6Vs",
|
||||
"V7dUwRJxpY",
|
||||
"Y4oz3g1LB6",
|
||||
"1cFTd-rwDr",
|
||||
"A2hTNhHJSo",
|
||||
"JSoC9zIZDz",
|
||||
@@ -60,15 +57,15 @@
|
||||
],
|
||||
"prop:background": "--affine-background-secondary-color",
|
||||
"prop:index": "a2",
|
||||
"prop:xywh": "[866.5055790704506,86.14140870095756,326.7016703680564,356]"
|
||||
"prop:xywh": "[866.5055790704506,86.14140870095756,326.7016703680564,500]"
|
||||
},
|
||||
"VNbg-Wz6Vs": {
|
||||
"sys:id": "VNbg-Wz6Vs",
|
||||
"sys:flavour": "affine:frame",
|
||||
"sys:children": ["hiVj6pUziI", "6rgGQmAmfb", "KRefAQRNnh"],
|
||||
"sys:children": ["Prrnq7ruGC", "6rgGQmAmfb", "KRefAQRNnh"],
|
||||
"prop:index": "a0",
|
||||
"prop:background": "--affine-tag-green",
|
||||
"prop:xywh": "[1211.9913594556406,86.0748937043449,552.5830233754074,796]"
|
||||
"prop:xywh": "[1211.9913594556406,86.0748937043449,552.5830233754074,572]"
|
||||
},
|
||||
"V7dUwRJxpY": {
|
||||
"sys:id": "V7dUwRJxpY",
|
||||
@@ -5910,16 +5907,16 @@
|
||||
"Y4oz3g1LB6": {
|
||||
"sys:id": "Y4oz3g1LB6",
|
||||
"sys:flavour": "affine:frame",
|
||||
"sys:children": ["Prrnq7ruGC"],
|
||||
"prop:xywh": "[855.7586305793726,-38.93174493636967,1488.043436415603,104]",
|
||||
"sys:children": ["aPk03I3k9L"],
|
||||
"prop:xywh": "[855.7586305793726,-38.93174493636967,1488.043436415603,112]",
|
||||
"prop:index": "a0",
|
||||
"prop:background": "--affine-tag-yellow"
|
||||
},
|
||||
"1cFTd-rwDr": {
|
||||
"sys:id": "1cFTd-rwDr",
|
||||
"sys:flavour": "affine:frame",
|
||||
"sys:children": ["aPk03I3k9L", "4_plt-pF5i", "5O-z_KtfdV"],
|
||||
"prop:xywh": "[1782.1527708473825,83.59728260421294,554.4267667459387,668]",
|
||||
"sys:children": ["2NKIdhpZZy", "4_plt-pF5i", "5O-z_KtfdV"],
|
||||
"prop:xywh": "[1782.1527708473825,83.59728260421294,554.4267667459387,573]",
|
||||
"prop:index": "a0",
|
||||
"prop:background": "--affine-tag-blue"
|
||||
},
|
||||
@@ -5927,7 +5924,7 @@
|
||||
"sys:id": "A2hTNhHJSo",
|
||||
"sys:flavour": "affine:frame",
|
||||
"sys:children": ["1t5gAmmDk1", "Ru5RZxl2cw", "m09CQTVNta"],
|
||||
"prop:xywh": "[1862.2162713385649,667.8687461185463,471.2475208977704,724]",
|
||||
"prop:xywh": "[1862.2162713385649,667.8687461185463,471.2475208977704,569]",
|
||||
"prop:index": "a0",
|
||||
"prop:background": "--affine-tag-red"
|
||||
},
|
||||
@@ -5937,13 +5934,13 @@
|
||||
"sys:children": ["RYwAAsT0jt", "yui0v4a-DG", "CuW0As_WD5"],
|
||||
"prop:index": "a0",
|
||||
"prop:background": "--affine-tag-purple",
|
||||
"prop:xywh": "[1310.31891616522,676.1486476697154,537.1322406806248,724]"
|
||||
"prop:xywh": "[1310.31891616522,676.1486476697154,537.1322406806248,561]"
|
||||
},
|
||||
"Vq_8QO3ruz": {
|
||||
"sys:id": "Vq_8QO3ruz",
|
||||
"sys:flavour": "affine:frame",
|
||||
"sys:children": ["Z6tZpqYD1i", "cSq4fYa62E", "e-ekSJPKh0"],
|
||||
"prop:xywh": "[824.3933427871591,677.7709857969486,475.6451530544002,724]",
|
||||
"prop:xywh": "[824.3933427871591,677.7709857969486,475.6451530544002,542]",
|
||||
"prop:index": "a0",
|
||||
"prop:background": "--affine-tag-blue"
|
||||
},
|
||||
@@ -5954,16 +5951,17 @@
|
||||
"YQPpZUitL9",
|
||||
"jNb1ieggGw",
|
||||
"yln9MU-iVm",
|
||||
"z1fWcxw9qe",
|
||||
"rY1fVETRzE"
|
||||
],
|
||||
"prop:index": "a0",
|
||||
"prop:background": "--affine-tag-green",
|
||||
"prop:xywh": "[817.0745095091336,1272.4084873924633,586.3018678030073,922]"
|
||||
"prop:xywh": "[817.0745095091336,1272.4084873924633,586.3018678030073,672]"
|
||||
},
|
||||
"3An3wRFKN_": {
|
||||
"sys:id": "3An3wRFKN_",
|
||||
"sys:flavour": "affine:frame",
|
||||
"sys:children": ["KZrhdN52ZD", "3MnKwqEw_Q"],
|
||||
"sys:children": ["3MnKwqEw_Q"],
|
||||
"prop:xywh": "[-264.94381566608683,389.00823320424837,494.2811077047478,314]",
|
||||
"prop:index": "a2",
|
||||
"prop:background": "--affine-background-secondary-color"
|
||||
@@ -5972,7 +5970,7 @@
|
||||
"sys:id": "U2hR9Lu1E7",
|
||||
"sys:flavour": "affine:frame",
|
||||
"sys:children": ["LYes52XNDN"],
|
||||
"prop:xywh": "[2918.2644723261433,881.0630462339941,539.4086027654356,655]",
|
||||
"prop:xywh": "[2918.2644723261433,881.0630462339941,539.4086027654356,439]",
|
||||
"prop:index": "a2",
|
||||
"prop:background": "--affine-background-secondary-color"
|
||||
},
|
||||
@@ -5980,7 +5978,7 @@
|
||||
"sys:id": "nOERveFG0j",
|
||||
"sys:flavour": "affine:frame",
|
||||
"sys:children": ["SjyfxmcAjc"],
|
||||
"prop:xywh": "[2919.8341116576826,1349.0080470072992,535.7138283708327,632]",
|
||||
"prop:xywh": "[2919.8341116576826,1349.0080470072992,535.7138283708327,451]",
|
||||
"prop:index": "a2",
|
||||
"prop:background": "--affine-background-secondary-color"
|
||||
},
|
||||
@@ -6060,17 +6058,8 @@
|
||||
"sys:id": "Prrnq7ruGC",
|
||||
"sys:flavour": "affine:paragraph",
|
||||
"sys:children": [],
|
||||
"prop:type": "h1",
|
||||
"prop:text": [
|
||||
{ "insert": "Let's " },
|
||||
{ "insert": "Write", "attributes": { "bold": true } },
|
||||
{ "insert": ", " },
|
||||
{ "insert": "Draw", "attributes": { "bold": true } },
|
||||
{ "insert": " and " },
|
||||
{ "insert": "Plan", "attributes": { "bold": true } },
|
||||
{ "insert": " with " },
|
||||
{ "insert": "AFFiNE", "attributes": { "bold": true } }
|
||||
]
|
||||
"prop:type": "h3",
|
||||
"prop:text": [{ "insert": "Create Your Workspace" }]
|
||||
},
|
||||
"6rgGQmAmfb": {
|
||||
"sys:id": "6rgGQmAmfb",
|
||||
@@ -6087,6 +6076,22 @@
|
||||
"sys:id": "aPk03I3k9L",
|
||||
"sys:flavour": "affine:paragraph",
|
||||
"sys:children": [],
|
||||
"prop:type": "h2",
|
||||
"prop:text": [
|
||||
{ "insert": "Let's " },
|
||||
{ "insert": "Write", "attributes": { "bold": true } },
|
||||
{ "insert": ", " },
|
||||
{ "insert": "Draw", "attributes": { "bold": true } },
|
||||
{ "insert": " and " },
|
||||
{ "insert": "Plan", "attributes": { "bold": true } },
|
||||
{ "insert": " with " },
|
||||
{ "insert": "AFFiNE", "attributes": { "bold": true } }
|
||||
]
|
||||
},
|
||||
"2NKIdhpZZy": {
|
||||
"sys:id": "2NKIdhpZZy",
|
||||
"sys:flavour": "affine:paragraph",
|
||||
"sys:children": [],
|
||||
"prop:type": "h3",
|
||||
"prop:text": [{ "insert": "Organise Your Pages" }]
|
||||
},
|
||||
@@ -6191,8 +6196,8 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"KZrhdN52ZD": {
|
||||
"sys:id": "KZrhdN52ZD",
|
||||
"z1fWcxw9qe": {
|
||||
"sys:id": "z1fWcxw9qe",
|
||||
"sys:flavour": "affine:divider",
|
||||
"sys:children": []
|
||||
},
|
||||
@@ -6316,8 +6321,8 @@
|
||||
"prop:width": 0,
|
||||
"prop:height": 0
|
||||
},
|
||||
"5O-z_KtfdV": {
|
||||
"sys:id": "5O-z_KtfdV",
|
||||
"rY1fVETRzE": {
|
||||
"sys:id": "rY1fVETRzE",
|
||||
"sys:flavour": "affine:embed",
|
||||
"sys:children": [],
|
||||
"prop:type": "image",
|
||||
@@ -6326,8 +6331,8 @@
|
||||
"prop:width": 0,
|
||||
"prop:height": 0
|
||||
},
|
||||
"m09CQTVNta": {
|
||||
"sys:id": "m09CQTVNta",
|
||||
"e-ekSJPKh0": {
|
||||
"sys:id": "e-ekSJPKh0",
|
||||
"sys:flavour": "affine:embed",
|
||||
"sys:children": [],
|
||||
"prop:type": "image",
|
||||
@@ -6346,8 +6351,8 @@
|
||||
"prop:width": 0,
|
||||
"prop:height": 0
|
||||
},
|
||||
"e-ekSJPKh0": {
|
||||
"sys:id": "e-ekSJPKh0",
|
||||
"5O-z_KtfdV": {
|
||||
"sys:id": "5O-z_KtfdV",
|
||||
"sys:flavour": "affine:embed",
|
||||
"sys:children": [],
|
||||
"prop:type": "image",
|
||||
@@ -6356,8 +6361,8 @@
|
||||
"prop:width": 0,
|
||||
"prop:height": 0
|
||||
},
|
||||
"rY1fVETRzE": {
|
||||
"sys:id": "rY1fVETRzE",
|
||||
"m09CQTVNta": {
|
||||
"sys:id": "m09CQTVNta",
|
||||
"sys:flavour": "affine:embed",
|
||||
"sys:children": [],
|
||||
"prop:type": "image",
|
||||
@@ -6366,32 +6371,25 @@
|
||||
"prop:width": 0,
|
||||
"prop:height": 0
|
||||
},
|
||||
"LYes52XNDN": {
|
||||
"sys:id": "LYes52XNDN",
|
||||
"sys:flavour": "affine:embed",
|
||||
"sys:children": [],
|
||||
"prop:type": "image",
|
||||
"prop:sourceId": "https://cdn.affine.pro/047ebf2c9a5c7c9d8521c2ea5e6140ff7732ef9e28a9f944e9bf3ca4.png",
|
||||
"prop:caption": "",
|
||||
"prop:width": 0,
|
||||
"prop:height": 0
|
||||
},
|
||||
"SjyfxmcAjc": {
|
||||
"sys:id": "SjyfxmcAjc",
|
||||
"sys:flavour": "affine:embed",
|
||||
"sys:children": [],
|
||||
"prop:type": "image",
|
||||
"prop:sourceId": "https://cdn.affine.pro/6aa785ee927547ce9dd9d7b43e01eac948337fe57571443e87bc3a60.png",
|
||||
"prop:sourceId": "https://cdn.affine.pro/047ebf2c9a5c7c9d8521c2ea5e6140ff7732ef9e28a9f944e9bf3ca4.png",
|
||||
"prop:caption": "",
|
||||
"prop:width": 0,
|
||||
"prop:height": 0
|
||||
},
|
||||
"hiVj6pUziI": {
|
||||
"sys:id": "hiVj6pUziI",
|
||||
"sys:flavour": "affine:paragraph",
|
||||
"LYes52XNDN": {
|
||||
"sys:id": "LYes52XNDN",
|
||||
"sys:flavour": "affine:embed",
|
||||
"sys:children": [],
|
||||
"prop:text": [{ "insert": "Create Your Workspace" }],
|
||||
"prop:type": "h3"
|
||||
"prop:type": "image",
|
||||
"prop:sourceId": "https://cdn.affine.pro/6aa785ee927547ce9dd9d7b43e01eac948337fe57571443e87bc3a60.png",
|
||||
"prop:caption": "",
|
||||
"prop:width": 0,
|
||||
"prop:height": 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,5 +40,5 @@
|
||||
"next": "=13.4.2",
|
||||
"ws": "^8.13.0"
|
||||
},
|
||||
"version": "0.6.1-beta.0"
|
||||
"version": "0.7.0-canary.13"
|
||||
}
|
||||
|
||||
@@ -207,12 +207,10 @@ export function createAffineAuth(prefix = '/') {
|
||||
}),
|
||||
}).then(r => r.json()) as Promise<LoginResponse>;
|
||||
} catch (error) {
|
||||
if (
|
||||
error instanceof Error &&
|
||||
'code' in error &&
|
||||
error.code === 'auth/popup-closed-by-user'
|
||||
) {
|
||||
return null;
|
||||
if (error instanceof Error && 'code' in error) {
|
||||
if (error.code === 'auth/popup-closed-by-user') {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
logger.error('Failed to sign in', error);
|
||||
}
|
||||
|
||||
@@ -171,9 +171,7 @@ const createSQLiteProvider = (
|
||||
if (origin === sqliteOrigin) {
|
||||
return;
|
||||
}
|
||||
apis.db.applyDocUpdate(blockSuiteWorkspace.id, update).catch(err => {
|
||||
console.error(err);
|
||||
});
|
||||
apis.db.applyDocUpdate(blockSuiteWorkspace.id, update);
|
||||
}
|
||||
|
||||
let unsubscribe = () => {};
|
||||
@@ -249,7 +247,7 @@ const createSQLiteDBDownloadProvider = (
|
||||
const diff = Y.encodeStateAsUpdate(blockSuiteWorkspace.doc, updates);
|
||||
|
||||
// also apply updates to sqlite
|
||||
await apis.db.applyDocUpdate(blockSuiteWorkspace.id, diff);
|
||||
apis.db.applyDocUpdate(blockSuiteWorkspace.id, diff);
|
||||
|
||||
const bs = blockSuiteWorkspace.blobs;
|
||||
|
||||
|
||||
@@ -1,15 +1,7 @@
|
||||
{
|
||||
"name": "@toeverything/y-indexeddb",
|
||||
"type": "module",
|
||||
"version": "0.6.1-beta.0",
|
||||
"description": "IndexedDB database adapter for Yjs",
|
||||
"repository": "toeverything/AFFiNE",
|
||||
"author": "toeverything",
|
||||
"keywords": [
|
||||
"indexeddb",
|
||||
"yjs",
|
||||
"yjs-adapter"
|
||||
],
|
||||
"version": "0.7.0-canary.13",
|
||||
"scripts": {
|
||||
"build": "vite build"
|
||||
},
|
||||
@@ -36,13 +28,14 @@
|
||||
"idb": "^7.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@blocksuite/blocks": "0.0.0-20230613142146-d72d4600-nightly",
|
||||
"@blocksuite/store": "0.0.0-20230613142146-d72d4600-nightly",
|
||||
"@blocksuite/blocks": "0.0.0-20230607055421-9b20fcaf-nightly",
|
||||
"@blocksuite/store": "0.0.0-20230607055421-9b20fcaf-nightly",
|
||||
"vite": "^4.3.9",
|
||||
"vite-plugin-dts": "^2.3.0",
|
||||
"y-indexeddb": "^9.0.11"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"yjs": "^13.5.51"
|
||||
}
|
||||
},
|
||||
"stableVersion": "0.5.2"
|
||||
}
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
*/
|
||||
import 'fake-indexeddb/auto';
|
||||
|
||||
import { initEmptyPage } from '@affine/env/blocksuite';
|
||||
import { __unstableSchemas, AffineSchemas } from '@blocksuite/blocks/models';
|
||||
import type { Page } from '@blocksuite/store';
|
||||
import { assertExists, uuidv4, Workspace } from '@blocksuite/store';
|
||||
import { openDB } from 'idb';
|
||||
import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest';
|
||||
@@ -24,21 +24,6 @@ import {
|
||||
setMergeCount,
|
||||
} from '../index';
|
||||
|
||||
function initEmptyPage(page: Page) {
|
||||
const pageBlockId = page.addBlock('affine:page', {
|
||||
title: new page.Text(''),
|
||||
});
|
||||
const surfaceBlockId = page.addBlock('affine:surface', {}, pageBlockId);
|
||||
const frameBLockId = page.addBlock('affine:frame', {}, pageBlockId);
|
||||
const paragraphBlockId = page.addBlock('affine:paragraph', {}, frameBLockId);
|
||||
return {
|
||||
pageBlockId,
|
||||
surfaceBlockId,
|
||||
frameBLockId,
|
||||
paragraphBlockId,
|
||||
};
|
||||
}
|
||||
|
||||
async function getUpdates(id: string): Promise<Uint8Array[]> {
|
||||
const db = await openDB(rootDBName, dbVersion);
|
||||
const store = await db
|
||||
@@ -88,8 +73,7 @@ describe('indexeddb provider', () => {
|
||||
},
|
||||
],
|
||||
});
|
||||
const page = workspace.createPage({ id: 'page0' });
|
||||
await page.waitForLoaded();
|
||||
const page = workspace.createPage('page0');
|
||||
const pageBlockId = page.addBlock('affine:page', { title: '' });
|
||||
const frameId = page.addBlock('affine:frame', {}, pageBlockId);
|
||||
page.addBlock('affine:paragraph', {}, frameId);
|
||||
@@ -159,8 +143,7 @@ describe('indexeddb provider', () => {
|
||||
provider.disconnect();
|
||||
expect(provider.connected).toBe(false);
|
||||
{
|
||||
const page = workspace.createPage({ id: 'page0' });
|
||||
await page.waitForLoaded();
|
||||
const page = workspace.createPage('page0');
|
||||
const pageBlockId = page.addBlock('affine:page', { title: '' });
|
||||
const frameId = page.addBlock('affine:frame', {}, pageBlockId);
|
||||
page.addBlock('affine:paragraph', {}, frameId);
|
||||
@@ -231,11 +214,10 @@ describe('indexeddb provider', () => {
|
||||
);
|
||||
provider.connect();
|
||||
{
|
||||
const page = workspace.createPage({ id: 'page0' });
|
||||
await page.waitForLoaded();
|
||||
const page = workspace.createPage('page0');
|
||||
const pageBlockId = page.addBlock('affine:page', { title: '' });
|
||||
const frameId = page.addBlock('affine:frame', {}, pageBlockId);
|
||||
for (let i = 0; i < 99; i++) {
|
||||
for (let i = 0; i < 100; i++) {
|
||||
page.addBlock('affine:paragraph', {}, frameId);
|
||||
}
|
||||
}
|
||||
@@ -390,89 +372,9 @@ describe('milestone', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('subDoc', () => {
|
||||
test('basic', async () => {
|
||||
let json1: any, json2: any;
|
||||
{
|
||||
const doc = new Doc();
|
||||
const map = doc.getMap();
|
||||
const subDoc = new Doc();
|
||||
subDoc.load();
|
||||
map.set('1', subDoc);
|
||||
map.set('2', 'test');
|
||||
const provider = createIndexedDBProvider('test', doc);
|
||||
provider.connect();
|
||||
await provider.whenSynced;
|
||||
provider.disconnect();
|
||||
json1 = doc.toJSON();
|
||||
}
|
||||
{
|
||||
const doc = new Doc();
|
||||
const provider = createIndexedDBProvider('test', doc);
|
||||
provider.connect();
|
||||
await provider.whenSynced;
|
||||
const map = doc.getMap();
|
||||
const subDoc = map.get('1') as Doc;
|
||||
subDoc.load();
|
||||
provider.disconnect();
|
||||
json2 = doc.toJSON();
|
||||
}
|
||||
expect(json1['']['1'].toJSON()).toEqual(json2['']['1'].toJSON());
|
||||
expect(json1['']['2']).toEqual(json2['']['2']);
|
||||
});
|
||||
|
||||
test('blocksuite', async () => {
|
||||
const page0 = workspace.createPage({
|
||||
id: 'page0',
|
||||
});
|
||||
await page0.waitForLoaded();
|
||||
const { paragraphBlockId: paragraphBlockIdPage1 } = initEmptyPage(page0);
|
||||
const provider = createIndexedDBProvider(
|
||||
workspace.id,
|
||||
workspace.doc,
|
||||
rootDBName
|
||||
);
|
||||
provider.connect();
|
||||
const page1 = workspace.createPage({
|
||||
id: 'page1',
|
||||
});
|
||||
await page1.waitForLoaded();
|
||||
const { paragraphBlockId: paragraphBlockIdPage2 } = initEmptyPage(page1);
|
||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
provider.disconnect();
|
||||
{
|
||||
const newWorkspace = new Workspace({
|
||||
id,
|
||||
isSSR: true,
|
||||
});
|
||||
newWorkspace.register(AffineSchemas).register(__unstableSchemas);
|
||||
const provider = createIndexedDBProvider(
|
||||
newWorkspace.id,
|
||||
newWorkspace.doc,
|
||||
rootDBName
|
||||
);
|
||||
provider.connect();
|
||||
await provider.whenSynced;
|
||||
const page0 = newWorkspace.getPage('page0') as Page;
|
||||
await page0.waitForLoaded();
|
||||
{
|
||||
const block = page0.getBlockById(paragraphBlockIdPage1);
|
||||
assertExists(block);
|
||||
}
|
||||
const page1 = newWorkspace.getPage('page1') as Page;
|
||||
await page1.waitForLoaded();
|
||||
{
|
||||
const block = page1.getBlockById(paragraphBlockIdPage2);
|
||||
assertExists(block);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('utils', () => {
|
||||
test('download binary', async () => {
|
||||
const page = workspace.createPage({ id: 'page0' });
|
||||
await page.waitForLoaded();
|
||||
const page = workspace.createPage('page0');
|
||||
initEmptyPage(page);
|
||||
const provider = createIndexedDBProvider(
|
||||
workspace.id,
|
||||
@@ -495,12 +397,7 @@ describe('utils', () => {
|
||||
applyUpdate(newWorkspace.doc, update);
|
||||
await new Promise<void>(resolve =>
|
||||
setTimeout(() => {
|
||||
expect(workspace.doc.toJSON()['meta']).toEqual(
|
||||
newWorkspace.doc.toJSON()['meta']
|
||||
);
|
||||
expect(Object.keys(workspace.doc.toJSON()['spaces'])).toEqual(
|
||||
Object.keys(newWorkspace.doc.toJSON()['spaces'])
|
||||
);
|
||||
expect(workspace.doc.toJSON()).toEqual(newWorkspace.doc.toJSON());
|
||||
resolve();
|
||||
}, 0)
|
||||
);
|
||||
|
||||
@@ -142,12 +142,6 @@ export const getMilestones = async (
|
||||
return milestone.milestone;
|
||||
};
|
||||
|
||||
type SubDocsEvent = {
|
||||
added: Set<Doc>;
|
||||
removed: Set<Doc>;
|
||||
loaded: Set<Doc>;
|
||||
};
|
||||
|
||||
export const createIndexedDBProvider = (
|
||||
id: string,
|
||||
doc: Doc,
|
||||
@@ -157,175 +151,62 @@ export const createIndexedDBProvider = (
|
||||
let reject: (reason?: unknown) => void;
|
||||
let early = true;
|
||||
let connected = false;
|
||||
const dbPromise = openDB<BlockSuiteBinaryDB>(dbName, dbVersion, {
|
||||
upgrade: upgradeDB,
|
||||
});
|
||||
|
||||
const updateHandlerMap = new WeakMap<
|
||||
Doc,
|
||||
(update: Uint8Array, origin: unknown) => void
|
||||
>();
|
||||
const destroyHandlerMap = new WeakMap<Doc, () => void>();
|
||||
const subDocsHandlerMap = new WeakMap<Doc, (event: SubDocsEvent) => void>();
|
||||
|
||||
const createOrGetHandleUpdate = (id: string, doc: Doc) => {
|
||||
if (updateHandlerMap.has(doc)) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
return updateHandlerMap.get(doc)!;
|
||||
}
|
||||
const fn = async function handleUpdate(
|
||||
update: Uint8Array,
|
||||
origin: unknown
|
||||
) {
|
||||
const db = await dbPromise;
|
||||
if (!connected) {
|
||||
return;
|
||||
}
|
||||
if (origin === indexeddbOrigin) {
|
||||
return;
|
||||
}
|
||||
const store = db
|
||||
.transaction('workspace', 'readwrite')
|
||||
.objectStore('workspace');
|
||||
let data = await store.get(id);
|
||||
if (!data) {
|
||||
data = {
|
||||
id,
|
||||
updates: [],
|
||||
};
|
||||
}
|
||||
data.updates.push({
|
||||
timestamp: Date.now(),
|
||||
update,
|
||||
});
|
||||
if (data.updates.length > mergeCount) {
|
||||
const updates = data.updates.map(({ update }) => update);
|
||||
const doc = new Doc();
|
||||
doc.transact(() => {
|
||||
updates.forEach(update => {
|
||||
applyUpdate(doc, update, indexeddbOrigin);
|
||||
});
|
||||
}, indexeddbOrigin);
|
||||
|
||||
const update = encodeStateAsUpdate(doc);
|
||||
data = {
|
||||
id,
|
||||
updates: [
|
||||
{
|
||||
timestamp: Date.now(),
|
||||
update,
|
||||
},
|
||||
],
|
||||
};
|
||||
await writeOperation(store.put(data));
|
||||
} else {
|
||||
await writeOperation(store.put(data));
|
||||
}
|
||||
};
|
||||
updateHandlerMap.set(doc, fn);
|
||||
return fn;
|
||||
};
|
||||
|
||||
/* deepscan-disable UNUSED_PARAM */
|
||||
const createOrGetHandleDestroy = (_: string, doc: Doc) => {
|
||||
if (destroyHandlerMap.has(doc)) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
return destroyHandlerMap.get(doc)!;
|
||||
}
|
||||
const fn = async function handleDestroy() {
|
||||
const db = await dbPromise;
|
||||
db.close();
|
||||
};
|
||||
destroyHandlerMap.set(doc, fn);
|
||||
return fn;
|
||||
};
|
||||
|
||||
/* deepscan-disable UNUSED_PARAM */
|
||||
const createOrGetHandleSubDocs = (_: string, doc: Doc) => {
|
||||
if (subDocsHandlerMap.has(doc)) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
return subDocsHandlerMap.get(doc)!;
|
||||
}
|
||||
const fn = async function handleSubDocs(event: SubDocsEvent) {
|
||||
event.removed.forEach(doc => {
|
||||
unTrackDoc(doc.guid, doc);
|
||||
});
|
||||
event.loaded.forEach(doc => {
|
||||
trackDoc(doc.guid, doc);
|
||||
});
|
||||
};
|
||||
subDocsHandlerMap.set(doc, fn);
|
||||
return fn;
|
||||
};
|
||||
|
||||
function trackDoc(id: string, doc: Doc) {
|
||||
doc.on('update', createOrGetHandleUpdate(id, doc));
|
||||
doc.on('destroy', createOrGetHandleDestroy(id, doc));
|
||||
doc.on('subdocs', createOrGetHandleSubDocs(id, doc));
|
||||
}
|
||||
|
||||
function unTrackDoc(id: string, doc: Doc) {
|
||||
doc.subdocs.forEach(doc => {
|
||||
unTrackDoc(doc.guid, doc);
|
||||
});
|
||||
doc.off('update', createOrGetHandleUpdate(id, doc));
|
||||
doc.off('destroy', createOrGetHandleDestroy(id, doc));
|
||||
doc.off('subdocs', createOrGetHandleSubDocs(id, doc));
|
||||
}
|
||||
|
||||
async function saveDocOperation(id: string, doc: Doc) {
|
||||
async function handleUpdate(update: Uint8Array, origin: unknown) {
|
||||
const db = await dbPromise;
|
||||
const store = db
|
||||
.transaction('workspace', 'readwrite')
|
||||
.objectStore('workspace');
|
||||
const data = await store.get(id);
|
||||
if (!connected) {
|
||||
return;
|
||||
}
|
||||
if (origin === indexeddbOrigin) {
|
||||
return;
|
||||
}
|
||||
const store = db
|
||||
.transaction('workspace', 'readwrite')
|
||||
.objectStore('workspace');
|
||||
let data = await store.get(id);
|
||||
if (!data) {
|
||||
await writeOperation(
|
||||
db.put('workspace', {
|
||||
id,
|
||||
updates: [
|
||||
{
|
||||
timestamp: Date.now(),
|
||||
update: encodeStateAsUpdate(doc),
|
||||
},
|
||||
],
|
||||
})
|
||||
);
|
||||
} else {
|
||||
data = {
|
||||
id,
|
||||
updates: [],
|
||||
};
|
||||
}
|
||||
data.updates.push({
|
||||
timestamp: Date.now(),
|
||||
update,
|
||||
});
|
||||
if (data.updates.length > mergeCount) {
|
||||
const updates = data.updates.map(({ update }) => update);
|
||||
const fakeDoc = new Doc();
|
||||
fakeDoc.transact(() => {
|
||||
updates.forEach(update => {
|
||||
applyUpdate(fakeDoc, update);
|
||||
});
|
||||
}, indexeddbOrigin);
|
||||
const newUpdate = diffUpdate(
|
||||
encodeStateAsUpdate(doc),
|
||||
encodeStateAsUpdate(fakeDoc)
|
||||
);
|
||||
await writeOperation(
|
||||
store.put({
|
||||
...data,
|
||||
updates: [
|
||||
...data.updates,
|
||||
{
|
||||
timestamp: Date.now(),
|
||||
update: newUpdate,
|
||||
},
|
||||
],
|
||||
})
|
||||
);
|
||||
const doc = new Doc();
|
||||
doc.transact(() => {
|
||||
updates.forEach(update => {
|
||||
applyUpdate(doc, update);
|
||||
applyUpdate(doc, update, indexeddbOrigin);
|
||||
});
|
||||
}, indexeddbOrigin);
|
||||
|
||||
const update = encodeStateAsUpdate(doc);
|
||||
data = {
|
||||
id,
|
||||
updates: [
|
||||
{
|
||||
timestamp: Date.now(),
|
||||
update,
|
||||
},
|
||||
],
|
||||
};
|
||||
await writeOperation(store.put(data));
|
||||
} else {
|
||||
await writeOperation(store.put(data));
|
||||
}
|
||||
}
|
||||
|
||||
const dbPromise = openDB<BlockSuiteBinaryDB>(dbName, dbVersion, {
|
||||
upgrade: upgradeDB,
|
||||
});
|
||||
const handleDestroy = async () => {
|
||||
connected = true;
|
||||
const db = await dbPromise;
|
||||
db.close();
|
||||
};
|
||||
const apis = {
|
||||
connect: async () => {
|
||||
if (connected) return;
|
||||
@@ -336,23 +217,60 @@ export const createIndexedDBProvider = (
|
||||
reject = _reject;
|
||||
});
|
||||
connected = true;
|
||||
trackDoc(id, doc);
|
||||
// only the runs `await` below, otherwise the logic is incorrect
|
||||
doc.on('update', handleUpdate);
|
||||
doc.on('destroy', handleDestroy);
|
||||
// only run promise below, otherwise the logic is incorrect
|
||||
const db = await dbPromise;
|
||||
await tryMigrate(db, id, dbName);
|
||||
const store = db
|
||||
.transaction('workspace', 'readwrite')
|
||||
.objectStore('workspace');
|
||||
const data = await store.get(id);
|
||||
if (!connected) {
|
||||
return;
|
||||
}
|
||||
const docs: [string, Doc][] = [];
|
||||
docs.push([id, doc]);
|
||||
while (docs.length > 0) {
|
||||
const [id, doc] = docs.pop() as [string, Doc];
|
||||
await saveDocOperation(id, doc);
|
||||
doc.subdocs.forEach(doc => {
|
||||
docs.push([doc.guid, doc]);
|
||||
});
|
||||
if (!data) {
|
||||
await writeOperation(
|
||||
db.put('workspace', {
|
||||
id,
|
||||
updates: [
|
||||
{
|
||||
timestamp: Date.now(),
|
||||
update: encodeStateAsUpdate(doc),
|
||||
},
|
||||
],
|
||||
})
|
||||
);
|
||||
} else {
|
||||
const updates = data.updates.map(({ update }) => update);
|
||||
const fakeDoc = new Doc();
|
||||
fakeDoc.transact(() => {
|
||||
updates.forEach(update => {
|
||||
applyUpdate(fakeDoc, update);
|
||||
});
|
||||
}, indexeddbOrigin);
|
||||
const newUpdate = diffUpdate(
|
||||
encodeStateAsUpdate(doc),
|
||||
encodeStateAsUpdate(fakeDoc)
|
||||
);
|
||||
await writeOperation(
|
||||
store.put({
|
||||
...data,
|
||||
updates: [
|
||||
...data.updates,
|
||||
{
|
||||
timestamp: Date.now(),
|
||||
update: newUpdate,
|
||||
},
|
||||
],
|
||||
})
|
||||
);
|
||||
doc.transact(() => {
|
||||
updates.forEach(update => {
|
||||
applyUpdate(doc, update);
|
||||
});
|
||||
}, indexeddbOrigin);
|
||||
}
|
||||
|
||||
early = false;
|
||||
resolve();
|
||||
},
|
||||
@@ -361,7 +279,8 @@ export const createIndexedDBProvider = (
|
||||
if (early) {
|
||||
reject(new EarlyDisconnectError());
|
||||
}
|
||||
unTrackDoc(id, doc);
|
||||
doc.off('update', handleUpdate);
|
||||
doc.off('destroy', handleDestroy);
|
||||
},
|
||||
async cleanup() {
|
||||
if (connected) {
|
||||
|
||||
@@ -9,6 +9,9 @@
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.node.json"
|
||||
},
|
||||
{
|
||||
"path": "../env"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -21,5 +21,5 @@
|
||||
"react": "*",
|
||||
"react-dom": "*"
|
||||
},
|
||||
"version": "0.6.1-beta.0"
|
||||
"version": "0.7.0-canary.13"
|
||||
}
|
||||
|
||||
@@ -28,5 +28,5 @@
|
||||
"react": "*",
|
||||
"react-dom": "*"
|
||||
},
|
||||
"version": "0.6.1-beta.0"
|
||||
"version": "0.7.0-canary.13"
|
||||
}
|
||||
|
||||
@@ -12,48 +12,47 @@ import { openAIApiKeyAtom, useChatAtoms } from '../core/hooks';
|
||||
import { detailContentActionsStyle, detailContentStyle } from './index.css';
|
||||
|
||||
if (typeof window === 'undefined') {
|
||||
import('@blocksuite/blocks')
|
||||
.then(({ FormatQuickBar }) => {
|
||||
FormatQuickBar.customElements.push((_page, getSelection) => {
|
||||
const div = document.createElement('div');
|
||||
const root = createRoot(div);
|
||||
import('@blocksuite/blocks').then(({ FormatQuickBar }) => {
|
||||
FormatQuickBar.customElements.push((_page, getSelection) => {
|
||||
const div = document.createElement('div');
|
||||
const root = createRoot(div);
|
||||
|
||||
const AskAI = (): ReactElement => {
|
||||
const { conversationAtom } = useChatAtoms();
|
||||
const call = useSetAtom(conversationAtom);
|
||||
const onClickAskAI = useCallback(() => {
|
||||
const selection = getSelection();
|
||||
if (selection != null) {
|
||||
const text = selection.models
|
||||
.map(model => {
|
||||
return model.text?.toString();
|
||||
})
|
||||
.filter((v): v is string => Boolean(v))
|
||||
.join('\n');
|
||||
console.log('selected text:', text);
|
||||
call(
|
||||
`I selected some text from the document: \n"${text}."`
|
||||
).catch(err => {
|
||||
console.error(err);
|
||||
});
|
||||
}
|
||||
}, [call]);
|
||||
const AskAI = (): ReactElement => {
|
||||
const { conversationAtom } = useChatAtoms();
|
||||
const call = useSetAtom(conversationAtom);
|
||||
|
||||
return <div onClick={onClickAskAI}>Ask AI</div>;
|
||||
};
|
||||
root.render(
|
||||
<StrictMode>
|
||||
<Provider store={rootStore}>
|
||||
<AskAI />
|
||||
</Provider>
|
||||
</StrictMode>
|
||||
return (
|
||||
<div
|
||||
onClick={() => {
|
||||
const selection = getSelection();
|
||||
if (selection != null) {
|
||||
const text = selection.models
|
||||
.map(model => {
|
||||
return model.text?.toString();
|
||||
})
|
||||
.filter((v): v is string => Boolean(v))
|
||||
.join('\n');
|
||||
console.log('selected text:', text);
|
||||
void call(
|
||||
`I selected some text from the document: \n"${text}."`
|
||||
);
|
||||
}
|
||||
}}
|
||||
>
|
||||
Ask AI
|
||||
</div>
|
||||
);
|
||||
return div;
|
||||
});
|
||||
})
|
||||
.catch(error => {
|
||||
console.error(error);
|
||||
};
|
||||
root.render(
|
||||
<StrictMode>
|
||||
<Provider store={rootStore}>
|
||||
<AskAI />
|
||||
</Provider>
|
||||
</StrictMode>
|
||||
);
|
||||
return div;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const Actions = () => {
|
||||
|
||||
@@ -49,14 +49,9 @@ const getConversationAtom = (chat: ConversationChain) => {
|
||||
throw new Error();
|
||||
}
|
||||
const memory = chat.memory as BufferMemory;
|
||||
memory.chatHistory
|
||||
.getMessages()
|
||||
.then(messages => {
|
||||
setAtom(messages);
|
||||
})
|
||||
.catch(err => {
|
||||
console.error(err);
|
||||
});
|
||||
void memory.chatHistory.getMessages().then(messages => {
|
||||
setAtom(messages);
|
||||
});
|
||||
const llmStart = (): void => {
|
||||
setAtom(conversations => [...conversations, new AIChatMessage('')]);
|
||||
};
|
||||
@@ -91,14 +86,9 @@ const getConversationAtom = (chat: ConversationChain) => {
|
||||
});
|
||||
// refresh messages
|
||||
const memory = chat.memory as BufferMemory;
|
||||
memory.chatHistory
|
||||
.getMessages()
|
||||
.then(messages => {
|
||||
set(conversationBaseAtom, messages);
|
||||
})
|
||||
.catch(err => {
|
||||
console.error(err);
|
||||
});
|
||||
void memory.chatHistory.getMessages().then(messages => {
|
||||
set(conversationBaseAtom, messages);
|
||||
});
|
||||
}
|
||||
);
|
||||
conversationWeakMap.set(chat, conversationAtom);
|
||||
|
||||
2
tests/fixtures/package.json
vendored
2
tests/fixtures/package.json
vendored
@@ -3,5 +3,5 @@
|
||||
"exports": {
|
||||
"./*": "./*"
|
||||
},
|
||||
"version": "0.6.1-beta.0"
|
||||
"version": "0.7.0-canary.13"
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@affine-test/kit",
|
||||
"private": true,
|
||||
"version": "0.6.1-beta.0",
|
||||
"version": "0.7.0-canary.13",
|
||||
"exports": {
|
||||
"./playwright": "./playwright.ts"
|
||||
},
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
import { test } from '@affine-test/kit/playwright';
|
||||
import type { Page } from '@playwright/test';
|
||||
import { expect } from '@playwright/test';
|
||||
|
||||
import { openHomePage } from '../../libs/load-page';
|
||||
import { newPage, waitEditorLoad } from '../../libs/page-logic';
|
||||
const addDatabase = async (page: Page) => {
|
||||
await page.keyboard.press('/', { delay: 50 });
|
||||
await page.keyboard.press('d');
|
||||
await page.keyboard.press('a');
|
||||
await page.keyboard.press('t');
|
||||
await page.keyboard.press('a');
|
||||
await page.keyboard.press('b');
|
||||
await page.keyboard.press('a', { delay: 50 });
|
||||
await page.keyboard.press('Enter', { delay: 50 });
|
||||
};
|
||||
test('database is useable', async ({ page }) => {
|
||||
await openHomePage(page);
|
||||
await waitEditorLoad(page);
|
||||
await newPage(page);
|
||||
await page.keyboard.insertText('test title');
|
||||
await page.keyboard.press('Enter');
|
||||
const title = page.locator('.affine-default-page-block-title');
|
||||
expect(await title.innerText()).toBe('test title');
|
||||
await addDatabase(page);
|
||||
const database = page.locator('.affine-database-table');
|
||||
expect(database).toBeVisible();
|
||||
await page.reload();
|
||||
await waitEditorLoad(page);
|
||||
await newPage(page);
|
||||
await page.keyboard.insertText('test title2');
|
||||
await page.keyboard.press('Enter');
|
||||
const title2 = page.locator('.affine-default-page-block-title');
|
||||
expect(await title2.innerText()).toBe('test title2');
|
||||
await addDatabase(page);
|
||||
const database2 = page.locator('.affine-database-table');
|
||||
expect(database2).toBeVisible();
|
||||
});
|
||||
|
||||
test('link page is useable', async ({ page }) => {
|
||||
await openHomePage(page);
|
||||
await waitEditorLoad(page);
|
||||
await newPage(page);
|
||||
await page.keyboard.insertText('page1');
|
||||
await page.keyboard.press('Enter');
|
||||
const title = page.locator('.affine-default-page-block-title');
|
||||
expect(await title.innerText()).toBe('page1');
|
||||
await newPage(page);
|
||||
await page.keyboard.insertText('page2');
|
||||
await page.keyboard.press('Enter');
|
||||
const title2 = page.locator('.affine-default-page-block-title');
|
||||
expect(await title2.innerText()).toBe('page2');
|
||||
await page.keyboard.press('@', { delay: 50 });
|
||||
await page.keyboard.press('p');
|
||||
await page.keyboard.press('a');
|
||||
await page.keyboard.press('g');
|
||||
await page.keyboard.press('e');
|
||||
await page.keyboard.press('1');
|
||||
await page.keyboard.press('Enter');
|
||||
const link = page.locator('.affine-reference');
|
||||
expect(link).toBeVisible();
|
||||
await page.click('.affine-reference');
|
||||
expect(await title.innerText()).toBe('page1');
|
||||
});
|
||||
333
yarn.lock
333
yarn.lock
@@ -158,10 +158,6 @@ __metadata:
|
||||
dependencies:
|
||||
"@affine-test/kit": "workspace:*"
|
||||
"@affine/native": "workspace:*"
|
||||
"@blocksuite/blocks": 0.0.0-20230607055421-9b20fcaf-nightly
|
||||
"@blocksuite/editor": 0.0.0-20230607055421-9b20fcaf-nightly
|
||||
"@blocksuite/lit": 0.0.0-20230607055421-9b20fcaf-nightly
|
||||
"@blocksuite/store": 0.0.0-20230607055421-9b20fcaf-nightly
|
||||
"@electron-forge/cli": ^6.1.1
|
||||
"@electron-forge/core": ^6.1.1
|
||||
"@electron-forge/core-utils": ^6.1.1
|
||||
@@ -176,6 +172,7 @@ __metadata:
|
||||
"@types/fs-extra": ^11.0.1
|
||||
"@types/uuid": ^9.0.1
|
||||
async-call-rpc: ^6.3.1
|
||||
cheerio: ^1.0.0-rc.12
|
||||
cross-env: 7.0.3
|
||||
electron: =25.0.1
|
||||
electron-log: ^5.0.0-beta.24
|
||||
@@ -184,8 +181,6 @@ __metadata:
|
||||
electron-window-state: ^5.0.3
|
||||
esbuild: ^0.17.19
|
||||
fs-extra: ^11.1.1
|
||||
jotai: ^2.1.1
|
||||
link-preview-js: ^3.0.4
|
||||
lodash-es: ^4.17.21
|
||||
nanoid: ^4.0.2
|
||||
playwright: =1.33.0
|
||||
@@ -193,7 +188,6 @@ __metadata:
|
||||
ts-node: ^10.9.1
|
||||
undici: ^5.22.1
|
||||
uuid: ^9.0.0
|
||||
which: ^3.0.1
|
||||
yjs: ^13.6.1
|
||||
zx: ^7.2.2
|
||||
peerDependencies:
|
||||
@@ -302,7 +296,6 @@ __metadata:
|
||||
eslint-plugin-react: ^7.32.2
|
||||
eslint-plugin-react-hooks: ^4.6.0
|
||||
eslint-plugin-simple-import-sort: ^10.0.0
|
||||
eslint-plugin-sonarjs: ^0.19.0
|
||||
eslint-plugin-unicorn: ^47.0.0
|
||||
eslint-plugin-unused-imports: ^2.0.0
|
||||
fake-indexeddb: 4.0.1
|
||||
@@ -2612,15 +2605,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/runtime@npm:^7.14.0":
|
||||
version: 7.22.5
|
||||
resolution: "@babel/runtime@npm:7.22.5"
|
||||
dependencies:
|
||||
regenerator-runtime: ^0.13.11
|
||||
checksum: 12a50b7de2531beef38840d17af50c55a094253697600cee255311222390c68eed704829308d4fd305e1b3dfbce113272e428e9d9d45b1730e0fede997eaceb1
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/template@npm:^7.18.10, @babel/template@npm:^7.20.7, @babel/template@npm:^7.21.9, @babel/template@npm:^7.3.3":
|
||||
version: 7.21.9
|
||||
resolution: "@babel/template@npm:7.21.9"
|
||||
@@ -2729,32 +2713,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@blocksuite/blocks@npm:0.0.0-20230613142146-d72d4600-nightly":
|
||||
version: 0.0.0-20230613142146-d72d4600-nightly
|
||||
resolution: "@blocksuite/blocks@npm:0.0.0-20230613142146-d72d4600-nightly"
|
||||
dependencies:
|
||||
"@blocksuite/connector": 0.0.0-20230613142146-d72d4600-nightly
|
||||
"@blocksuite/global": 0.0.0-20230613142146-d72d4600-nightly
|
||||
"@blocksuite/phasor": 0.0.0-20230613142146-d72d4600-nightly
|
||||
"@blocksuite/virgo": 0.0.0-20230613142146-d72d4600-nightly
|
||||
"@floating-ui/dom": ^1.2.9
|
||||
hotkeys-js: ^3.10.1
|
||||
html-to-image: ^1.11.11
|
||||
jspdf: ^2.5.1
|
||||
jszip: ^3.10.1
|
||||
lit: ^2.7.3
|
||||
marked: ^4.2.12
|
||||
shiki: ^0.14.1
|
||||
turndown: ^7.1.1
|
||||
zod: ^3.21.4
|
||||
peerDependencies:
|
||||
"@blocksuite/lit": 0.0.0-20230613142146-d72d4600-nightly
|
||||
"@blocksuite/store": 0.0.0-20230613142146-d72d4600-nightly
|
||||
yjs: ^13
|
||||
checksum: 949d37335c16b6c6fd224a9ce6f0e356d500e139010706351a277f5ec69ebab309016267d8ecbb8d95adcae8d0edad2c99fb763f3caf158cf28d6bb12b8613d3
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@blocksuite/connector@npm:0.0.0-20230607055421-9b20fcaf-nightly":
|
||||
version: 0.0.0-20230607055421-9b20fcaf-nightly
|
||||
resolution: "@blocksuite/connector@npm:0.0.0-20230607055421-9b20fcaf-nightly"
|
||||
@@ -2762,13 +2720,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@blocksuite/connector@npm:0.0.0-20230613142146-d72d4600-nightly":
|
||||
version: 0.0.0-20230613142146-d72d4600-nightly
|
||||
resolution: "@blocksuite/connector@npm:0.0.0-20230613142146-d72d4600-nightly"
|
||||
checksum: c5fcbae09c72cd61ecf8d4366c720edad7704f7737d0635e420fc0359ab9f4fe5a964581eee8e908ac1cab23abfba8bd770490bf674a594dc53624d6da775d5d
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@blocksuite/editor@npm:0.0.0-20230607055421-9b20fcaf-nightly":
|
||||
version: 0.0.0-20230607055421-9b20fcaf-nightly
|
||||
resolution: "@blocksuite/editor@npm:0.0.0-20230607055421-9b20fcaf-nightly"
|
||||
@@ -2801,21 +2752,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@blocksuite/global@npm:0.0.0-20230613142146-d72d4600-nightly":
|
||||
version: 0.0.0-20230613142146-d72d4600-nightly
|
||||
resolution: "@blocksuite/global@npm:0.0.0-20230613142146-d72d4600-nightly"
|
||||
dependencies:
|
||||
ansi-colors: ^4.1.3
|
||||
zod: ^3.21.4
|
||||
peerDependencies:
|
||||
lit: ^2.7
|
||||
peerDependenciesMeta:
|
||||
lit:
|
||||
optional: true
|
||||
checksum: 45ccaa08c14787da8e3be8cbde9f01a34afea8874da6eaf7900961f953bbc0e7bab13866037d1504a1e983a8cc9e0735f5d9b1e074f6e400b27f7efae00292dd
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@blocksuite/icons@npm:^2.1.19":
|
||||
version: 2.1.19
|
||||
resolution: "@blocksuite/icons@npm:2.1.19"
|
||||
@@ -2852,20 +2788,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@blocksuite/phasor@npm:0.0.0-20230613142146-d72d4600-nightly":
|
||||
version: 0.0.0-20230613142146-d72d4600-nightly
|
||||
resolution: "@blocksuite/phasor@npm:0.0.0-20230613142146-d72d4600-nightly"
|
||||
dependencies:
|
||||
"@blocksuite/global": 0.0.0-20230613142146-d72d4600-nightly
|
||||
fractional-indexing: ^3.2.0
|
||||
roughjs: ^4.5.2
|
||||
peerDependencies:
|
||||
nanoid: ^4
|
||||
yjs: ^13
|
||||
checksum: 24dbb806ab928c4b37dcf94ea14fbd1f23dfcf63c42e42b378ca78baa51ec713556fc4a6553c5bf505d59309cd29079ffa8abb575a7c4f04cbef2202714f07c9
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@blocksuite/store@npm:0.0.0-20230607055421-9b20fcaf-nightly":
|
||||
version: 0.0.0-20230607055421-9b20fcaf-nightly
|
||||
resolution: "@blocksuite/store@npm:0.0.0-20230607055421-9b20fcaf-nightly"
|
||||
@@ -2890,30 +2812,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@blocksuite/store@npm:0.0.0-20230613142146-d72d4600-nightly":
|
||||
version: 0.0.0-20230613142146-d72d4600-nightly
|
||||
resolution: "@blocksuite/store@npm:0.0.0-20230613142146-d72d4600-nightly"
|
||||
dependencies:
|
||||
"@blocksuite/global": 0.0.0-20230613142146-d72d4600-nightly
|
||||
"@blocksuite/virgo": 0.0.0-20230613142146-d72d4600-nightly
|
||||
"@types/flexsearch": ^0.7.3
|
||||
buffer: ^6.0.3
|
||||
flexsearch: 0.7.21
|
||||
idb-keyval: ^6.2.0
|
||||
ky: ^0.33.3
|
||||
lib0: ^0.2.74
|
||||
merge: ^2.1.1
|
||||
minimatch: ^9.0.0
|
||||
nanoid: ^4.0.1
|
||||
y-protocols: ^1.0.5
|
||||
y-webrtc: ^10.2.5
|
||||
zod: ^3.21.4
|
||||
peerDependencies:
|
||||
yjs: ^13
|
||||
checksum: 1e6673b4c90ceb73176c552528d174126c036b445cc81c649e4e2fb694b87adbe12dcc3675117a088f5aadbe0410e380601914d05e26334879e12135c0843b17
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@blocksuite/virgo@npm:0.0.0-20230607055421-9b20fcaf-nightly":
|
||||
version: 0.0.0-20230607055421-9b20fcaf-nightly
|
||||
resolution: "@blocksuite/virgo@npm:0.0.0-20230607055421-9b20fcaf-nightly"
|
||||
@@ -2927,19 +2825,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@blocksuite/virgo@npm:0.0.0-20230613142146-d72d4600-nightly":
|
||||
version: 0.0.0-20230613142146-d72d4600-nightly
|
||||
resolution: "@blocksuite/virgo@npm:0.0.0-20230613142146-d72d4600-nightly"
|
||||
dependencies:
|
||||
"@blocksuite/global": 0.0.0-20230613142146-d72d4600-nightly
|
||||
zod: ^3.21.4
|
||||
peerDependencies:
|
||||
lit: ^2.7
|
||||
yjs: ^13
|
||||
checksum: f3b5ee207b90d7f960eb10c37eb6866f06c0a2ad1e8e8bc46cc131ef2958f70a5b78d3dbafb7b19063b624acb898486a9b1f7fd7f83aa3f6253904b23f3eab47
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@clack/core@npm:^0.3.2":
|
||||
version: 0.3.2
|
||||
resolution: "@clack/core@npm:0.3.2"
|
||||
@@ -4619,13 +4504,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@floating-ui/core@npm:^1.3.0":
|
||||
version: 1.3.0
|
||||
resolution: "@floating-ui/core@npm:1.3.0"
|
||||
checksum: 51d8acc9fd720cb217cae7074f5f923bf2b6e0bb4f228e03077254d0f6e49f9753b34a14b9abb1f11671c3b61284c487ab27c4ba1843bcd4397e7d72dc7d4a59
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@floating-ui/dom@npm:^1.2.1":
|
||||
version: 1.2.9
|
||||
resolution: "@floating-ui/dom@npm:1.2.9"
|
||||
@@ -4635,15 +4513,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@floating-ui/dom@npm:^1.2.9":
|
||||
version: 1.3.0
|
||||
resolution: "@floating-ui/dom@npm:1.3.0"
|
||||
dependencies:
|
||||
"@floating-ui/core": ^1.3.0
|
||||
checksum: 39f92b3ce6de5d60a1cea951cbee22d0a9670fe4499b0128f0868a697d9288989994394d90cb99c3d1485aa432621e064d6b3c52914042a7d8d3c05897fb185d
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@floating-ui/react-dom@npm:^1.3.0":
|
||||
version: 1.3.0
|
||||
resolution: "@floating-ui/react-dom@npm:1.3.0"
|
||||
@@ -9408,8 +9277,8 @@ __metadata:
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@toeverything/y-indexeddb@workspace:packages/y-indexeddb"
|
||||
dependencies:
|
||||
"@blocksuite/blocks": 0.0.0-20230613142146-d72d4600-nightly
|
||||
"@blocksuite/store": 0.0.0-20230613142146-d72d4600-nightly
|
||||
"@blocksuite/blocks": 0.0.0-20230607055421-9b20fcaf-nightly
|
||||
"@blocksuite/store": 0.0.0-20230607055421-9b20fcaf-nightly
|
||||
idb: ^7.1.1
|
||||
vite: ^4.3.9
|
||||
vite-plugin-dts: ^2.3.0
|
||||
@@ -10032,13 +9901,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/raf@npm:^3.4.0":
|
||||
version: 3.4.0
|
||||
resolution: "@types/raf@npm:3.4.0"
|
||||
checksum: d93e9b5244a081c64708b8918ef7e56936d6ef0144925b189e67d34127c0cb3a73fcf6866ab312db156554a66c26609dd056da5f7302f6658c049d6a37ed5f56
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/range-parser@npm:*":
|
||||
version: 1.2.4
|
||||
resolution: "@types/range-parser@npm:1.2.4"
|
||||
@@ -11653,15 +11515,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"atob@npm:^2.1.2":
|
||||
version: 2.1.2
|
||||
resolution: "atob@npm:2.1.2"
|
||||
bin:
|
||||
atob: bin/atob.js
|
||||
checksum: dfeeeb70090c5ebea7be4b9f787f866686c645d9f39a0d184c817252d0cf08455ed25267d79c03254d3be1f03ac399992a792edcd5ffb9c91e097ab5ef42833a
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"author-regex@npm:^1.0.0":
|
||||
version: 1.0.0
|
||||
resolution: "author-regex@npm:1.0.0"
|
||||
@@ -11987,13 +11840,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"base64-arraybuffer@npm:^1.0.2":
|
||||
version: 1.0.2
|
||||
resolution: "base64-arraybuffer@npm:1.0.2"
|
||||
checksum: 15e6400d2d028bf18be4ed97702b11418f8f8779fb8c743251c863b726638d52f69571d4cc1843224da7838abef0949c670bde46936663c45ad078e89fee5c62
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"base64-js@npm:^1.3.1, base64-js@npm:^1.5.1":
|
||||
version: 1.5.1
|
||||
resolution: "base64-js@npm:1.5.1"
|
||||
@@ -12234,15 +12080,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"btoa@npm:^1.2.1":
|
||||
version: 1.2.1
|
||||
resolution: "btoa@npm:1.2.1"
|
||||
bin:
|
||||
btoa: bin/btoa.js
|
||||
checksum: afbf004fb1b1d530e053ffa66ef5bd3878b101c59d808ac947fcff96810b4452abba2b54be687adadea2ba9efc7af48b04228742789bf824ef93f103767e690c
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"buffer-crc32@npm:~0.2.3":
|
||||
version: 0.2.13
|
||||
resolution: "buffer-crc32@npm:0.2.13"
|
||||
@@ -12511,22 +12348,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"canvg@npm:^3.0.6":
|
||||
version: 3.0.10
|
||||
resolution: "canvg@npm:3.0.10"
|
||||
dependencies:
|
||||
"@babel/runtime": ^7.12.5
|
||||
"@types/raf": ^3.4.0
|
||||
core-js: ^3.8.3
|
||||
raf: ^3.4.1
|
||||
regenerator-runtime: ^0.13.7
|
||||
rgbcolor: ^1.0.1
|
||||
stackblur-canvas: ^2.0.0
|
||||
svg-pathdata: ^6.0.3
|
||||
checksum: 2cfd86bcb9b56b43a97745cc672e696169b4c09e8850fb4f27bec5ebf173179d16feb594224d643a32f1ce01e47b55d44e0058419114d48d34f12c2452c65927
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"capital-case@npm:^1.0.4":
|
||||
version: 1.0.4
|
||||
resolution: "capital-case@npm:1.0.4"
|
||||
@@ -12734,6 +12555,21 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"cheerio@npm:^1.0.0-rc.12":
|
||||
version: 1.0.0-rc.12
|
||||
resolution: "cheerio@npm:1.0.0-rc.12"
|
||||
dependencies:
|
||||
cheerio-select: ^2.1.0
|
||||
dom-serializer: ^2.0.0
|
||||
domhandler: ^5.0.3
|
||||
domutils: ^3.0.1
|
||||
htmlparser2: ^8.0.1
|
||||
parse5: ^7.0.0
|
||||
parse5-htmlparser2-tree-adapter: ^7.0.0
|
||||
checksum: 5d4c1b7a53cf22d3a2eddc0aff70cf23cbb30d01a4c79013e703a012475c02461aa1fcd99127e8d83a02216386ed6942b2c8103845fd0812300dd199e6e7e054
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"chokidar@npm:3.5.3, chokidar@npm:^3.4.2, chokidar@npm:^3.5.2, chokidar@npm:^3.5.3":
|
||||
version: 3.5.3
|
||||
resolution: "chokidar@npm:3.5.3"
|
||||
@@ -13455,13 +13291,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"core-js@npm:^3.6.0, core-js@npm:^3.8.3":
|
||||
version: 3.31.0
|
||||
resolution: "core-js@npm:3.31.0"
|
||||
checksum: f7cf9b3010f7ca99c026d95b61743baca1a85512742ed2b67e8f65a72ac4f4fe0b90b00057783e886bdd39d3a295f42f845d33e7cba3973ed263df978343ab79
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"core-util-is@npm:~1.0.0":
|
||||
version: 1.0.3
|
||||
resolution: "core-util-is@npm:1.0.3"
|
||||
@@ -13602,15 +13431,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"css-line-break@npm:^2.1.0":
|
||||
version: 2.1.0
|
||||
resolution: "css-line-break@npm:2.1.0"
|
||||
dependencies:
|
||||
utrie: ^1.0.2
|
||||
checksum: 37b1fe632b03be7a287cd394cef8b5285666343443125c510df9cfb6a4734a2c71e154ec8f7bbff72d7c339e1e5872989b1c52d86162aed27d6cc114725bb4d0
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"css-select@npm:^5.1.0":
|
||||
version: 5.1.0
|
||||
resolution: "css-select@npm:5.1.0"
|
||||
@@ -14461,13 +14281,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"dompurify@npm:^2.2.0":
|
||||
version: 2.4.5
|
||||
resolution: "dompurify@npm:2.4.5"
|
||||
checksum: d6d3c3b320f15cdb5b26aa1902c3275a3ab2c3705a9df4420bb94691d7c4df67959ec7b91e486c308320791b0ee000456f042734c45d76721e61c2768eac706e
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"domutils@npm:^1.5.1":
|
||||
version: 1.7.0
|
||||
resolution: "domutils@npm:1.7.0"
|
||||
@@ -15462,15 +15275,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"eslint-plugin-sonarjs@npm:^0.19.0":
|
||||
version: 0.19.0
|
||||
resolution: "eslint-plugin-sonarjs@npm:0.19.0"
|
||||
peerDependencies:
|
||||
eslint: ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0
|
||||
checksum: 893640583f62ce55584c6ddd481aa0fd6fa15fe0fffc32ac92b17f3fadde8eaf32414183bb80b612455212e9bb14400236398af6279ca04e8992f008e011926c
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"eslint-plugin-unicorn@npm:^47.0.0":
|
||||
version: 47.0.0
|
||||
resolution: "eslint-plugin-unicorn@npm:47.0.0"
|
||||
@@ -16127,13 +15931,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"fflate@npm:^0.4.8":
|
||||
version: 0.4.8
|
||||
resolution: "fflate@npm:0.4.8"
|
||||
checksum: 29d8cbe44d5e7f53e7f5a160ac7f9cc025480c7b3bfd85c5f898cbe20dfa2dad4732daa534982664bf30b35896a90af44ea33ede5d94c5ffd1b8b0c0a0a56ca2
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"fflate@npm:^0.7.4":
|
||||
version: 0.7.4
|
||||
resolution: "fflate@npm:0.7.4"
|
||||
@@ -17687,16 +17484,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"html2canvas@npm:^1.0.0-rc.5":
|
||||
version: 1.4.1
|
||||
resolution: "html2canvas@npm:1.4.1"
|
||||
dependencies:
|
||||
css-line-break: ^2.1.0
|
||||
text-segmentation: ^1.0.3
|
||||
checksum: c134324af57f3262eecf982e436a4843fded3c6cf61954440ffd682527e4dd350e0c2fafd217c0b6f9a455fe345d0c67b4505689796ab160d4ca7c91c3766739
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"htmlparser2@npm:^3.9.2":
|
||||
version: 3.10.1
|
||||
resolution: "htmlparser2@npm:3.10.1"
|
||||
@@ -19924,31 +19711,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"jspdf@npm:^2.5.1":
|
||||
version: 2.5.1
|
||||
resolution: "jspdf@npm:2.5.1"
|
||||
dependencies:
|
||||
"@babel/runtime": ^7.14.0
|
||||
atob: ^2.1.2
|
||||
btoa: ^1.2.1
|
||||
canvg: ^3.0.6
|
||||
core-js: ^3.6.0
|
||||
dompurify: ^2.2.0
|
||||
fflate: ^0.4.8
|
||||
html2canvas: ^1.0.0-rc.5
|
||||
dependenciesMeta:
|
||||
canvg:
|
||||
optional: true
|
||||
core-js:
|
||||
optional: true
|
||||
dompurify:
|
||||
optional: true
|
||||
html2canvas:
|
||||
optional: true
|
||||
checksum: 9ecdccc50678cd780f0995157618630ca0da65576835983232d48001aab0b29e51af765e078808526d5e5e2e1ebf3cee460e03eaf590f875d160f2e0cb614a1e
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"jsx-ast-utils@npm:^2.4.1 || ^3.0.0, jsx-ast-utils@npm:^3.3.3":
|
||||
version: 3.3.3
|
||||
resolution: "jsx-ast-utils@npm:3.3.3"
|
||||
@@ -23051,13 +22813,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"performance-now@npm:^2.1.0":
|
||||
version: 2.1.0
|
||||
resolution: "performance-now@npm:2.1.0"
|
||||
checksum: 534e641aa8f7cba160f0afec0599b6cecefbb516a2e837b512be0adbe6c1da5550e89c78059c7fabc5c9ffdf6627edabe23eb7c518c4500067a898fa65c2b550
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"picocolors@npm:^1.0.0":
|
||||
version: 1.0.0
|
||||
resolution: "picocolors@npm:1.0.0"
|
||||
@@ -23779,15 +23534,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"raf@npm:^3.4.1":
|
||||
version: 3.4.1
|
||||
resolution: "raf@npm:3.4.1"
|
||||
dependencies:
|
||||
performance-now: ^2.1.0
|
||||
checksum: 50ba284e481c8185dbcf45fc4618ba3aec580bb50c9121385d5698cb6012fe516d2015b1df6dd407a7b7c58d44be8086108236affbce1861edd6b44637c8cd52
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"ramda@npm:0.29.0":
|
||||
version: 0.29.0
|
||||
resolution: "ramda@npm:0.29.0"
|
||||
@@ -24479,7 +24225,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"regenerator-runtime@npm:^0.13.11, regenerator-runtime@npm:^0.13.7, regenerator-runtime@npm:^0.13.9":
|
||||
"regenerator-runtime@npm:^0.13.11, regenerator-runtime@npm:^0.13.9":
|
||||
version: 0.13.11
|
||||
resolution: "regenerator-runtime@npm:0.13.11"
|
||||
checksum: 27481628d22a1c4e3ff551096a683b424242a216fee44685467307f14d58020af1e19660bf2e26064de946bad7eff28950eae9f8209d55723e2d9351e632bbb4
|
||||
@@ -24898,13 +24644,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"rgbcolor@npm:^1.0.1":
|
||||
version: 1.0.1
|
||||
resolution: "rgbcolor@npm:1.0.1"
|
||||
checksum: bd062ac007a3e979e2f83dc69feb3cc4f9bca7d8631899548394160e30c47e4f7e52b31aa3f66a69061ad56e899e812ec52f5c33686c085d72c9b3d22faed1c8
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"rimraf@npm:^2.6.1":
|
||||
version: 2.7.1
|
||||
resolution: "rimraf@npm:2.7.1"
|
||||
@@ -25810,13 +25549,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"stackblur-canvas@npm:^2.0.0":
|
||||
version: 2.6.0
|
||||
resolution: "stackblur-canvas@npm:2.6.0"
|
||||
checksum: 4356b3362773ff9511a8cea715ceda94e45c4e8c34276ddc7e71f2817467b09f66d6bcb299340a661d8ddc053da682aa4d93080ea97492514028762c2ab88e8d
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"stacktrace-parser@npm:^0.1.10":
|
||||
version: 0.1.10
|
||||
resolution: "stacktrace-parser@npm:0.1.10"
|
||||
@@ -26350,13 +26082,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"svg-pathdata@npm:^6.0.3":
|
||||
version: 6.0.3
|
||||
resolution: "svg-pathdata@npm:6.0.3"
|
||||
checksum: f0e55be50c654be5d259d70945ed7e5354bf78e51c6039b4045d9f7c49d703a0c33dda36751815aec2824d046c417c35226e7491246ffff3e9164735ea428446
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"swap-case@npm:^2.0.2":
|
||||
version: 2.0.2
|
||||
resolution: "swap-case@npm:2.0.2"
|
||||
@@ -26586,15 +26311,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"text-segmentation@npm:^1.0.3":
|
||||
version: 1.0.3
|
||||
resolution: "text-segmentation@npm:1.0.3"
|
||||
dependencies:
|
||||
utrie: ^1.0.2
|
||||
checksum: 2e24632d59567c55ab49ac324815e2f7a8043e63e26b109636322ac3e30692cee8679a448fd5d0f0598a345f407afd0e34ba612e22524cf576d382d84058c013
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"text-table@npm:^0.2.0":
|
||||
version: 0.2.0
|
||||
resolution: "text-table@npm:0.2.0"
|
||||
@@ -27648,15 +27364,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"utrie@npm:^1.0.2":
|
||||
version: 1.0.2
|
||||
resolution: "utrie@npm:1.0.2"
|
||||
dependencies:
|
||||
base64-arraybuffer: ^1.0.2
|
||||
checksum: c96fbb7d4d8855a154327da0b18e39b7511cc70a7e4bcc3658e24f424bb884312d72b5ba777500b8858e34d365dc6b1a921dc5ca2f0d341182519c6b78e280a5
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"uuid@npm:9.0.0, uuid@npm:^9.0.0":
|
||||
version: 9.0.0
|
||||
resolution: "uuid@npm:9.0.0"
|
||||
@@ -28302,7 +28009,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"which@npm:^3.0.0, which@npm:^3.0.1":
|
||||
"which@npm:^3.0.0":
|
||||
version: 3.0.1
|
||||
resolution: "which@npm:3.0.1"
|
||||
dependencies:
|
||||
|
||||
Reference in New Issue
Block a user