mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-04 08:38:34 +00:00
Compare commits
214 Commits
xp/02-07-f
...
v0.21.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f0aafda509 | ||
|
|
c57f41805f | ||
|
|
984a6763ae | ||
|
|
dd1cf14069 | ||
|
|
d7268ce04c | ||
|
|
e4e3d8ef59 | ||
|
|
1081d6281f | ||
|
|
3820186512 | ||
|
|
7d4bb5150e | ||
|
|
a2125787c2 | ||
|
|
93d8e22b07 | ||
|
|
780c35eabe | ||
|
|
280227fa5f | ||
|
|
0887c1864c | ||
|
|
1b858e1e6c | ||
|
|
8c87d2a39e | ||
|
|
238ec59dd2 | ||
|
|
ca75162fc9 | ||
|
|
bda5562f90 | ||
|
|
b8e7ca3214 | ||
|
|
ebdeaf3783 | ||
|
|
d1b82f0c58 | ||
|
|
a28b8b1b11 | ||
|
|
558e84138c | ||
|
|
49c6ad7c04 | ||
|
|
646182ea2a | ||
|
|
e927d02c96 | ||
|
|
1f45cc5dec | ||
|
|
e1bd2047c4 | ||
|
|
43809838ef | ||
|
|
3792464fa0 | ||
|
|
af48df230d | ||
|
|
f93acc6635 | ||
|
|
40f218c898 | ||
|
|
952f1878a6 | ||
|
|
6e10fe6205 | ||
|
|
eb0bcd9b99 | ||
|
|
92240fc1a2 | ||
|
|
fddf68f061 | ||
|
|
4e33059d58 | ||
|
|
ea9de7b542 | ||
|
|
c306d98370 | ||
|
|
53dff7a158 | ||
|
|
8c473cf685 | ||
|
|
da580076b0 | ||
|
|
8a13eca271 | ||
|
|
568a390b75 | ||
|
|
e376992ccf | ||
|
|
854569af2d | ||
|
|
bb1270061a | ||
|
|
41499c1cd6 | ||
|
|
aed7f40568 | ||
|
|
0fbca31c27 | ||
|
|
96e860caf3 | ||
|
|
2a1306c58c | ||
|
|
5a1106fb88 | ||
|
|
138e7f60de | ||
|
|
3ecdc377fe | ||
|
|
eed26b1601 | ||
|
|
0f7a739b3b | ||
|
|
a76414066a | ||
|
|
905349a139 | ||
|
|
3090724659 | ||
|
|
fa50743393 | ||
|
|
ae92aef1a4 | ||
|
|
eebc7b751a | ||
|
|
46d8d30e62 | ||
|
|
adbd41130c | ||
|
|
7a1d5ab252 | ||
|
|
030af6f426 | ||
|
|
133be72ac2 | ||
|
|
8ce10e6d0a | ||
|
|
0aeb3041b5 | ||
|
|
6cf182190c | ||
|
|
6033baeb86 | ||
|
|
363476a46c | ||
|
|
90a3bd53cd | ||
|
|
f2865c7bb0 | ||
|
|
2533a92873 | ||
|
|
6939e80827 | ||
|
|
c8d22d97d5 | ||
|
|
565d7b2b1e | ||
|
|
a9ba54a92e | ||
|
|
093bffdf5c | ||
|
|
01429f8f66 | ||
|
|
773db7860a | ||
|
|
727c540fda | ||
|
|
56e98f26ff | ||
|
|
dd109459a9 | ||
|
|
e334347592 | ||
|
|
64ed23d473 | ||
|
|
cfde175298 | ||
|
|
b4c643e8bc | ||
|
|
70a318f1c4 | ||
|
|
a4c76ff485 | ||
|
|
9206145a48 | ||
|
|
f2646796fc | ||
|
|
a1500e3ee1 | ||
|
|
c61df18ab9 | ||
|
|
03dd073cb4 | ||
|
|
b53b2acfe3 | ||
|
|
80a663efe7 | ||
|
|
5109ceccec | ||
|
|
2026f12daa | ||
|
|
a5eb1b9985 | ||
|
|
bd5428e311 | ||
|
|
90c43356c1 | ||
|
|
abfbf07712 | ||
|
|
f3e9b4bbf0 | ||
|
|
90c3c4bf7f | ||
|
|
2adb8e1404 | ||
|
|
c5c6978136 | ||
|
|
c8392d0cbe | ||
|
|
fde97dcf78 | ||
|
|
0f18585631 | ||
|
|
1386a66579 | ||
|
|
07b1c2fa05 | ||
|
|
501b5f6a97 | ||
|
|
3b13affa58 | ||
|
|
94ddcc7a7a | ||
|
|
c4c6cdb6f2 | ||
|
|
35bea20b80 | ||
|
|
85d176ce6f | ||
|
|
b21a0b4520 | ||
|
|
432634c5a3 | ||
|
|
51b3f2b057 | ||
|
|
6d1fe37e4c | ||
|
|
a3e4978354 | ||
|
|
b8fd6370f8 | ||
|
|
c6d4787954 | ||
|
|
90bf003ab8 | ||
|
|
e125b2a7c0 | ||
|
|
36b1ca4327 | ||
|
|
ef76c83184 | ||
|
|
c20514f269 | ||
|
|
08eb248cb4 | ||
|
|
1b5df6b75e | ||
|
|
add4a5859d | ||
|
|
f091ac7e74 | ||
|
|
6833c2a2dd | ||
|
|
5a955d9f70 | ||
|
|
679e9e1966 | ||
|
|
d9fade8045 | ||
|
|
8d9f5327a1 | ||
|
|
b759a22221 | ||
|
|
f2e2072878 | ||
|
|
dad858014f | ||
|
|
8427293d36 | ||
|
|
d8997576a5 | ||
|
|
2d304adf15 | ||
|
|
7f98420061 | ||
|
|
4e1e91120f | ||
|
|
eb219b2c48 | ||
|
|
f374f2695f | ||
|
|
bd30a73db8 | ||
|
|
cad4dde4b1 | ||
|
|
bed02f2520 | ||
|
|
521eb09a7a | ||
|
|
cb7b5caa74 | ||
|
|
6276732efc | ||
|
|
d38458b733 | ||
|
|
08327b14d6 | ||
|
|
7af5e53838 | ||
|
|
032244ae61 | ||
|
|
b74d40d45f | ||
|
|
9cb80205f8 | ||
|
|
275098abe2 | ||
|
|
ab60203849 | ||
|
|
cfd709bbbc | ||
|
|
56db0d3b0e | ||
|
|
c94f782da2 | ||
|
|
d96f00925c | ||
|
|
b785b7e8e5 | ||
|
|
b1d4a3c001 | ||
|
|
1d6698572a | ||
|
|
10d86fee9f | ||
|
|
dc67614d6d | ||
|
|
6ed9c33c33 | ||
|
|
cbe372c6ec | ||
|
|
b6faf70e4d | ||
|
|
e7f5601303 | ||
|
|
c3a5301d5b | ||
|
|
b0b7534599 | ||
|
|
9f8cf4e2ca | ||
|
|
93d4b6dc4d | ||
|
|
7478df56ee | ||
|
|
1dbd34177e | ||
|
|
3467515ae9 | ||
|
|
1be83dc330 | ||
|
|
0a37ca91fb | ||
|
|
eac8f32f4c | ||
|
|
b099deb6df | ||
|
|
782f31ad26 | ||
|
|
5930bba97d | ||
|
|
afd1a30b96 | ||
|
|
bc0f32f20b | ||
|
|
d31e0c0e71 | ||
|
|
2eecfef393 | ||
|
|
fe05872ada | ||
|
|
58d6a96e45 | ||
|
|
5f3cf53819 | ||
|
|
ac096f533a | ||
|
|
8957d0645f | ||
|
|
c9e14ac0db | ||
|
|
fec698fd8b | ||
|
|
587fea02b8 | ||
|
|
731a4c952f | ||
|
|
f1882061a2 | ||
|
|
2f1f09e25f | ||
|
|
47a8d15878 | ||
|
|
eda680ccdc | ||
|
|
51dddc10be | ||
|
|
b37182ceb7 | ||
|
|
6a66bf53a8 |
@@ -6,7 +6,7 @@
|
||||
"workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}",
|
||||
"features": {
|
||||
"ghcr.io/devcontainers/features/node:1": {
|
||||
"version": "18"
|
||||
"version": "22"
|
||||
},
|
||||
"ghcr.io/devcontainers/features/rust:1": {}
|
||||
},
|
||||
|
||||
6
.docker/selfhost/config.example.json
Normal file
6
.docker/selfhost/config.example.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"$schema": "https://github.com/toeverything/affine/releases/latest/download/config.schema.json",
|
||||
"server": {
|
||||
"name": "AFFiNE Self Hosted Server"
|
||||
}
|
||||
}
|
||||
@@ -3,42 +3,6 @@
|
||||
"title": "AFFiNE Application Configuration",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"redis": {
|
||||
"type": "object",
|
||||
"description": "Configuration for redis module",
|
||||
"properties": {
|
||||
"db": {
|
||||
"type": "number",
|
||||
"description": "The database index of redis server to be used(Must be less than 10).\n@default 0\n@environment `REDIS_DATABASE`",
|
||||
"default": 0
|
||||
},
|
||||
"host": {
|
||||
"type": "string",
|
||||
"description": "The host of the redis server.\n@default \"localhost\"\n@environment `REDIS_HOST`",
|
||||
"default": "localhost"
|
||||
},
|
||||
"port": {
|
||||
"type": "number",
|
||||
"description": "The port of the redis server.\n@default 6379\n@environment `REDIS_PORT`",
|
||||
"default": 6379
|
||||
},
|
||||
"username": {
|
||||
"type": "string",
|
||||
"description": "The username of the redis server.\n@default \"\"\n@environment `REDIS_USERNAME`",
|
||||
"default": ""
|
||||
},
|
||||
"password": {
|
||||
"type": "string",
|
||||
"description": "The password of the redis server.\n@default \"\"\n@environment `REDIS_PASSWORD`",
|
||||
"default": ""
|
||||
},
|
||||
"ioredis": {
|
||||
"type": "object",
|
||||
"description": "The config for the ioredis client.\n@default {}\n@link https://github.com/luin/ioredis",
|
||||
"default": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"metrics": {
|
||||
"type": "object",
|
||||
"description": "Configuration for metrics module",
|
||||
@@ -50,25 +14,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"graphql": {
|
||||
"type": "object",
|
||||
"description": "Configuration for graphql module",
|
||||
"properties": {
|
||||
"apolloDriverConfig": {
|
||||
"type": "object",
|
||||
"description": "The config for underlying nestjs GraphQL and apollo driver engine.\n@default {\"buildSchemaOptions\":{\"numberScalarMode\":\"integer\"},\"useGlobalPrefix\":true,\"playground\":true,\"introspection\":true,\"sortSchema\":true}\n@link https://docs.nestjs.com/graphql/quick-start",
|
||||
"default": {
|
||||
"buildSchemaOptions": {
|
||||
"numberScalarMode": "integer"
|
||||
},
|
||||
"useGlobalPrefix": true,
|
||||
"playground": true,
|
||||
"introspection": true,
|
||||
"sortSchema": true
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"crypto": {
|
||||
"type": "object",
|
||||
"description": "Configuration for crypto module",
|
||||
@@ -86,25 +31,20 @@
|
||||
"properties": {
|
||||
"queue": {
|
||||
"type": "object",
|
||||
"description": "The config for job queues\n@default {\"prefix\":\"affine_job\",\"defaultJobOptions\":{\"attempts\":5,\"removeOnComplete\":true,\"removeOnFail\":{\"age\":86400,\"count\":500}}}\n@link https://api.docs.bullmq.io/interfaces/v5.QueueOptions.html",
|
||||
"description": "The config for job queues\n@default {\"attempts\":5,\"removeOnComplete\":true,\"removeOnFail\":{\"age\":86400,\"count\":500}}\n@link https://api.docs.bullmq.io/interfaces/v5.QueueOptions.html",
|
||||
"default": {
|
||||
"prefix": "affine_job",
|
||||
"defaultJobOptions": {
|
||||
"attempts": 5,
|
||||
"removeOnComplete": true,
|
||||
"removeOnFail": {
|
||||
"age": 86400,
|
||||
"count": 500
|
||||
}
|
||||
"attempts": 5,
|
||||
"removeOnComplete": true,
|
||||
"removeOnFail": {
|
||||
"age": 86400,
|
||||
"count": 500
|
||||
}
|
||||
}
|
||||
},
|
||||
"worker": {
|
||||
"type": "object",
|
||||
"description": "The config for job workers\n@default {\"defaultWorkerOptions\":{}}\n@link https://api.docs.bullmq.io/interfaces/v5.WorkerOptions.html",
|
||||
"default": {
|
||||
"defaultWorkerOptions": {}
|
||||
}
|
||||
"description": "The config for job workers\n@default {}\n@link https://api.docs.bullmq.io/interfaces/v5.WorkerOptions.html",
|
||||
"default": {}
|
||||
},
|
||||
"queues.copilot": {
|
||||
"type": "object",
|
||||
@@ -209,22 +149,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"db": {
|
||||
"type": "object",
|
||||
"description": "Configuration for db module",
|
||||
"properties": {
|
||||
"datasourceUrl": {
|
||||
"type": "string",
|
||||
"description": "The datasource url for the prisma client.\n@default \"postgresql://localhost:5432/affine\"\n@environment `DATABASE_URL`",
|
||||
"default": "postgresql://localhost:5432/affine"
|
||||
},
|
||||
"prisma": {
|
||||
"type": "object",
|
||||
"description": "The config for the prisma client.\n@default {}\n@link https://www.prisma.io/docs/reference/api-reference/prisma-client-reference",
|
||||
"default": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"auth": {
|
||||
"type": "object",
|
||||
"description": "Configuration for auth module",
|
||||
@@ -427,6 +351,24 @@
|
||||
"accountId": {
|
||||
"type": "string",
|
||||
"description": "The account id for the cloudflare r2 storage provider."
|
||||
},
|
||||
"usePresignedURL": {
|
||||
"type": "object",
|
||||
"description": "The presigned url config for the cloudflare r2 storage provider.",
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"type": "boolean",
|
||||
"description": "Whether to use presigned url for the cloudflare r2 storage provider."
|
||||
},
|
||||
"urlPrefix": {
|
||||
"type": "string",
|
||||
"description": "The presigned url prefix for the cloudflare r2 storage provider.\nsee https://developers.cloudflare.com/waf/custom-rules/use-cases/configure-token-authentication/ to configure it.\nExample value: \"https://storage.example.com\"\nExample rule: is_timed_hmac_valid_v0(\"your_secret\", http.request.uri, 10800, http.request.timestamp.sec, 6)"
|
||||
},
|
||||
"signKey": {
|
||||
"type": "string",
|
||||
"description": "The presigned key for the cloudflare r2 storage provider."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -530,6 +472,24 @@
|
||||
"accountId": {
|
||||
"type": "string",
|
||||
"description": "The account id for the cloudflare r2 storage provider."
|
||||
},
|
||||
"usePresignedURL": {
|
||||
"type": "object",
|
||||
"description": "The presigned url config for the cloudflare r2 storage provider.",
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"type": "boolean",
|
||||
"description": "Whether to use presigned url for the cloudflare r2 storage provider."
|
||||
},
|
||||
"urlPrefix": {
|
||||
"type": "string",
|
||||
"description": "The presigned url prefix for the cloudflare r2 storage provider.\nsee https://developers.cloudflare.com/waf/custom-rules/use-cases/configure-token-authentication/ to configure it.\nExample value: \"https://storage.example.com\"\nExample rule: is_timed_hmac_valid_v0(\"your_secret\", http.request.uri, 10800, http.request.timestamp.sec, 6)"
|
||||
},
|
||||
"signKey": {
|
||||
"type": "string",
|
||||
"description": "The presigned key for the cloudflare r2 storage provider."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -557,8 +517,8 @@
|
||||
},
|
||||
"externalUrl": {
|
||||
"type": "string",
|
||||
"description": "Base url of AFFiNE server, used for generating external urls.\nDefault to be `[server.protocol]://[server.host][:server.port]` if not specified.\n \n@default \"http://localhost:3010\"\n@environment `AFFINE_SERVER_EXTERNAL_URL`",
|
||||
"default": "http://localhost:3010"
|
||||
"description": "Base url of AFFiNE server, used for generating external urls.\nDefault to be `[server.protocol]://[server.host][:server.port]` if not specified.\n \n@default \"\"\n@environment `AFFINE_SERVER_EXTERNAL_URL`",
|
||||
"default": ""
|
||||
},
|
||||
"https": {
|
||||
"type": "boolean",
|
||||
@@ -593,6 +553,17 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"docService": {
|
||||
"type": "object",
|
||||
"description": "Configuration for docService module",
|
||||
"properties": {
|
||||
"endpoint": {
|
||||
"type": "string",
|
||||
"description": "The endpoint of the doc service.\n@default \"\"\n@environment `DOC_SERVICE_ENDPOINT`",
|
||||
"default": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
"client": {
|
||||
"type": "object",
|
||||
"description": "Configuration for client module",
|
||||
@@ -765,6 +736,24 @@
|
||||
"accountId": {
|
||||
"type": "string",
|
||||
"description": "The account id for the cloudflare r2 storage provider."
|
||||
},
|
||||
"usePresignedURL": {
|
||||
"type": "object",
|
||||
"description": "The presigned url config for the cloudflare r2 storage provider.",
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"type": "boolean",
|
||||
"description": "Whether to use presigned url for the cloudflare r2 storage provider."
|
||||
},
|
||||
"urlPrefix": {
|
||||
"type": "string",
|
||||
"description": "The presigned url prefix for the cloudflare r2 storage provider.\nsee https://developers.cloudflare.com/waf/custom-rules/use-cases/configure-token-authentication/ to configure it.\nExample value: \"https://storage.example.com\"\nExample rule: is_timed_hmac_valid_v0(\"your_secret\", http.request.uri, 10800, http.request.timestamp.sec, 6)"
|
||||
},
|
||||
"signKey": {
|
||||
"type": "string",
|
||||
"description": "The presigned key for the cloudflare r2 storage provider."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -877,7 +866,7 @@
|
||||
},
|
||||
"stripe": {
|
||||
"type": "object",
|
||||
"description": "Stripe API keys\n@default {}\n@link https://docs.stripe.com/api",
|
||||
"description": "Stripe sdk options\n@default {}\n@link https://docs.stripe.com/api",
|
||||
"default": {}
|
||||
}
|
||||
}
|
||||
|
||||
2
.github/actions/deploy/deploy.mjs
vendored
2
.github/actions/deploy/deploy.mjs
vendored
@@ -10,6 +10,7 @@ const {
|
||||
DATABASE_USERNAME,
|
||||
DATABASE_PASSWORD,
|
||||
DATABASE_NAME,
|
||||
GCLOUD_CONNECTION_NAME,
|
||||
CLOUD_SQL_IAM_ACCOUNT,
|
||||
APP_IAM_ACCOUNT,
|
||||
REDIS_SERVER_HOST,
|
||||
@@ -71,6 +72,7 @@ const createHelmCommand = ({ isDryRun }) => {
|
||||
isProduction || isBeta || isInternal
|
||||
? [
|
||||
`--set cloud-sql-proxy.enabled=true`,
|
||||
`--set-string cloud-sql-proxy.database.connectionName="${GCLOUD_CONNECTION_NAME}"`,
|
||||
`--set-string global.database.host=${DATABASE_URL}`,
|
||||
`--set-string global.database.user=${DATABASE_USERNAME}`,
|
||||
`--set-string global.database.password=${DATABASE_PASSWORD}`,
|
||||
|
||||
2
.github/helm/affine/Chart.yaml
vendored
2
.github/helm/affine/Chart.yaml
vendored
@@ -3,4 +3,4 @@ name: affine
|
||||
description: AFFiNE cloud chart
|
||||
type: application
|
||||
version: 0.0.0
|
||||
appVersion: "0.20.0"
|
||||
appVersion: "0.21.0"
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
replicaCount: 3
|
||||
enabled: false
|
||||
database:
|
||||
connectionName: ""
|
||||
|
||||
image:
|
||||
# the tag is defined as chart appVersion.
|
||||
|
||||
@@ -3,7 +3,7 @@ name: graphql
|
||||
description: AFFiNE GraphQL server
|
||||
type: application
|
||||
version: 0.0.0
|
||||
appVersion: "0.20.0"
|
||||
appVersion: "0.21.0"
|
||||
dependencies:
|
||||
- name: gcloud-sql-proxy
|
||||
version: 0.0.0
|
||||
|
||||
2
.github/helm/affine/charts/sync/Chart.yaml
vendored
2
.github/helm/affine/charts/sync/Chart.yaml
vendored
@@ -3,7 +3,7 @@ name: sync
|
||||
description: AFFiNE Sync Server
|
||||
type: application
|
||||
version: 0.0.0
|
||||
appVersion: "0.20.0"
|
||||
appVersion: "0.21.0"
|
||||
dependencies:
|
||||
- name: gcloud-sql-proxy
|
||||
version: 0.0.0
|
||||
|
||||
18
.github/workflows/deploy.yml
vendored
18
.github/workflows/deploy.yml
vendored
@@ -92,34 +92,16 @@ jobs:
|
||||
APP_VERSION: ${{ steps.version.outputs.APP_VERSION }}
|
||||
DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }}
|
||||
CANARY_DEPLOY_HOST: ${{ secrets.CANARY_DEPLOY_HOST }}
|
||||
R2_ACCOUNT_ID: ${{ secrets.R2_ACCOUNT_ID }}
|
||||
R2_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }}
|
||||
R2_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }}
|
||||
CAPTCHA_TURNSTILE_SECRET: ${{ secrets.CAPTCHA_TURNSTILE_SECRET }}
|
||||
COPILOT_OPENAI_API_KEY: ${{ secrets.COPILOT_OPENAI_API_KEY }}
|
||||
COPILOT_FAL_API_KEY: ${{ secrets.COPILOT_FAL_API_KEY }}
|
||||
COPILOT_GOOGLE_API_KEY: ${{ secrets.COPILOT_GOOGLE_API_KEY }}
|
||||
COPILOT_PERPLEXITY_API_KEY: ${{ secrets.COPILOT_PERPLEXITY_API_KEY }}
|
||||
COPILOT_UNSPLASH_API_KEY: ${{ secrets.COPILOT_UNSPLASH_API_KEY }}
|
||||
METRICS_CUSTOMER_IO_TOKEN: ${{ secrets.METRICS_CUSTOMER_IO_TOKEN }}
|
||||
MAILER_SENDER: ${{ secrets.OAUTH_EMAIL_SENDER }}
|
||||
MAILER_USER: ${{ secrets.OAUTH_EMAIL_LOGIN }}
|
||||
MAILER_PASSWORD: ${{ secrets.OAUTH_EMAIL_PASSWORD }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
AFFINE_GOOGLE_CLIENT_ID: ${{ secrets.AFFINE_GOOGLE_CLIENT_ID }}
|
||||
AFFINE_GOOGLE_CLIENT_SECRET: ${{ secrets.AFFINE_GOOGLE_CLIENT_SECRET }}
|
||||
DATABASE_URL: ${{ secrets.DATABASE_URL }}
|
||||
DATABASE_USERNAME: ${{ secrets.DATABASE_USERNAME }}
|
||||
DATABASE_PASSWORD: ${{ secrets.DATABASE_PASSWORD }}
|
||||
DATABASE_NAME: ${{ secrets.DATABASE_NAME }}
|
||||
GCLOUD_CONNECTION_NAME: ${{ secrets.GCLOUD_CONNECTION_NAME }}
|
||||
GCLOUD_CLOUD_SQL_INTERNAL_ENDPOINT: ${{ secrets.GCLOUD_CLOUD_SQL_INTERNAL_ENDPOINT }}
|
||||
REDIS_SERVER_HOST: ${{ secrets.REDIS_SERVER_HOST }}
|
||||
REDIS_SERVER_PASSWORD: ${{ secrets.REDIS_SERVER_PASSWORD }}
|
||||
CLOUD_SQL_IAM_ACCOUNT: ${{ secrets.CLOUD_SQL_IAM_ACCOUNT }}
|
||||
APP_IAM_ACCOUNT: ${{ secrets.APP_IAM_ACCOUNT }}
|
||||
STRIPE_API_KEY: ${{ secrets.STRIPE_API_KEY }}
|
||||
STRIPE_WEBHOOK_KEY: ${{ secrets.STRIPE_WEBHOOK_KEY }}
|
||||
STATIC_IP_NAME: ${{ secrets.STATIC_IP_NAME }}
|
||||
|
||||
deploy-done:
|
||||
|
||||
20
.github/workflows/release-desktop.yml
vendored
20
.github/workflows/release-desktop.yml
vendored
@@ -142,11 +142,19 @@ jobs:
|
||||
# some flatpak deps need git protocol.file.allow
|
||||
git config --global protocol.file.allow always
|
||||
|
||||
- name: Remove nbstore node_modules
|
||||
shell: bash
|
||||
# node_modules of nbstore is not needed for building, and it will make the build process out of memory
|
||||
run: |
|
||||
rm -rf packages/frontend/apps/electron/node_modules/@affine/nbstore/node_modules/@blocksuite
|
||||
rm -rf packages/frontend/apps/electron/node_modules/@affine/native/node_modules
|
||||
|
||||
- name: make
|
||||
run: yarn affine @affine/electron make --platform=${{ matrix.spec.platform }} --arch=${{ matrix.spec.arch }}
|
||||
env:
|
||||
SKIP_WEB_BUILD: 1
|
||||
HOIST_NODE_MODULES: 1
|
||||
NODE_OPTIONS: --max-old-space-size=14384
|
||||
|
||||
- name: signing DMG
|
||||
if: ${{ matrix.spec.platform == 'darwin' }}
|
||||
@@ -240,11 +248,20 @@ jobs:
|
||||
- name: Build Desktop Layers
|
||||
run: yarn affine @affine/electron build
|
||||
|
||||
- name: Remove nbstore node_modules
|
||||
shell: bash
|
||||
# node_modules of nbstore is not needed for building, and it will make the build process out of memory
|
||||
run: |
|
||||
rm -rf packages/frontend/apps/electron/node_modules/@affine/nbstore/node_modules/@blocksuite
|
||||
rm -rf packages/frontend/apps/electron/node_modules/@affine/native/node_modules
|
||||
|
||||
- name: package
|
||||
run: yarn affine @affine/electron package --platform=${{ matrix.spec.platform }} --arch=${{ matrix.spec.arch }}
|
||||
run: |
|
||||
yarn affine @affine/electron package --platform=${{ matrix.spec.platform }} --arch=${{ matrix.spec.arch }}
|
||||
env:
|
||||
SKIP_WEB_BUILD: 1
|
||||
HOIST_NODE_MODULES: 1
|
||||
NODE_OPTIONS: --max-old-space-size=14384
|
||||
|
||||
- name: get all files to be signed
|
||||
id: get_files_to_be_signed
|
||||
@@ -443,6 +460,7 @@ jobs:
|
||||
run: |
|
||||
cp ./.docker/selfhost/compose.yml ./release/docker-compose.yml
|
||||
cp ./.docker/selfhost/.env.example ./release/.env.example
|
||||
cp ./.docker/selfhost/schema.json ./release/config.schema.json
|
||||
- name: Generate Release yml
|
||||
run: |
|
||||
node ./scripts/generate-release-yml.mjs
|
||||
|
||||
25
.github/workflows/release-mobile.yml
vendored
25
.github/workflows/release-mobile.yml
vendored
@@ -117,10 +117,31 @@ jobs:
|
||||
name: android
|
||||
path: packages/frontend/apps/android/dist
|
||||
|
||||
ios:
|
||||
runs-on: namespace-profile-macos
|
||||
determine-ios-runner:
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- build-ios-web
|
||||
outputs:
|
||||
RUNNER: ${{ steps.runner.outputs.RUNNER }}
|
||||
steps:
|
||||
- name: Determine Runner
|
||||
id: runner
|
||||
# Randomly pick runner with 80% chance for blaze/macos-14 and 20% chance for namespace-profile-macos
|
||||
# blaze/macos-14 is free but has limited concurrency
|
||||
run: |
|
||||
RANDOM_NUMBER=$(( $RANDOM % 100 + 1 ))
|
||||
if [ $RANDOM_NUMBER -le 20 ]; then
|
||||
echo "Selected namespace-profile-macos (20% probability)"
|
||||
echo "RUNNER=namespace-profile-macos" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "Selected blaze/macos-14 (80% probability)"
|
||||
echo "RUNNER=blaze/macos-14" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
ios:
|
||||
runs-on: ${{ github.ref_name == 'canary' && 'macos-latest' || needs.determine-ios-runner.outputs.RUNNER }}
|
||||
needs:
|
||||
- determine-ios-runner
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Download mobile artifact
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -12,4 +12,4 @@ npmPublishAccess: public
|
||||
|
||||
npmPublishRegistry: "https://registry.npmjs.org"
|
||||
|
||||
yarnPath: .yarn/releases/yarn-4.8.0.cjs
|
||||
yarnPath: .yarn/releases/yarn-4.8.1.cjs
|
||||
|
||||
374
Cargo.lock
generated
374
Cargo.lock
generated
@@ -81,7 +81,6 @@ dependencies = [
|
||||
"coreaudio-rs",
|
||||
"dispatch2",
|
||||
"libc",
|
||||
"mp3lame-encoder",
|
||||
"napi",
|
||||
"napi-build",
|
||||
"napi-derive",
|
||||
@@ -349,7 +348,7 @@ dependencies = [
|
||||
"derive_utils",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.99",
|
||||
"syn 2.0.100",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -358,15 +357,6 @@ version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
|
||||
|
||||
[[package]]
|
||||
name = "autotools"
|
||||
version = "0.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ef941527c41b0fc0dd48511a8154cd5fc7e29200a0ff8b7203c5d777dbc795cf"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "backtrace"
|
||||
version = "0.3.74"
|
||||
@@ -406,9 +396,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "base64ct"
|
||||
version = "1.6.0"
|
||||
version = "1.7.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b"
|
||||
checksum = "89e25b6adfb930f02d1981565a6e5d9c547ac15a96606256d3b59040e5cd4ca3"
|
||||
|
||||
[[package]]
|
||||
name = "basic-toml"
|
||||
@@ -434,7 +424,7 @@ dependencies = [
|
||||
"regex",
|
||||
"rustc-hash 1.1.0",
|
||||
"shlex",
|
||||
"syn 2.0.99",
|
||||
"syn 2.0.100",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -508,18 +498,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "borsh"
|
||||
version = "1.5.5"
|
||||
version = "1.5.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5430e3be710b68d984d1391c854eb431a9d548640711faa54eecb1df93db91cc"
|
||||
checksum = "ad8646f98db542e39fc66e68a20b2144f6a732636df7c2354e74645faaa433ce"
|
||||
dependencies = [
|
||||
"cfg_aliases",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bpaf"
|
||||
version = "0.9.18"
|
||||
version = "0.9.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4de4d74c5891642753c67ab88f58d971a68dd98673b69689a8c24ce3ec78a412"
|
||||
checksum = "4848ed5727d39a7573551c205bcb1ccd88c8cad4ed2c80f62e2316f208196b8d"
|
||||
|
||||
[[package]]
|
||||
name = "bstr"
|
||||
@@ -729,9 +719,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.31"
|
||||
version = "4.5.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "027bb0d98429ae334a8698531da7077bdf906419543a35a55c2cb1b66437d767"
|
||||
checksum = "d8aa86934b44c19c50f87cc2790e19f54f7a67aedb64101c2e1a2e5ecfb73944"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
@@ -739,9 +729,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.5.31"
|
||||
version = "4.5.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5589e0cba072e0f3d23791efac0fd8627b49c829c196a492e88168e6a669d863"
|
||||
checksum = "2414dbb2dd0695280da6ea9261e327479e9d37b0630f6b53ba2a11c60c679fd9"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
@@ -751,14 +741,14 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "4.5.28"
|
||||
version = "4.5.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bf4ced95c6f4a675af3da73304b9ac4ed991640c36374e4b46795c49e17cf1ed"
|
||||
checksum = "09176aae279615badda0765c0c0b3f6ed53f4709118af73cf4655d85d1530cd7"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.99",
|
||||
"syn 2.0.100",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1068,7 +1058,7 @@ checksum = "30542c1ad912e0e3d22a1935c290e12e8a29d704a420177a31faad4a601a0800"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.99",
|
||||
"syn 2.0.100",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1081,7 +1071,7 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"rustc_version",
|
||||
"syn 2.0.99",
|
||||
"syn 2.0.100",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1092,7 +1082,7 @@ checksum = "ccfae181bab5ab6c5478b2ccb69e4c68a02f8c3ec72f6616bfec9dbc599d2ee0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.99",
|
||||
"syn 2.0.100",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1133,7 +1123,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.99",
|
||||
"syn 2.0.100",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1259,9 +1249,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "event-listener-strategy"
|
||||
version = "0.5.3"
|
||||
version = "0.5.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c3e4e0dd3673c1139bf041f3008816d9cf2946bbfac2945c09e523b8d7b05b2"
|
||||
checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93"
|
||||
dependencies = [
|
||||
"event-listener",
|
||||
"pin-project-lite",
|
||||
@@ -1298,9 +1288,9 @@ checksum = "e7ef3d5e8ae27277c8285ac43ed153158178ef0f79567f32024ca8140a0c7cd8"
|
||||
|
||||
[[package]]
|
||||
name = "flate2"
|
||||
version = "1.1.0"
|
||||
version = "1.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "11faaf5a5236997af9848be0bef4db95824b1d534ebc64d0f0c6cf3e67bd38dc"
|
||||
checksum = "7ced92e76e966ca2fd84c8f7aa01a4aea65b0eb6648d72f7c8f3e2764a67fece"
|
||||
dependencies = [
|
||||
"crc32fast",
|
||||
"miniz_oxide",
|
||||
@@ -1325,9 +1315,9 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||
|
||||
[[package]]
|
||||
name = "foldhash"
|
||||
version = "0.1.4"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f"
|
||||
checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
|
||||
|
||||
[[package]]
|
||||
name = "foreign-types"
|
||||
@@ -1347,7 +1337,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.99",
|
||||
"syn 2.0.100",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1504,14 +1494,14 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.3.1"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8"
|
||||
checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi 0.13.3+wasi-0.2.2",
|
||||
"windows-targets 0.52.6",
|
||||
"r-efi",
|
||||
"wasi 0.14.2+wasi-0.2.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1539,9 +1529,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "half"
|
||||
version = "2.4.1"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888"
|
||||
checksum = "7db2ff139bba50379da6aa0766b52fdcb62cb5b263009b09ed58ba604e14bbd1"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crunchy",
|
||||
@@ -1669,16 +1659,17 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone"
|
||||
version = "0.1.61"
|
||||
version = "0.1.63"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220"
|
||||
checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8"
|
||||
dependencies = [
|
||||
"android_system_properties",
|
||||
"core-foundation-sys",
|
||||
"iana-time-zone-haiku",
|
||||
"js-sys",
|
||||
"log",
|
||||
"wasm-bindgen",
|
||||
"windows-core 0.52.0",
|
||||
"windows-core 0.61.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1731,9 +1722,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "icu_locid_transform_data"
|
||||
version = "1.5.0"
|
||||
version = "1.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e"
|
||||
checksum = "7515e6d781098bf9f7205ab3fc7e9709d34554ae0b21ddbcb5febfa4bc7df11d"
|
||||
|
||||
[[package]]
|
||||
name = "icu_normalizer"
|
||||
@@ -1755,9 +1746,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "icu_normalizer_data"
|
||||
version = "1.5.0"
|
||||
version = "1.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516"
|
||||
checksum = "c5e8338228bdc8ab83303f16b797e177953730f601a96c25d10cb3ab0daa0cb7"
|
||||
|
||||
[[package]]
|
||||
name = "icu_properties"
|
||||
@@ -1776,9 +1767,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "icu_properties_data"
|
||||
version = "1.5.0"
|
||||
version = "1.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569"
|
||||
checksum = "85fb8799753b75aee8d2a21d7c14d9f38921b54b3dbda10f5a3c7a7b82dba5e2"
|
||||
|
||||
[[package]]
|
||||
name = "icu_provider"
|
||||
@@ -1805,7 +1796,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.99",
|
||||
"syn 2.0.100",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1826,9 +1817,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "icu_segmenter_data"
|
||||
version = "1.5.0"
|
||||
version = "1.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f739ee737260d955e330bc83fdeaaf1631f7fb7ed218761d3c04bb13bb7d79df"
|
||||
checksum = "a1e52775179941363cc594e49ce99284d13d6948928d8e72c755f55e98caa1eb"
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
@@ -1853,9 +1844,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.7.1"
|
||||
version = "2.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652"
|
||||
checksum = "3954d50fe15b02142bf25d3b8bdadb634ec3948f103d04ffe3031bc8fe9d7058"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown 0.15.2",
|
||||
@@ -2006,9 +1997,9 @@ checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa"
|
||||
|
||||
[[package]]
|
||||
name = "libmimalloc-sys"
|
||||
version = "0.1.40"
|
||||
version = "0.1.41"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "07d0e07885d6a754b9c7993f2625187ad694ee985d60f23355ff0e7077261502"
|
||||
checksum = "6b20daca3a4ac14dbdc753c5e90fc7b490a48a9131daed3c9a9ced7b2defd37b"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
@@ -2027,9 +2018,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.9.2"
|
||||
version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6db9c683daf087dc577b7506e9695b3d556a9f3849903fa28186283afd6809e9"
|
||||
checksum = "fe7db12097d22ec582439daf8618b8fdd1a7bef6270e9af3b1ebcd30893cf413"
|
||||
|
||||
[[package]]
|
||||
name = "litemap"
|
||||
@@ -2049,9 +2040,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.26"
|
||||
version = "0.4.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e"
|
||||
checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
|
||||
|
||||
[[package]]
|
||||
name = "loom"
|
||||
@@ -2162,9 +2153,9 @@ checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
|
||||
|
||||
[[package]]
|
||||
name = "mimalloc"
|
||||
version = "0.1.44"
|
||||
version = "0.1.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "99585191385958383e13f6b822e6b6d8d9cf928e7d286ceb092da92b43c87bc1"
|
||||
checksum = "03cb1f88093fe50061ca1195d336ffec131347c7b833db31f9ab62a2d1b7925f"
|
||||
dependencies = [
|
||||
"libmimalloc-sys",
|
||||
]
|
||||
@@ -2193,9 +2184,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.8.5"
|
||||
version = "0.8.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e3e04debbb59698c15bacbb6d93584a8c0ca9cc3213cb423d31f760d8843ce5"
|
||||
checksum = "ff70ce3e48ae43fa075863cef62e8b43b71a4f2382229920e0df362592919430"
|
||||
dependencies = [
|
||||
"adler2",
|
||||
]
|
||||
@@ -2211,27 +2202,6 @@ dependencies = [
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mp3lame-encoder"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc8c8b5cdbe788ccd1098c3d3635298a011cffdebdd3460c9ca5060a7551557b"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"mp3lame-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mp3lame-sys"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "acaec8842b2ebd61692a6c8c2b9f3edbf5c36e5e5c4677b5911430eaf859377c"
|
||||
dependencies = [
|
||||
"autotools",
|
||||
"cc",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nanoid"
|
||||
version = "0.4.0"
|
||||
@@ -2273,7 +2243,7 @@ dependencies = [
|
||||
"napi-derive-backend",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.99",
|
||||
"syn 2.0.100",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2286,7 +2256,7 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"semver",
|
||||
"syn 2.0.99",
|
||||
"syn 2.0.100",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2430,7 +2400,7 @@ dependencies = [
|
||||
"proc-macro-crate",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.99",
|
||||
"syn 2.0.100",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2501,9 +2471,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.21.2"
|
||||
version = "1.21.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c2806eaa3524762875e21c3dcd057bc4b7bfa01ce4da8d46be1cd43649e1cc6b"
|
||||
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
|
||||
|
||||
[[package]]
|
||||
name = "oorandom"
|
||||
@@ -2734,11 +2704,11 @@ checksum = "78451badbdaebaf17f053fd9152b3ffb33b516104eacb45e7864aaa9c712f306"
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.20"
|
||||
version = "0.2.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04"
|
||||
checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
|
||||
dependencies = [
|
||||
"zerocopy 0.7.35",
|
||||
"zerocopy 0.8.24",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2787,13 +2757,19 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.39"
|
||||
version = "1.0.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c1f1914ce909e1658d9907913b4b91947430c7d9be598b15a1912935b8c04801"
|
||||
checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "r-efi"
|
||||
version = "5.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5"
|
||||
|
||||
[[package]]
|
||||
name = "radium"
|
||||
version = "0.7.0"
|
||||
@@ -2819,7 +2795,7 @@ checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94"
|
||||
dependencies = [
|
||||
"rand_chacha 0.9.0",
|
||||
"rand_core 0.9.3",
|
||||
"zerocopy 0.8.23",
|
||||
"zerocopy 0.8.24",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2857,7 +2833,7 @@ version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38"
|
||||
dependencies = [
|
||||
"getrandom 0.3.1",
|
||||
"getrandom 0.3.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2973,9 +2949,9 @@ checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
|
||||
|
||||
[[package]]
|
||||
name = "ring"
|
||||
version = "0.17.13"
|
||||
version = "0.17.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "70ac5d832aa16abd7d1def883a8545280c20a60f523a370aa3a9617c2b8550ee"
|
||||
checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"cfg-if",
|
||||
@@ -3010,7 +2986,7 @@ dependencies = [
|
||||
"rinja_parser",
|
||||
"rustc-hash 2.1.1",
|
||||
"serde",
|
||||
"syn 2.0.99",
|
||||
"syn 2.0.100",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3026,9 +3002,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rsa"
|
||||
version = "0.9.7"
|
||||
version = "0.9.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "47c75d7c5c6b673e58bf54d8544a9f432e3a925b0e80f7cd3602ab5c50c55519"
|
||||
checksum = "78928ac1ed176a5ca1d17e578a1825f3d81ca54cf41053a592584b020cfd691b"
|
||||
dependencies = [
|
||||
"const-oid",
|
||||
"digest",
|
||||
@@ -3046,9 +3022,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rubato"
|
||||
version = "0.16.1"
|
||||
version = "0.16.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cdd96992d7e24b3d7f35fdfe02af037a356ac90d41b466945cf3333525a86eea"
|
||||
checksum = "5258099699851cfd0082aeb645feb9c084d9a5e1f1b8d5372086b989fc5e56a1"
|
||||
dependencies = [
|
||||
"num-complex",
|
||||
"num-integer",
|
||||
@@ -3100,9 +3076,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "1.0.1"
|
||||
version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dade4812df5c384711475be5fcd8c162555352945401aed22a35bffeab61f657"
|
||||
checksum = "d97817398dd4bb2e6da002002db259209759911da105da92bec29ccb12cf58bf"
|
||||
dependencies = [
|
||||
"bitflags 2.9.0",
|
||||
"errno",
|
||||
@@ -3113,9 +3089,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rustls"
|
||||
version = "0.23.23"
|
||||
version = "0.23.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "47796c98c480fce5406ef69d1c76378375492c3b0a0de587be0c1d9feb12f395"
|
||||
checksum = "822ee9188ac4ec04a2f0531e55d035fb2de73f18b41a63c70c2712503b6fb13c"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"ring",
|
||||
@@ -3142,9 +3118,9 @@ checksum = "917ce264624a4b4db1c364dcc35bfca9ded014d0a958cd47ad3e960e988ea51c"
|
||||
|
||||
[[package]]
|
||||
name = "rustls-webpki"
|
||||
version = "0.102.8"
|
||||
version = "0.103.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9"
|
||||
checksum = "fef8b8769aaccf73098557a87cd1816b4f9c7c16811c9c77142aa695c16f2c03"
|
||||
dependencies = [
|
||||
"ring",
|
||||
"rustls-pki-types",
|
||||
@@ -3217,7 +3193,7 @@ checksum = "7f81c2fde025af7e69b1d1420531c8a8811ca898919db177141a85313b1cb932"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.99",
|
||||
"syn 2.0.100",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3246,7 +3222,7 @@ checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.99",
|
||||
"syn 2.0.100",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3388,9 +3364,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "socket2"
|
||||
version = "0.5.8"
|
||||
version = "0.5.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8"
|
||||
checksum = "4f5fd57c80058a56cf5c777ab8a126398ece8e442983605d280a44ce79d0edef"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.52.0",
|
||||
@@ -3475,7 +3451,7 @@ dependencies = [
|
||||
"quote",
|
||||
"sqlx-core",
|
||||
"sqlx-macros-core",
|
||||
"syn 2.0.99",
|
||||
"syn 2.0.100",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3498,7 +3474,7 @@ dependencies = [
|
||||
"sqlx-mysql",
|
||||
"sqlx-postgres",
|
||||
"sqlx-sqlite",
|
||||
"syn 2.0.99",
|
||||
"syn 2.0.100",
|
||||
"tempfile",
|
||||
"tokio",
|
||||
"url",
|
||||
@@ -3635,9 +3611,9 @@ checksum = "fe895eb47f22e2ddd4dabc02bce419d2e643c8e3b585c78158b349195bc24d82"
|
||||
|
||||
[[package]]
|
||||
name = "string_cache"
|
||||
version = "0.8.8"
|
||||
version = "0.8.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "938d512196766101d333398efde81bc1f37b00cb42c2f8350e5df639f040bbbe"
|
||||
checksum = "bf776ba3fa74f83bf4b63c3dcbbf82173db2632ed8452cb2d891d33f459de70f"
|
||||
dependencies = [
|
||||
"new_debug_unreachable",
|
||||
"parking_lot",
|
||||
@@ -3694,7 +3670,7 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"rustversion",
|
||||
"syn 2.0.99",
|
||||
"syn 2.0.100",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3912,9 +3888,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.99"
|
||||
version = "2.0.100"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e02e925281e18ffd9d640e234264753c43edc62d64b2d4cf898f1bc5e75f3fc2"
|
||||
checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -3929,7 +3905,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.99",
|
||||
"syn 2.0.100",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3940,13 +3916,12 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
|
||||
|
||||
[[package]]
|
||||
name = "tempfile"
|
||||
version = "3.18.0"
|
||||
version = "3.19.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2c317e0a526ee6120d8dabad239c8dadca62b24b6f168914bbbc8e2fb1f0e567"
|
||||
checksum = "7437ac7763b9b123ccf33c338a5cc1bac6f69b45a136c19bdd8a65e3916435bf"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"fastrand",
|
||||
"getrandom 0.3.1",
|
||||
"getrandom 0.3.2",
|
||||
"once_cell",
|
||||
"rustix",
|
||||
"windows-sys 0.59.0",
|
||||
@@ -4017,7 +3992,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.99",
|
||||
"syn 2.0.100",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4028,7 +4003,7 @@ checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.99",
|
||||
"syn 2.0.100",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4084,9 +4059,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.44.1"
|
||||
version = "1.44.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f382da615b842244d4b8738c82ed1275e6c5dd90c459a30941cd07080b06c91a"
|
||||
checksum = "e6b88822cbe49de4185e3a4cbf8321dd487cf5fe0c5c65695fef6346371e9c48"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
"bytes",
|
||||
@@ -4108,7 +4083,7 @@ checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.99",
|
||||
"syn 2.0.100",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4168,7 +4143,7 @@ checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.99",
|
||||
"syn 2.0.100",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4322,9 +4297,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tree-sitter-rust"
|
||||
version = "0.23.2"
|
||||
version = "0.24.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4d64d449ca63e683c562c7743946a646671ca23947b9c925c0cfbe65051a4af"
|
||||
checksum = "4b9b18034c684a2420722be8b2a91c9c44f2546b631c039edf575ccba8c61be1"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"tree-sitter-language",
|
||||
@@ -4474,7 +4449,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f9902d4ed16c65e6c0222241024dd0bfeed07ea3deb7c470eb175e5f5ef406cd"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"syn 2.0.99",
|
||||
"syn 2.0.100",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4489,7 +4464,7 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"serde",
|
||||
"syn 2.0.99",
|
||||
"syn 2.0.100",
|
||||
"toml",
|
||||
"uniffi_meta",
|
||||
]
|
||||
@@ -4564,7 +4539,7 @@ version = "1.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "458f7a779bf54acc9f347480ac654f68407d3aab21269a6e3c9f922acd9e2da9"
|
||||
dependencies = [
|
||||
"getrandom 0.3.1",
|
||||
"getrandom 0.3.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4615,9 +4590,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.13.3+wasi-0.2.2"
|
||||
version = "0.14.2+wasi-0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2"
|
||||
checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3"
|
||||
dependencies = [
|
||||
"wit-bindgen-rt",
|
||||
]
|
||||
@@ -4650,7 +4625,7 @@ dependencies = [
|
||||
"log",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.99",
|
||||
"syn 2.0.100",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
@@ -4672,7 +4647,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.99",
|
||||
"syn 2.0.100",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
@@ -4712,9 +4687,9 @@ checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082"
|
||||
|
||||
[[package]]
|
||||
name = "whoami"
|
||||
version = "1.5.2"
|
||||
version = "1.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "372d5b87f58ec45c384ba03563b03544dc5fadc3983e434b286913f5b4a9bb6d"
|
||||
checksum = "6994d13118ab492c3c80c1f81928718159254c53c472bf9ce36f8dae4add02a7"
|
||||
dependencies = [
|
||||
"redox_syscall",
|
||||
"wasite",
|
||||
@@ -4722,9 +4697,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "widestring"
|
||||
version = "1.1.0"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7219d36b6eac893fa81e84ebe06485e7dcbb616177469b142df14f1f4deb1311"
|
||||
checksum = "dd7cf3379ca1aac9eea11fba24fd7e315d621f8dfe35c8d7d2be8b793726e07d"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
@@ -4777,15 +4752,6 @@ dependencies = [
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-core"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
|
||||
dependencies = [
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-core"
|
||||
version = "0.57.0"
|
||||
@@ -4807,10 +4773,23 @@ dependencies = [
|
||||
"windows-implement 0.58.0",
|
||||
"windows-interface 0.58.0",
|
||||
"windows-result 0.2.0",
|
||||
"windows-strings",
|
||||
"windows-strings 0.1.0",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-core"
|
||||
version = "0.61.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4763c1de310c86d75a878046489e2e5ba02c649d185f21c67d4cf8a56d098980"
|
||||
dependencies = [
|
||||
"windows-implement 0.60.0",
|
||||
"windows-interface 0.59.1",
|
||||
"windows-link",
|
||||
"windows-result 0.3.2",
|
||||
"windows-strings 0.4.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-implement"
|
||||
version = "0.57.0"
|
||||
@@ -4819,7 +4798,7 @@ checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.99",
|
||||
"syn 2.0.100",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4830,7 +4809,18 @@ checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.99",
|
||||
"syn 2.0.100",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-implement"
|
||||
version = "0.60.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.100",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4841,7 +4831,7 @@ checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.99",
|
||||
"syn 2.0.100",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4852,14 +4842,25 @@ checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.99",
|
||||
"syn 2.0.100",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-interface"
|
||||
version = "0.59.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.100",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-link"
|
||||
version = "0.1.0"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6dccfd733ce2b1753b03b6d3c65edf020262ea35e20ccdf3e288043e6dd620e3"
|
||||
checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38"
|
||||
|
||||
[[package]]
|
||||
name = "windows-result"
|
||||
@@ -4879,6 +4880,15 @@ dependencies = [
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-result"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c64fd11a4fd95df68efcfee5f44a294fe71b8bc6a91993e2791938abcc712252"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-strings"
|
||||
version = "0.1.0"
|
||||
@@ -4889,6 +4899,15 @@ dependencies = [
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-strings"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a2ba9642430ee452d5a7aa78d72907ebe8cfda358e8cb7918a2050581322f97"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.48.0"
|
||||
@@ -5039,18 +5058,18 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||
|
||||
[[package]]
|
||||
name = "winnow"
|
||||
version = "0.7.3"
|
||||
version = "0.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0e7f4ea97f6f78012141bcdb6a216b2609f0979ada50b20ca5b52dde2eac2bb1"
|
||||
checksum = "0e97b544156e9bebe1a0ffbc03484fc1ffe3100cbce3ffb17eac35f7cdd7ab36"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wit-bindgen-rt"
|
||||
version = "0.33.0"
|
||||
version = "0.39.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c"
|
||||
checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1"
|
||||
dependencies = [
|
||||
"bitflags 2.9.0",
|
||||
]
|
||||
@@ -5138,7 +5157,7 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.99",
|
||||
"syn 2.0.100",
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
@@ -5148,17 +5167,16 @@ version = "0.7.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"zerocopy-derive 0.7.35",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
version = "0.8.23"
|
||||
version = "0.8.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fd97444d05a4328b90e75e503a34bad781f14e28a823ad3557f0750df1ebcbc6"
|
||||
checksum = "2586fea28e186957ef732a5f8b3be2da217d65c5969d4b1e17f973ebbe876879"
|
||||
dependencies = [
|
||||
"zerocopy-derive 0.8.23",
|
||||
"zerocopy-derive 0.8.24",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5169,18 +5187,18 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.99",
|
||||
"syn 2.0.100",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy-derive"
|
||||
version = "0.8.23"
|
||||
version = "0.8.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6352c01d0edd5db859a63e2605f4ea3183ddbd15e2c4a9e7d32184df75e4f154"
|
||||
checksum = "a996a8f63c5c4448cd959ac1bab0aaa3306ccfd060472f85943ee0750f0169be"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.99",
|
||||
"syn 2.0.100",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5200,7 +5218,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.99",
|
||||
"syn 2.0.100",
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
@@ -5229,7 +5247,7 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.99",
|
||||
"syn 2.0.100",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
@@ -31,7 +31,6 @@ homedir = "0.3"
|
||||
infer = { version = "0.19.0" }
|
||||
libc = "0.2"
|
||||
mimalloc = "0.1"
|
||||
mp3lame-encoder = "0.2"
|
||||
napi = { version = "3.0.0-alpha.31", features = ["async", "chrono_date", "error_anyhow", "napi9", "serde"] }
|
||||
napi-build = { version = "2" }
|
||||
napi-derive = { version = "3.0.0-alpha.28" }
|
||||
@@ -66,7 +65,7 @@ tree-sitter-java = { version = "0.23" }
|
||||
tree-sitter-javascript = { version = "0.23" }
|
||||
tree-sitter-kotlin-ng = { version = "1.1" }
|
||||
tree-sitter-python = { version = "0.23" }
|
||||
tree-sitter-rust = { version = "0.23" }
|
||||
tree-sitter-rust = { version = "0.24" }
|
||||
tree-sitter-scala = { version = "0.23" }
|
||||
tree-sitter-typescript = { version = "0.23" }
|
||||
uniffi = "0.29"
|
||||
@@ -83,3 +82,7 @@ codegen-units = 1
|
||||
lto = true
|
||||
opt-level = 3
|
||||
strip = "symbols"
|
||||
|
||||
# android uniffi bindgen requires symbols
|
||||
[profile.release.package.affine_mobile_native]
|
||||
strip = "none"
|
||||
18
README.md
18
README.md
@@ -21,6 +21,23 @@
|
||||
<br/>
|
||||
<br/>
|
||||
|
||||
<div align="left" valign="middle">
|
||||
<a href="https://runblaze.dev">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://www.runblaze.dev/logo_dark.png">
|
||||
<img align="right" src="https://www.runblaze.dev/logo_light.png" height="102px"/>
|
||||
</picture>
|
||||
</a>
|
||||
|
||||
<br style="display: none;"/>
|
||||
|
||||
_Special thanks to [Blaze](https://runblaze.dev) for their support of this project. They provide high-performance Apple Silicon macOS and Linux (AMD64 & ARM64) runners for GitHub Actions, greatly reducing our automated build times._
|
||||
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
<br/>
|
||||
|
||||
<div align="center">
|
||||
<a href="https://affine.pro">Home Page</a> |
|
||||
<a href="https://affine.pro/redirect/discord">Discord</a> |
|
||||
@@ -160,7 +177,6 @@ We would also like to give thanks to open-source projects that make AFFiNE possi
|
||||
- [Jotai](https://github.com/pmndrs/jotai) - Primitive and flexible state management for React.
|
||||
- [async-call-rpc](https://github.com/Jack-Works/async-call-rpc) - A lightweight JSON RPC client & server.
|
||||
- [Vite](https://github.com/vitejs/vite) - Next generation frontend tooling.
|
||||
- [lame](https://lame.sourceforge.io/) - High quality MPEG Audio Layer III (MP3) encoder.
|
||||
- Other upstream [dependencies](https://github.com/toeverything/AFFiNE/network/dependencies).
|
||||
|
||||
Thanks a lot to the community for providing such powerful and simple libraries, so that we can focus more on the implementation of the product logic, and we hope that in the future our projects will also provide a more easy-to-use knowledge base for everyone.
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
"@blocksuite/affine-gfx-mindmap": "workspace:*",
|
||||
"@blocksuite/affine-gfx-note": "workspace:*",
|
||||
"@blocksuite/affine-gfx-shape": "workspace:*",
|
||||
"@blocksuite/affine-gfx-template": "workspace:*",
|
||||
"@blocksuite/affine-gfx-text": "workspace:*",
|
||||
"@blocksuite/affine-gfx-turbo-renderer": "workspace:*",
|
||||
"@blocksuite/affine-inline-footnote": "workspace:*",
|
||||
@@ -128,6 +129,7 @@
|
||||
"./gfx/mindmap": "./src/gfx/mindmap.ts",
|
||||
"./gfx/connector": "./src/gfx/connector.ts",
|
||||
"./gfx/group": "./src/gfx/group.ts",
|
||||
"./gfx/template": "./src/gfx/template.ts",
|
||||
"./gfx/turbo-renderer": "./src/gfx/turbo-renderer.ts",
|
||||
"./components/block-selection": "./src/components/block-selection.ts",
|
||||
"./components/block-zero-width": "./src/components/block-zero-width.ts",
|
||||
@@ -178,9 +180,9 @@
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.20.0",
|
||||
"version": "0.21.0",
|
||||
"devDependencies": {
|
||||
"@vanilla-extract/vite-plugin": "^5.0.0",
|
||||
"vitest": "3.0.9"
|
||||
"vitest": "3.1.1"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3680,88 +3680,95 @@ bbb
|
||||
expect(nanoidReplacement(rawBlockSnapshot)).toEqual(blockSnapshot);
|
||||
});
|
||||
|
||||
test('inline latex', async () => {
|
||||
const markdown = 'inline $E=mc^2$ latex\n';
|
||||
const blockSnapshot: BlockSnapshot = {
|
||||
type: 'block',
|
||||
id: 'matchesReplaceMap[0]',
|
||||
flavour: 'affine:note',
|
||||
props: {
|
||||
xywh: '[0,0,800,95]',
|
||||
background: DefaultTheme.noteBackgrounColor,
|
||||
index: 'a0',
|
||||
hidden: false,
|
||||
displayMode: NoteDisplayMode.DocAndEdgeless,
|
||||
},
|
||||
children: [
|
||||
{
|
||||
type: 'block',
|
||||
id: 'matchesReplaceMap[1]',
|
||||
flavour: 'affine:paragraph',
|
||||
props: {
|
||||
type: 'text',
|
||||
text: {
|
||||
'$blocksuite:internal:text$': true,
|
||||
delta: [
|
||||
{
|
||||
insert: 'inline ',
|
||||
},
|
||||
{
|
||||
insert: ' ',
|
||||
attributes: {
|
||||
latex: 'E=mc^2',
|
||||
},
|
||||
},
|
||||
{
|
||||
insert: ' latex',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
children: [],
|
||||
describe('inline latex', () => {
|
||||
test.each([
|
||||
['dollar sign syntax', 'inline $E=mc^2$ latex\n'],
|
||||
['backslash syntax', 'inline \\(E=mc^2\\) latex\n'],
|
||||
])('should convert %s correctly', async (_, markdown) => {
|
||||
const blockSnapshot: BlockSnapshot = {
|
||||
type: 'block',
|
||||
id: 'matchesReplaceMap[0]',
|
||||
flavour: 'affine:note',
|
||||
props: {
|
||||
xywh: '[0,0,800,95]',
|
||||
background: DefaultTheme.noteBackgrounColor,
|
||||
index: 'a0',
|
||||
hidden: false,
|
||||
displayMode: NoteDisplayMode.DocAndEdgeless,
|
||||
},
|
||||
],
|
||||
};
|
||||
children: [
|
||||
{
|
||||
type: 'block',
|
||||
id: 'matchesReplaceMap[1]',
|
||||
flavour: 'affine:paragraph',
|
||||
props: {
|
||||
type: 'text',
|
||||
text: {
|
||||
'$blocksuite:internal:text$': true,
|
||||
delta: [
|
||||
{
|
||||
insert: 'inline ',
|
||||
},
|
||||
{
|
||||
insert: ' ',
|
||||
attributes: {
|
||||
latex: 'E=mc^2',
|
||||
},
|
||||
},
|
||||
{
|
||||
insert: ' latex',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
children: [],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const mdAdapter = new MarkdownAdapter(createJob(), provider);
|
||||
const rawBlockSnapshot = await mdAdapter.toBlockSnapshot({
|
||||
file: markdown,
|
||||
const mdAdapter = new MarkdownAdapter(createJob(), provider);
|
||||
const rawBlockSnapshot = await mdAdapter.toBlockSnapshot({
|
||||
file: markdown,
|
||||
});
|
||||
expect(nanoidReplacement(rawBlockSnapshot)).toEqual(blockSnapshot);
|
||||
});
|
||||
expect(nanoidReplacement(rawBlockSnapshot)).toEqual(blockSnapshot);
|
||||
});
|
||||
|
||||
test('latex block', async () => {
|
||||
const markdown = '$$\nE=mc^2\n$$\n';
|
||||
|
||||
const blockSnapshot: BlockSnapshot = {
|
||||
type: 'block',
|
||||
id: 'matchesReplaceMap[0]',
|
||||
flavour: 'affine:note',
|
||||
props: {
|
||||
xywh: '[0,0,800,95]',
|
||||
background: DefaultTheme.noteBackgrounColor,
|
||||
index: 'a0',
|
||||
hidden: false,
|
||||
displayMode: NoteDisplayMode.DocAndEdgeless,
|
||||
},
|
||||
children: [
|
||||
{
|
||||
type: 'block',
|
||||
id: 'matchesReplaceMap[1]',
|
||||
flavour: 'affine:latex',
|
||||
props: {
|
||||
latex: 'E=mc^2',
|
||||
},
|
||||
children: [],
|
||||
describe('latex block', () => {
|
||||
test.each([
|
||||
['dollar sign syntax', '$$\nE=mc^2\n$$\n'],
|
||||
['backslash syntax', '\\[\nE=mc^2\n\\]\n'],
|
||||
])('should convert %s correctly', async (_, markdown) => {
|
||||
const blockSnapshot: BlockSnapshot = {
|
||||
type: 'block',
|
||||
id: 'matchesReplaceMap[0]',
|
||||
flavour: 'affine:note',
|
||||
props: {
|
||||
xywh: '[0,0,800,95]',
|
||||
background: DefaultTheme.noteBackgrounColor,
|
||||
index: 'a0',
|
||||
hidden: false,
|
||||
displayMode: NoteDisplayMode.DocAndEdgeless,
|
||||
},
|
||||
],
|
||||
};
|
||||
children: [
|
||||
{
|
||||
type: 'block',
|
||||
id: 'matchesReplaceMap[1]',
|
||||
flavour: 'affine:latex',
|
||||
props: {
|
||||
latex: 'E=mc^2',
|
||||
},
|
||||
children: [],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const mdAdapter = new MarkdownAdapter(createJob(), provider);
|
||||
const rawBlockSnapshot = await mdAdapter.toBlockSnapshot({
|
||||
file: markdown,
|
||||
const mdAdapter = new MarkdownAdapter(createJob(), provider);
|
||||
const rawBlockSnapshot = await mdAdapter.toBlockSnapshot({
|
||||
file: markdown,
|
||||
});
|
||||
expect(nanoidReplacement(rawBlockSnapshot)).toEqual(blockSnapshot);
|
||||
});
|
||||
expect(nanoidReplacement(rawBlockSnapshot)).toEqual(blockSnapshot);
|
||||
});
|
||||
|
||||
test('reference', async () => {
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
import { SpecProvider } from '@blocksuite/affine-shared/utils';
|
||||
import { Container } from '@blocksuite/global/di';
|
||||
|
||||
import { registerSpecs } from '../../extensions/register';
|
||||
import {
|
||||
registerBlockSpecs,
|
||||
registerStoreSpecs,
|
||||
} from '../../extensions/register';
|
||||
|
||||
registerSpecs();
|
||||
registerStoreSpecs();
|
||||
registerBlockSpecs();
|
||||
|
||||
export function getProvider() {
|
||||
const container = new Container();
|
||||
|
||||
@@ -20,6 +20,7 @@ import type { ExtensionType } from '@blocksuite/store';
|
||||
|
||||
import { defaultBlockHtmlAdapterMatchers } from './html/block-matcher';
|
||||
import { defaultBlockMarkdownAdapterMatchers } from './markdown/block-matcher';
|
||||
import { defaultMarkdownPreprocessors } from './markdown/preprocessor';
|
||||
import { defaultBlockNotionHtmlAdapterMatchers } from './notion-html/block-matcher';
|
||||
import { defaultBlockPlainTextAdapterMatchers } from './plain-text/block-matcher';
|
||||
|
||||
@@ -44,6 +45,7 @@ export const MarkdownAdapterExtension: ExtensionType[] = [
|
||||
...MarkdownInlineToDeltaAdapterExtensions,
|
||||
...defaultBlockMarkdownAdapterMatchers,
|
||||
...InlineDeltaToMarkdownAdapterExtensions,
|
||||
...defaultMarkdownPreprocessors,
|
||||
];
|
||||
|
||||
export const NotionHtmlAdapterExtension: ExtensionType[] = [
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
export * from './extension.js';
|
||||
export * from './html/block-matcher.js';
|
||||
export * from './markdown/block-matcher.js';
|
||||
export * from './markdown/preprocessor.js';
|
||||
export * from './notion-html/block-matcher.js';
|
||||
export * from './plain-text/block-matcher.js';
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
import { CodeMarkdownPreprocessorExtension } from '@blocksuite/affine-block-code';
|
||||
import { LatexMarkdownPreprocessorExtension } from '@blocksuite/affine-block-latex';
|
||||
|
||||
export const defaultMarkdownPreprocessors = [
|
||||
LatexMarkdownPreprocessorExtension,
|
||||
CodeMarkdownPreprocessorExtension,
|
||||
];
|
||||
@@ -0,0 +1 @@
|
||||
export * from '@blocksuite/affine-components/open-doc-dropdown-menu';
|
||||
@@ -34,6 +34,7 @@ import { effects as componentHighlightDropdownMenuEffects } from '@blocksuite/af
|
||||
import { IconButton } from '@blocksuite/affine-components/icon-button';
|
||||
import { effects as componentLinkPreviewEffects } from '@blocksuite/affine-components/link-preview';
|
||||
import { effects as componentLinkedDocTitleEffects } from '@blocksuite/affine-components/linked-doc-title';
|
||||
import { effects as componentOpenDocDropdownMenuEffects } from '@blocksuite/affine-components/open-doc-dropdown-menu';
|
||||
import { effects as componentPortalEffects } from '@blocksuite/affine-components/portal';
|
||||
import { effects as componentSizeDropdownMenuEffects } from '@blocksuite/affine-components/size-dropdown-menu';
|
||||
import { SmoothCorner } from '@blocksuite/affine-components/smooth-corner';
|
||||
@@ -62,7 +63,7 @@ import { effects as widgetToolbarEffects } from '@blocksuite/affine-widget-toolb
|
||||
import { effects as dataViewEffects } from '@blocksuite/data-view/effects';
|
||||
import { effects as stdEffects } from '@blocksuite/std/effects';
|
||||
|
||||
import { registerSpecs } from './extensions/register.js';
|
||||
import { registerBlockSpecs } from './extensions';
|
||||
|
||||
export declare const _GLOBAL_:
|
||||
| typeof stdEffects
|
||||
@@ -112,8 +113,7 @@ export declare const _GLOBAL_:
|
||||
| typeof fragmentOutlineEffects;
|
||||
|
||||
export function effects() {
|
||||
registerSpecs();
|
||||
|
||||
registerBlockSpecs();
|
||||
stdEffects();
|
||||
|
||||
dataViewEffects();
|
||||
@@ -165,6 +165,7 @@ export function effects() {
|
||||
componentEdgelessLineWidthEffects();
|
||||
componentEdgelessLineStylesEffects();
|
||||
componentEdgelessShapeColorPickerEffects();
|
||||
componentOpenDocDropdownMenuEffects();
|
||||
|
||||
widgetScrollAnchoringEffects();
|
||||
widgetFrameTitleEffects();
|
||||
|
||||
@@ -17,14 +17,40 @@ import {
|
||||
} from '@blocksuite/affine-block-note';
|
||||
import { ParagraphBlockSpec } from '@blocksuite/affine-block-paragraph';
|
||||
import {
|
||||
EdgelessSurfaceBlockAdapterExtensions,
|
||||
EdgelessSurfaceBlockSpec,
|
||||
PageSurfaceBlockSpec,
|
||||
SurfaceBlockAdapterExtensions,
|
||||
} from '@blocksuite/affine-block-surface';
|
||||
import {
|
||||
EdgelessSurfaceRefBlockSpec,
|
||||
PageSurfaceRefBlockSpec,
|
||||
} from '@blocksuite/affine-block-surface-ref';
|
||||
import { TableBlockSpec } from '@blocksuite/affine-block-table';
|
||||
import {
|
||||
brushToMarkdownAdapterMatcher,
|
||||
brushToPlainTextAdapterMatcher,
|
||||
} from '@blocksuite/affine-gfx-brush';
|
||||
import {
|
||||
connectorToMarkdownAdapterMatcher,
|
||||
connectorToPlainTextAdapterMatcher,
|
||||
} from '@blocksuite/affine-gfx-connector';
|
||||
import {
|
||||
groupToMarkdownAdapterMatcher,
|
||||
groupToPlainTextAdapterMatcher,
|
||||
} from '@blocksuite/affine-gfx-group';
|
||||
import {
|
||||
mindmapToMarkdownAdapterMatcher,
|
||||
mindmapToPlainTextAdapterMatcher,
|
||||
} from '@blocksuite/affine-gfx-mindmap';
|
||||
import {
|
||||
shapeToMarkdownAdapterMatcher,
|
||||
shapeToPlainTextAdapterMatcher,
|
||||
} from '@blocksuite/affine-gfx-shape';
|
||||
import {
|
||||
textToMarkdownAdapterMatcher,
|
||||
textToPlainTextAdapterMatcher,
|
||||
} from '@blocksuite/affine-gfx-text';
|
||||
import { inlinePresetExtensions } from '@blocksuite/affine-inline-preset';
|
||||
import {
|
||||
DefaultOpenDocExtension,
|
||||
@@ -34,6 +60,24 @@ import {
|
||||
} from '@blocksuite/affine-shared/services';
|
||||
import type { ExtensionType } from '@blocksuite/store';
|
||||
|
||||
const elementToPlainTextAdapterMatchers = [
|
||||
groupToPlainTextAdapterMatcher,
|
||||
shapeToPlainTextAdapterMatcher,
|
||||
connectorToPlainTextAdapterMatcher,
|
||||
brushToPlainTextAdapterMatcher,
|
||||
textToPlainTextAdapterMatcher,
|
||||
mindmapToPlainTextAdapterMatcher,
|
||||
];
|
||||
|
||||
const elementToMarkdownAdapterMatchers = [
|
||||
groupToMarkdownAdapterMatcher,
|
||||
shapeToMarkdownAdapterMatcher,
|
||||
connectorToMarkdownAdapterMatcher,
|
||||
brushToMarkdownAdapterMatcher,
|
||||
textToMarkdownAdapterMatcher,
|
||||
mindmapToMarkdownAdapterMatcher,
|
||||
];
|
||||
|
||||
export const CommonBlockSpecs: ExtensionType[] = [
|
||||
inlinePresetExtensions,
|
||||
DocDisplayMetaService,
|
||||
@@ -54,6 +98,9 @@ export const CommonBlockSpecs: ExtensionType[] = [
|
||||
FontLoaderService,
|
||||
CalloutBlockSpec,
|
||||
FrameBlockSpec,
|
||||
|
||||
elementToPlainTextAdapterMatchers,
|
||||
elementToMarkdownAdapterMatchers,
|
||||
].flat();
|
||||
|
||||
export const PageFirstPartyBlockSpecs: ExtensionType[] = [
|
||||
@@ -61,6 +108,8 @@ export const PageFirstPartyBlockSpecs: ExtensionType[] = [
|
||||
NoteBlockSpec,
|
||||
PageSurfaceBlockSpec,
|
||||
PageSurfaceRefBlockSpec,
|
||||
|
||||
...SurfaceBlockAdapterExtensions,
|
||||
].flat();
|
||||
|
||||
export const EdgelessFirstPartyBlockSpecs: ExtensionType[] = [
|
||||
@@ -70,4 +119,6 @@ export const EdgelessFirstPartyBlockSpecs: ExtensionType[] = [
|
||||
EdgelessSurfaceBlockSpec,
|
||||
EdgelessSurfaceRefBlockSpec,
|
||||
EdgelessTextBlockSpec,
|
||||
|
||||
...EdgelessSurfaceBlockAdapterExtensions,
|
||||
].flat();
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
export * from './common.js';
|
||||
export * from './editor-specs.js';
|
||||
export * from './preview-specs.js';
|
||||
export * from './store.js';
|
||||
export * from './common';
|
||||
export * from './editor-specs';
|
||||
export * from './preview-specs';
|
||||
export * from './register';
|
||||
export * from './store';
|
||||
|
||||
@@ -10,8 +10,11 @@ import {
|
||||
} from './preview-specs.js';
|
||||
import { StoreExtensions } from './store.js';
|
||||
|
||||
export function registerSpecs() {
|
||||
export function registerStoreSpecs() {
|
||||
SpecProvider._.addSpec('store', StoreExtensions);
|
||||
}
|
||||
|
||||
export function registerBlockSpecs() {
|
||||
SpecProvider._.addSpec('page', PageEditorBlockSpecs);
|
||||
SpecProvider._.addSpec('edgeless', EdgelessEditorBlockSpecs);
|
||||
SpecProvider._.addSpec('preview:page', PreviewPageEditorBlockSpecs);
|
||||
|
||||
1
blocksuite/affine/all/src/gfx/template.ts
Normal file
1
blocksuite/affine/all/src/gfx/template.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from '@blocksuite/affine-gfx-template';
|
||||
@@ -7,35 +7,36 @@
|
||||
},
|
||||
"include": ["./src"],
|
||||
"references": [
|
||||
{ "path": "../blocks/block-attachment" },
|
||||
{ "path": "../blocks/block-bookmark" },
|
||||
{ "path": "../blocks/block-callout" },
|
||||
{ "path": "../blocks/block-code" },
|
||||
{ "path": "../blocks/block-data-view" },
|
||||
{ "path": "../blocks/block-database" },
|
||||
{ "path": "../blocks/block-divider" },
|
||||
{ "path": "../blocks/block-edgeless-text" },
|
||||
{ "path": "../blocks/block-embed" },
|
||||
{ "path": "../blocks/block-frame" },
|
||||
{ "path": "../blocks/block-image" },
|
||||
{ "path": "../blocks/block-latex" },
|
||||
{ "path": "../blocks/block-list" },
|
||||
{ "path": "../blocks/block-note" },
|
||||
{ "path": "../blocks/block-paragraph" },
|
||||
{ "path": "../blocks/block-root" },
|
||||
{ "path": "../blocks/block-surface" },
|
||||
{ "path": "../blocks/block-surface-ref" },
|
||||
{ "path": "../blocks/block-table" },
|
||||
{ "path": "../blocks/attachment" },
|
||||
{ "path": "../blocks/bookmark" },
|
||||
{ "path": "../blocks/callout" },
|
||||
{ "path": "../blocks/code" },
|
||||
{ "path": "../blocks/data-view" },
|
||||
{ "path": "../blocks/database" },
|
||||
{ "path": "../blocks/divider" },
|
||||
{ "path": "../blocks/edgeless-text" },
|
||||
{ "path": "../blocks/embed" },
|
||||
{ "path": "../blocks/frame" },
|
||||
{ "path": "../blocks/image" },
|
||||
{ "path": "../blocks/latex" },
|
||||
{ "path": "../blocks/list" },
|
||||
{ "path": "../blocks/note" },
|
||||
{ "path": "../blocks/paragraph" },
|
||||
{ "path": "../blocks/root" },
|
||||
{ "path": "../blocks/surface" },
|
||||
{ "path": "../blocks/surface-ref" },
|
||||
{ "path": "../blocks/table" },
|
||||
{ "path": "../components" },
|
||||
{ "path": "../fragments/fragment-doc-title" },
|
||||
{ "path": "../fragments/fragment-frame-panel" },
|
||||
{ "path": "../fragments/fragment-outline" },
|
||||
{ "path": "../fragments/doc-title" },
|
||||
{ "path": "../fragments/frame-panel" },
|
||||
{ "path": "../fragments/outline" },
|
||||
{ "path": "../gfx/brush" },
|
||||
{ "path": "../gfx/connector" },
|
||||
{ "path": "../gfx/group" },
|
||||
{ "path": "../gfx/mindmap" },
|
||||
{ "path": "../gfx/note" },
|
||||
{ "path": "../gfx/shape" },
|
||||
{ "path": "../gfx/template" },
|
||||
{ "path": "../gfx/text" },
|
||||
{ "path": "../gfx/turbo-renderer" },
|
||||
{ "path": "../inlines/footnote" },
|
||||
@@ -47,14 +48,14 @@
|
||||
{ "path": "../model" },
|
||||
{ "path": "../rich-text" },
|
||||
{ "path": "../shared" },
|
||||
{ "path": "../widgets/widget-drag-handle" },
|
||||
{ "path": "../widgets/widget-edgeless-auto-connect" },
|
||||
{ "path": "../widgets/widget-edgeless-toolbar" },
|
||||
{ "path": "../widgets/widget-frame-title" },
|
||||
{ "path": "../widgets/widget-remote-selection" },
|
||||
{ "path": "../widgets/widget-scroll-anchoring" },
|
||||
{ "path": "../widgets/widget-slash-menu" },
|
||||
{ "path": "../widgets/widget-toolbar" },
|
||||
{ "path": "../widgets/drag-handle" },
|
||||
{ "path": "../widgets/edgeless-auto-connect" },
|
||||
{ "path": "../widgets/edgeless-toolbar" },
|
||||
{ "path": "../widgets/frame-title" },
|
||||
{ "path": "../widgets/remote-selection" },
|
||||
{ "path": "../widgets/scroll-anchoring" },
|
||||
{ "path": "../widgets/slash-menu" },
|
||||
{ "path": "../widgets/toolbar" },
|
||||
{ "path": "../data-view" },
|
||||
{ "path": "../../framework/global" },
|
||||
{ "path": "../../framework/std" },
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
"@blocksuite/affine-shared": "workspace:*",
|
||||
"@blocksuite/affine-widget-slash-menu": "workspace:*",
|
||||
"@blocksuite/global": "workspace:*",
|
||||
"@blocksuite/icons": "^2.2.8",
|
||||
"@blocksuite/icons": "^2.2.10",
|
||||
"@blocksuite/std": "workspace:*",
|
||||
"@blocksuite/store": "workspace:*",
|
||||
"@floating-ui/dom": "^1.6.13",
|
||||
@@ -40,5 +40,5 @@
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.20.0"
|
||||
"version": "0.21.0"
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
import { FONT_XS, PANEL_BASE } from '@blocksuite/affine-shared/styles';
|
||||
import { fontXSStyle, panelBaseStyle } from '@blocksuite/affine-shared/styles';
|
||||
import { css } from 'lit';
|
||||
|
||||
export const renameStyles = css`
|
||||
${panelBaseStyle('.affine-attachment-rename-container')}
|
||||
.affine-attachment-rename-container {
|
||||
${PANEL_BASE};
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -35,8 +35,8 @@ export const renameStyles = css`
|
||||
outline: none;
|
||||
background: transparent;
|
||||
color: var(--affine-text-primary-color);
|
||||
${FONT_XS};
|
||||
}
|
||||
${fontXSStyle('.affine-attachment-rename-input-wrapper input')}
|
||||
|
||||
.affine-attachment-rename-input-wrapper input::placeholder {
|
||||
color: var(--affine-placeholder-color);
|
||||
@@ -0,0 +1,34 @@
|
||||
import { EdgelessClipboardConfig } from '@blocksuite/affine-block-surface';
|
||||
import { type BlockSnapshot } from '@blocksuite/store';
|
||||
|
||||
export class EdgelessClipboardAttachmentConfig extends EdgelessClipboardConfig {
|
||||
static override readonly key = 'affine:attachment';
|
||||
|
||||
override async createBlock(
|
||||
attachment: BlockSnapshot
|
||||
): Promise<string | null> {
|
||||
if (!this.surface) return null;
|
||||
|
||||
const { xywh, rotate, sourceId, name, size, type, embed, style } =
|
||||
attachment.props;
|
||||
|
||||
if (!(await this.std.workspace.blobSync.get(sourceId as string))) {
|
||||
return null;
|
||||
}
|
||||
const attachmentId = this.crud.addBlock(
|
||||
'affine:attachment',
|
||||
{
|
||||
xywh,
|
||||
rotate,
|
||||
sourceId,
|
||||
name,
|
||||
size,
|
||||
type,
|
||||
embed,
|
||||
style,
|
||||
},
|
||||
this.surface.model.id
|
||||
);
|
||||
return attachmentId;
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ export * from './attachment-block';
|
||||
export * from './attachment-service';
|
||||
export * from './attachment-spec';
|
||||
export { attachmentViewDropdownMenu } from './configs/toolbar';
|
||||
export * from './edgeless-clipboard-config';
|
||||
export {
|
||||
type AttachmentEmbedConfig,
|
||||
AttachmentEmbedConfigIdentifier,
|
||||
@@ -7,12 +7,12 @@
|
||||
},
|
||||
"include": ["./src"],
|
||||
"references": [
|
||||
{ "path": "../block-note" },
|
||||
{ "path": "../block-surface" },
|
||||
{ "path": "../embed" },
|
||||
{ "path": "../surface" },
|
||||
{ "path": "../../components" },
|
||||
{ "path": "../../model" },
|
||||
{ "path": "../../shared" },
|
||||
{ "path": "../../widgets/widget-slash-menu" },
|
||||
{ "path": "../../widgets/slash-menu" },
|
||||
{ "path": "../../../framework/global" },
|
||||
{ "path": "../../../framework/std" },
|
||||
{ "path": "../../../framework/store" }
|
||||
@@ -1,79 +0,0 @@
|
||||
import {
|
||||
type InsertedLinkType,
|
||||
insertEmbedIframeWithUrlCommand,
|
||||
insertEmbedLinkedDocCommand,
|
||||
type LinkableFlavour,
|
||||
} from '@blocksuite/affine-block-embed';
|
||||
import {
|
||||
FeatureFlagService,
|
||||
QuickSearchProvider,
|
||||
} from '@blocksuite/affine-shared/services';
|
||||
import type { Command } from '@blocksuite/std';
|
||||
|
||||
import { insertBookmarkCommand } from './insert-bookmark';
|
||||
|
||||
export const insertLinkByQuickSearchCommand: Command<
|
||||
{},
|
||||
{ insertedLinkType: Promise<InsertedLinkType> }
|
||||
> = (ctx, next) => {
|
||||
const { std } = ctx;
|
||||
const quickSearchService = std.getOptional(QuickSearchProvider);
|
||||
if (!quickSearchService) {
|
||||
next();
|
||||
return;
|
||||
}
|
||||
|
||||
const insertedLinkType: Promise<InsertedLinkType> = quickSearchService
|
||||
.openQuickSearch()
|
||||
.then(result => {
|
||||
if (!result) return null;
|
||||
|
||||
// add linked doc
|
||||
if ('docId' in result) {
|
||||
std.command.exec(insertEmbedLinkedDocCommand, {
|
||||
docId: result.docId,
|
||||
params: result.params,
|
||||
});
|
||||
return {
|
||||
flavour: 'affine:embed-linked-doc',
|
||||
};
|
||||
}
|
||||
|
||||
// add normal link;
|
||||
if ('externalUrl' in result) {
|
||||
const featureFlagService = std.get(FeatureFlagService);
|
||||
const enableEmbedIframeBlock = featureFlagService.getFlag(
|
||||
'enable_embed_iframe_block'
|
||||
);
|
||||
if (enableEmbedIframeBlock) {
|
||||
// try to insert embed iframe block first
|
||||
const [success, { flavour }] = std.command
|
||||
.chain()
|
||||
.try(chain => [
|
||||
chain.pipe(insertEmbedIframeWithUrlCommand, {
|
||||
url: result.externalUrl,
|
||||
}),
|
||||
chain.pipe(insertBookmarkCommand, { url: result.externalUrl }),
|
||||
])
|
||||
.run();
|
||||
if (!success || !flavour) return null;
|
||||
return {
|
||||
flavour: flavour as LinkableFlavour,
|
||||
};
|
||||
} else {
|
||||
const [success, { flavour }] = std.command.exec(
|
||||
insertBookmarkCommand,
|
||||
{ url: result.externalUrl }
|
||||
);
|
||||
if (!success || !flavour) return null;
|
||||
return {
|
||||
flavour: flavour as LinkableFlavour,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
});
|
||||
|
||||
next({ insertedLinkType });
|
||||
};
|
||||
@@ -1,20 +0,0 @@
|
||||
{
|
||||
"extends": "../../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"rootDir": "./src",
|
||||
"outDir": "./dist",
|
||||
"tsBuildInfoFile": "./dist/tsconfig.tsbuildinfo"
|
||||
},
|
||||
"include": ["./src"],
|
||||
"references": [
|
||||
{ "path": "../block-surface" },
|
||||
{ "path": "../../components" },
|
||||
{ "path": "../../model" },
|
||||
{ "path": "../../shared" },
|
||||
{ "path": "../../widgets/widget-edgeless-toolbar" },
|
||||
{ "path": "../../widgets/widget-frame-title" },
|
||||
{ "path": "../../../framework/global" },
|
||||
{ "path": "../../../framework/std" },
|
||||
{ "path": "../../../framework/store" }
|
||||
]
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
import { ImageBlockModel } from '@blocksuite/affine-model';
|
||||
import {
|
||||
type ToolbarModuleConfig,
|
||||
ToolbarModuleExtension,
|
||||
} from '@blocksuite/affine-shared/services';
|
||||
import { CaptionIcon, DownloadIcon } from '@blocksuite/icons/lit';
|
||||
import { BlockFlavourIdentifier } from '@blocksuite/std';
|
||||
import type { ExtensionType } from '@blocksuite/store';
|
||||
|
||||
import { ImageEdgelessBlockComponent } from '../image-edgeless-block';
|
||||
|
||||
const trackBaseProps = {
|
||||
category: 'image',
|
||||
type: 'card view',
|
||||
};
|
||||
|
||||
const builtinSurfaceToolbarConfig = {
|
||||
actions: [
|
||||
{
|
||||
id: 'a.download',
|
||||
tooltip: 'Download',
|
||||
icon: DownloadIcon(),
|
||||
run(ctx) {
|
||||
const block = ctx.getCurrentBlockByType(ImageEdgelessBlockComponent);
|
||||
block?.download();
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'b.caption',
|
||||
tooltip: 'Caption',
|
||||
icon: CaptionIcon(),
|
||||
run(ctx) {
|
||||
const block = ctx.getCurrentBlockByType(ImageEdgelessBlockComponent);
|
||||
block?.captionEditor?.show();
|
||||
|
||||
ctx.track('OpenedCaptionEditor', {
|
||||
...trackBaseProps,
|
||||
control: 'add caption',
|
||||
});
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
when: ctx => ctx.getSurfaceModelsByType(ImageBlockModel).length === 1,
|
||||
} as const satisfies ToolbarModuleConfig;
|
||||
|
||||
export const createBuiltinToolbarConfigExtension = (
|
||||
flavour: string
|
||||
): ExtensionType[] => {
|
||||
const name = flavour.split(':').pop();
|
||||
|
||||
return [
|
||||
ToolbarModuleExtension({
|
||||
id: BlockFlavourIdentifier(`affine:surface:${name}`),
|
||||
config: builtinSurfaceToolbarConfig,
|
||||
}),
|
||||
];
|
||||
};
|
||||
@@ -1,435 +0,0 @@
|
||||
import {
|
||||
type ClipboardConfigCreationContext,
|
||||
EdgelessClipboardConfig,
|
||||
} from '@blocksuite/affine-block-surface';
|
||||
import { ReferenceInfoSchema } from '@blocksuite/affine-model';
|
||||
import { type BlockSnapshot, fromJSON } from '@blocksuite/store';
|
||||
|
||||
export class EdgelessClipboardNoteConfig extends EdgelessClipboardConfig {
|
||||
static override readonly key = 'affine:note';
|
||||
|
||||
override async createBlock(note: BlockSnapshot): Promise<null | string> {
|
||||
const oldId = note.id;
|
||||
|
||||
delete note.props.index;
|
||||
if (!note.props.xywh) {
|
||||
console.error(`Note block(id: ${oldId}) does not have xywh property`);
|
||||
return null;
|
||||
}
|
||||
|
||||
const newId = await this.onBlockSnapshotPaste(
|
||||
note,
|
||||
this.std.store,
|
||||
this.std.store.root!.id
|
||||
);
|
||||
if (!newId) {
|
||||
console.error(`Failed to paste note block(id: ${oldId})`);
|
||||
return null;
|
||||
}
|
||||
|
||||
return newId;
|
||||
}
|
||||
}
|
||||
|
||||
export class EdgelessClipboardEdgelessTextConfig extends EdgelessClipboardConfig {
|
||||
static override readonly key = 'affine:edgeless-text';
|
||||
|
||||
override async createBlock(
|
||||
edgelessText: BlockSnapshot
|
||||
): Promise<string | null> {
|
||||
const oldId = edgelessText.id;
|
||||
delete edgelessText.props.index;
|
||||
if (!edgelessText.props.xywh) {
|
||||
console.error(
|
||||
`EdgelessText block(id: ${oldId}) does not have xywh property`
|
||||
);
|
||||
return null;
|
||||
}
|
||||
if (!this.surface) {
|
||||
return null;
|
||||
}
|
||||
const newId = await this.onBlockSnapshotPaste(
|
||||
edgelessText,
|
||||
this.std.store,
|
||||
this.surface.model.id
|
||||
);
|
||||
if (!newId) {
|
||||
console.error(`Failed to paste EdgelessText block(id: ${oldId})`);
|
||||
return null;
|
||||
}
|
||||
|
||||
return newId;
|
||||
}
|
||||
}
|
||||
|
||||
export class EdgelessClipboardImageConfig extends EdgelessClipboardConfig {
|
||||
static override readonly key = 'affine:image';
|
||||
|
||||
override async createBlock(image: BlockSnapshot) {
|
||||
const { xywh, rotate, sourceId, size, width, height, caption } =
|
||||
image.props;
|
||||
|
||||
if (!this.surface) return null;
|
||||
|
||||
if (!(await this.std.workspace.blobSync.get(sourceId as string))) {
|
||||
return null;
|
||||
}
|
||||
return this.crud.addBlock(
|
||||
'affine:image',
|
||||
{
|
||||
caption,
|
||||
sourceId,
|
||||
xywh,
|
||||
rotate,
|
||||
size,
|
||||
width,
|
||||
height,
|
||||
},
|
||||
this.surface.model.id
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export class EdgelessClipboardFrameConfig extends EdgelessClipboardConfig {
|
||||
static override readonly key = 'affine:frame';
|
||||
|
||||
override createBlock(
|
||||
frame: BlockSnapshot,
|
||||
context: ClipboardConfigCreationContext
|
||||
): string | null {
|
||||
if (!this.surface) return null;
|
||||
|
||||
const { oldToNewIdMap, newPresentationIndexes } = context;
|
||||
const { xywh, title, background, childElementIds } = frame.props;
|
||||
|
||||
const newChildElementIds: Record<string, boolean> = {};
|
||||
|
||||
if (typeof childElementIds === 'object' && childElementIds !== null) {
|
||||
Object.keys(childElementIds).forEach(oldId => {
|
||||
const newId = oldToNewIdMap.get(oldId);
|
||||
if (newId) {
|
||||
newChildElementIds[newId] = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const frameId = this.crud.addBlock(
|
||||
'affine:frame',
|
||||
{
|
||||
xywh,
|
||||
background,
|
||||
title: fromJSON(title),
|
||||
childElementIds: newChildElementIds,
|
||||
presentationIndex: newPresentationIndexes.get(frame.id),
|
||||
},
|
||||
this.surface.model.id
|
||||
);
|
||||
return frameId;
|
||||
}
|
||||
}
|
||||
|
||||
export class EdgelessClipboardAttachmentConfig extends EdgelessClipboardConfig {
|
||||
static override readonly key = 'affine:attachment';
|
||||
|
||||
override async createBlock(
|
||||
attachment: BlockSnapshot
|
||||
): Promise<string | null> {
|
||||
if (!this.surface) return null;
|
||||
|
||||
const { xywh, rotate, sourceId, name, size, type, embed, style } =
|
||||
attachment.props;
|
||||
|
||||
if (!(await this.std.workspace.blobSync.get(sourceId as string))) {
|
||||
return null;
|
||||
}
|
||||
const attachmentId = this.crud.addBlock(
|
||||
'affine:attachment',
|
||||
{
|
||||
xywh,
|
||||
rotate,
|
||||
sourceId,
|
||||
name,
|
||||
size,
|
||||
type,
|
||||
embed,
|
||||
style,
|
||||
},
|
||||
this.surface.model.id
|
||||
);
|
||||
return attachmentId;
|
||||
}
|
||||
}
|
||||
|
||||
export class EdgelessClipboardBookmarkConfig extends EdgelessClipboardConfig {
|
||||
static override readonly key = 'affine:bookmark';
|
||||
|
||||
override createBlock(bookmark: BlockSnapshot): string | null {
|
||||
if (!this.surface) return null;
|
||||
|
||||
const { xywh, style, url, caption, description, icon, image, title } =
|
||||
bookmark.props;
|
||||
|
||||
const bookmarkId = this.crud.addBlock(
|
||||
'affine:bookmark',
|
||||
{
|
||||
xywh,
|
||||
style,
|
||||
url,
|
||||
caption,
|
||||
description,
|
||||
icon,
|
||||
image,
|
||||
title,
|
||||
},
|
||||
this.surface.model.id
|
||||
);
|
||||
return bookmarkId;
|
||||
}
|
||||
}
|
||||
|
||||
export class EdgelessClipboardEmbedFigmaConfig extends EdgelessClipboardConfig {
|
||||
static override readonly key = 'affine:embed-figma';
|
||||
|
||||
override createBlock(figmaEmbed: BlockSnapshot): string | null {
|
||||
if (!this.surface) return null;
|
||||
const { xywh, style, url, caption, title, description } = figmaEmbed.props;
|
||||
|
||||
const embedFigmaId = this.crud.addBlock(
|
||||
'affine:embed-figma',
|
||||
{
|
||||
xywh,
|
||||
style,
|
||||
url,
|
||||
caption,
|
||||
title,
|
||||
description,
|
||||
},
|
||||
this.surface.model.id
|
||||
);
|
||||
return embedFigmaId;
|
||||
}
|
||||
}
|
||||
|
||||
export class EdgelessClipboardEmbedGithubConfig extends EdgelessClipboardConfig {
|
||||
static override readonly key = 'affine:embed-github';
|
||||
|
||||
override createBlock(githubEmbed: BlockSnapshot): string | null {
|
||||
if (!this.surface) return null;
|
||||
|
||||
const {
|
||||
xywh,
|
||||
style,
|
||||
owner,
|
||||
repo,
|
||||
githubType,
|
||||
githubId,
|
||||
url,
|
||||
caption,
|
||||
image,
|
||||
status,
|
||||
statusReason,
|
||||
title,
|
||||
description,
|
||||
createdAt,
|
||||
assignees,
|
||||
} = githubEmbed.props;
|
||||
|
||||
const embedGithubId = this.crud.addBlock(
|
||||
'affine:embed-github',
|
||||
{
|
||||
xywh,
|
||||
style,
|
||||
owner,
|
||||
repo,
|
||||
githubType,
|
||||
githubId,
|
||||
url,
|
||||
caption,
|
||||
image,
|
||||
status,
|
||||
statusReason,
|
||||
title,
|
||||
description,
|
||||
createdAt,
|
||||
assignees,
|
||||
},
|
||||
this.surface.model.id
|
||||
);
|
||||
return embedGithubId;
|
||||
}
|
||||
}
|
||||
|
||||
export class EdgelessClipboardEmbedHtmlConfig extends EdgelessClipboardConfig {
|
||||
static override readonly key = 'affine:embed-html';
|
||||
|
||||
override createBlock(htmlEmbed: BlockSnapshot): string | null {
|
||||
if (!this.surface) return null;
|
||||
const { xywh, style, caption, html, design } = htmlEmbed.props;
|
||||
|
||||
const embedHtmlId = this.crud.addBlock(
|
||||
'affine:embed-html',
|
||||
{
|
||||
xywh,
|
||||
style,
|
||||
caption,
|
||||
html,
|
||||
design,
|
||||
},
|
||||
this.surface.model.id
|
||||
);
|
||||
return embedHtmlId;
|
||||
}
|
||||
}
|
||||
|
||||
export class EdgelessClipboardEmbedLoomConfig extends EdgelessClipboardConfig {
|
||||
static override readonly key = 'affine:embed-loom';
|
||||
|
||||
override createBlock(loomEmbed: BlockSnapshot): string | null {
|
||||
if (!this.surface) return null;
|
||||
const { xywh, style, url, caption, videoId, image, title, description } =
|
||||
loomEmbed.props;
|
||||
|
||||
const embedLoomId = this.crud.addBlock(
|
||||
'affine:embed-loom',
|
||||
{
|
||||
xywh,
|
||||
style,
|
||||
url,
|
||||
caption,
|
||||
videoId,
|
||||
image,
|
||||
title,
|
||||
description,
|
||||
},
|
||||
this.surface.model.id
|
||||
);
|
||||
return embedLoomId;
|
||||
}
|
||||
}
|
||||
|
||||
export class EdgelessClipboardEmbedYoutubeConfig extends EdgelessClipboardConfig {
|
||||
static override readonly key = 'affine:embed-youtube';
|
||||
|
||||
override createBlock(youtubeEmbed: BlockSnapshot): string | null {
|
||||
if (!this.surface) return null;
|
||||
const {
|
||||
xywh,
|
||||
style,
|
||||
url,
|
||||
caption,
|
||||
videoId,
|
||||
image,
|
||||
title,
|
||||
description,
|
||||
creator,
|
||||
creatorUrl,
|
||||
creatorImage,
|
||||
} = youtubeEmbed.props;
|
||||
|
||||
const embedYoutubeId = this.crud.addBlock(
|
||||
'affine:embed-youtube',
|
||||
{
|
||||
xywh,
|
||||
style,
|
||||
url,
|
||||
caption,
|
||||
videoId,
|
||||
image,
|
||||
title,
|
||||
description,
|
||||
creator,
|
||||
creatorUrl,
|
||||
creatorImage,
|
||||
},
|
||||
this.surface.model.id
|
||||
);
|
||||
return embedYoutubeId;
|
||||
}
|
||||
}
|
||||
|
||||
export class EdgelessClipboardEmbedIframeConfig extends EdgelessClipboardConfig {
|
||||
static override readonly key = 'affine:embed-iframe';
|
||||
|
||||
override createBlock(embedIframe: BlockSnapshot): string | null {
|
||||
if (!this.surface) return null;
|
||||
const {
|
||||
xywh,
|
||||
caption,
|
||||
url,
|
||||
title,
|
||||
description,
|
||||
iframeUrl,
|
||||
scale,
|
||||
width,
|
||||
height,
|
||||
} = embedIframe.props;
|
||||
|
||||
return this.crud.addBlock(
|
||||
'affine:embed-iframe',
|
||||
{
|
||||
url,
|
||||
iframeUrl,
|
||||
xywh,
|
||||
caption,
|
||||
title,
|
||||
description,
|
||||
scale,
|
||||
width,
|
||||
height,
|
||||
},
|
||||
this.surface.model.id
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export class EdgelessClipboardEmbedLinkedDocConfig extends EdgelessClipboardConfig {
|
||||
static override readonly key = 'affine:embed-linked-doc';
|
||||
|
||||
override createBlock(linkedDocEmbed: BlockSnapshot): string | null {
|
||||
if (!this.surface) return null;
|
||||
|
||||
const { xywh, style, caption, pageId, params, title, description } =
|
||||
linkedDocEmbed.props;
|
||||
const referenceInfo = ReferenceInfoSchema.parse({
|
||||
pageId,
|
||||
params,
|
||||
title,
|
||||
description,
|
||||
});
|
||||
|
||||
return this.crud.addBlock(
|
||||
'affine:embed-linked-doc',
|
||||
{
|
||||
xywh,
|
||||
style,
|
||||
caption,
|
||||
...referenceInfo,
|
||||
},
|
||||
this.surface.model.id
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export class EdgelessClipboardEmbedSyncedDocConfig extends EdgelessClipboardConfig {
|
||||
static override readonly key = 'affine:embed-synced-doc';
|
||||
|
||||
override createBlock(syncedDocEmbed: BlockSnapshot): string | null {
|
||||
if (!this.surface) return null;
|
||||
|
||||
const { xywh, style, caption, scale, pageId, params } =
|
||||
syncedDocEmbed.props;
|
||||
const referenceInfo = ReferenceInfoSchema.parse({ pageId, params });
|
||||
|
||||
return this.crud.addBlock(
|
||||
'affine:embed-synced-doc',
|
||||
{
|
||||
xywh,
|
||||
style,
|
||||
caption,
|
||||
scale,
|
||||
...referenceInfo,
|
||||
},
|
||||
this.surface.model.id
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
import { html } from 'lit';
|
||||
|
||||
export const LassoFreeHandIcon = html`
|
||||
<svg
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M7.03152 18.9667C8.07902 18.9667 8.92819 18.1175 8.92819 17.07C8.92819 16.0225 8.07902 15.1733 7.03152 15.1733C5.98402 15.1733 5.13485 16.0225 5.13485 17.07C5.13485 18.1175 5.98402 18.9667 7.03152 18.9667ZM7.03152 20.2667C8.79699 20.2667 10.2282 18.8355 10.2282 17.07C10.2282 15.3045 8.79699 13.8733 7.03152 13.8733C5.26605 13.8733 3.83485 15.3045 3.83485 17.07C3.83485 18.8355 5.26605 20.2667 7.03152 20.2667Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M4.75714 19.6175C4.75714 19.3949 4.81661 19.145 4.93113 18.856C5.02405 18.6215 5.30218 18.5315 5.52776 18.6442C5.75334 18.757 5.83848 19.0293 5.75223 19.2663C5.68785 19.4432 5.67047 19.5529 5.67047 19.6175C5.67047 19.6727 5.67683 19.6824 5.71909 19.7205C5.74837 19.7468 5.77881 19.7695 5.82813 19.8062C5.8416 19.8162 5.85647 19.8273 5.87312 19.8398C5.94101 19.8907 6.03269 19.9615 6.119 20.0543C6.31218 20.2619 6.44109 20.5388 6.44109 20.9276C6.44109 21.3166 6.3093 21.6272 6.02789 21.8443C5.80114 22.0192 5.50339 22.1052 5.27045 22.1724C5.26524 22.1739 5.26006 22.1754 5.25492 22.1769C5.24264 22.1804 5.23031 22.184 5.21794 22.1876C4.8171 22.3032 4.37177 22.4316 3.91148 22.7773C3.70983 22.9288 3.42276 22.9326 3.24443 22.7542C3.06609 22.5759 3.06453 22.2842 3.26124 22.1263C3.89506 21.6177 4.50962 21.4409 4.94956 21.3144C4.96714 21.3093 4.98443 21.3044 5.00143 21.2994C5.28007 21.2189 5.40217 21.1735 5.47003 21.1211C5.471 21.1204 5.47202 21.1196 5.47311 21.1188C5.49238 21.1045 5.52776 21.0781 5.52776 20.9276C5.52776 20.7684 5.48543 20.7141 5.45027 20.6763C5.42241 20.6464 5.38566 20.6159 5.32511 20.5705C5.31683 20.5642 5.30753 20.5574 5.29743 20.5499C5.24552 20.5114 5.17247 20.4573 5.1081 20.3994C4.92203 20.2319 4.75714 19.9905 4.75714 19.6175Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M12.2086 12.6149C11.9968 11.7531 12.903 11.0458 13.6876 11.4606L22.0945 15.905C22.9737 16.3698 22.7465 17.6876 21.7625 17.8313L17.8897 18.3968C17.8383 18.4043 17.7946 18.4384 17.7749 18.4867L16.3978 21.8656C16.0219 22.7881 14.685 22.6903 14.4473 21.7229L12.2086 12.6149ZM13.2757 12.2397C13.1636 12.1804 13.0342 12.2815 13.0644 12.4046L15.3031 21.5126C15.3371 21.6508 15.528 21.6648 15.5817 21.533L16.9588 18.1541C17.0963 17.8167 17.402 17.5773 17.7624 17.5247L21.6352 16.9593C21.7758 16.9388 21.8082 16.7505 21.6826 16.6841L13.2757 12.2397Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M19.1489 14.9806C20.1975 13.7474 20.8015 12.2466 20.8015 10.6767C20.8015 6.775 17.0709 3.3 12.0549 3.3C7.03878 3.3 3.30818 6.775 3.30818 10.6767C3.30818 12.1636 3.85 13.5886 4.7983 14.7828C4.47298 15.1005 4.21518 15.4871 4.04843 15.9189C2.76805 14.4626 2.00818 12.6463 2.00818 10.6767C2.00818 5.88468 6.50623 2 12.0549 2C17.6035 2 22.1015 5.88468 22.1015 10.6767C22.1015 12.4784 21.4656 14.1519 20.3771 15.5389L19.1489 14.9806ZM13.9695 17.8785C13.3575 17.9927 12.7174 18.0534 12.0549 18.0534C11.3871 18.0534 10.7422 17.9918 10.1258 17.8758C10.0103 18.3206 9.80141 18.7278 9.52133 19.0751C10.3307 19.2567 11.1797 19.3533 12.0549 19.3533C12.8212 19.3533 13.5675 19.2793 14.2846 19.1389L13.9695 17.8785Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
`;
|
||||
|
||||
export const LassoPolygonalIcon = html`
|
||||
<svg
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M12.1538 12.3949C11.9419 11.533 12.8482 10.8257 13.6328 11.2405L22.0397 15.6849C22.9188 16.1497 22.6917 17.4676 21.7077 17.6112L17.8349 18.1767C17.7834 18.1842 17.7397 18.2184 17.7201 18.2666L16.343 21.6455C15.967 22.568 14.6302 22.4703 14.3924 21.5029L12.1538 12.3949ZM13.2209 12.0196C13.1088 11.9604 12.9793 12.0614 13.0096 12.1845L15.2482 21.2926C15.2822 21.4308 15.4732 21.4447 15.5269 21.3129L16.9039 17.934C17.0414 17.5967 17.3471 17.3573 17.7076 17.3047L21.5804 16.7393C21.7209 16.7187 21.7534 16.5304 21.6278 16.4641L13.2209 12.0196Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M9.11 18.9667C10.1575 18.9667 11.0067 18.1175 11.0067 17.07C11.0067 16.0225 10.1575 15.1733 9.11 15.1733C8.0625 15.1733 7.21333 16.0225 7.21333 17.07C7.21333 18.1175 8.0625 18.9667 9.11 18.9667ZM9.11 20.2667C10.8755 20.2667 12.3067 18.8355 12.3067 17.07C12.3067 15.3045 10.8755 13.8733 9.11 13.8733C7.34453 13.8733 5.91333 15.3045 5.91333 17.07C5.91333 18.8355 7.34453 20.2667 9.11 20.2667Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M20.15 1.78546V12.8479L18.2895 14.0882L17.0275 13.3671L18.85 12.1521V4.21453L10.565 9.7379L3.78505 6.77169L7.24943 14.4703C6.85977 14.7497 6.5355 15.1145 6.30404 15.5374L1.21497 4.22831L10.4351 8.26209L20.15 1.78546ZM12.0942 18.2184L13.8336 17.0588L13.443 15.7568L12.2635 16.5431C12.2919 16.7146 12.3067 16.8905 12.3067 17.07C12.3067 17.4748 12.2315 17.862 12.0942 18.2184Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M6.83562 19.6175C6.83562 19.3949 6.89509 19.145 7.00962 18.856C7.10254 18.6215 7.38066 18.5314 7.60625 18.6442C7.83183 18.757 7.91697 19.0293 7.83072 19.2663C7.76634 19.4432 7.74896 19.5529 7.74896 19.6175C7.74896 19.6726 7.75531 19.6824 7.79757 19.7204C7.82686 19.7468 7.8573 19.7695 7.90662 19.8062C7.92009 19.8162 7.93496 19.8273 7.9516 19.8398C8.0195 19.8907 8.11118 19.9615 8.19749 20.0542C8.39066 20.2619 8.51958 20.5387 8.51958 20.9276C8.51958 21.3165 8.38779 21.6272 8.10638 21.8443C7.87962 22.0192 7.58188 22.1051 7.34894 22.1724C7.34373 22.1739 7.33855 22.1754 7.33341 22.1769C7.32112 22.1804 7.3088 22.184 7.29643 22.1875C6.89559 22.3031 6.45026 22.4316 5.98997 22.7773C5.78832 22.9288 5.50125 22.9326 5.32291 22.7542C5.14457 22.5759 5.14302 22.2841 5.33973 22.1263C5.97355 21.6177 6.58811 21.4409 7.02805 21.3144C7.04562 21.3093 7.06292 21.3043 7.07992 21.2994C7.35856 21.2189 7.48065 21.1735 7.54851 21.1211C7.54948 21.1204 7.55051 21.1196 7.55159 21.1188C7.57087 21.1044 7.60625 21.0781 7.60625 20.9276C7.60625 20.7684 7.56391 20.7141 7.52876 20.6763C7.5009 20.6464 7.46415 20.6158 7.4036 20.5704C7.39532 20.5642 7.38602 20.5573 7.37592 20.5498C7.324 20.5114 7.25095 20.4573 7.18659 20.3993C7.00052 20.2319 6.83562 19.9905 6.83562 19.6175Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
`;
|
||||
@@ -1,41 +0,0 @@
|
||||
import { menu } from '@blocksuite/affine-components/context-menu';
|
||||
import { LassoMode } from '@blocksuite/affine-shared/types';
|
||||
import type { DenseMenuBuilder } from '@blocksuite/affine-widget-edgeless-toolbar';
|
||||
|
||||
import { LassoFreeHandIcon, LassoPolygonalIcon } from './icons.js';
|
||||
|
||||
export const buildLassoDenseMenu: DenseMenuBuilder = (_, gfx) => {
|
||||
// TODO: active state
|
||||
// const prevMode =
|
||||
// edgeless.service.editPropsStore.getLastProps('lasso').mode ??
|
||||
// LassoMode.FreeHand;
|
||||
|
||||
const isActive = gfx.tool.currentToolName$.peek() === 'lasso';
|
||||
|
||||
const createSelect = (mode: LassoMode) => () => {
|
||||
gfx.tool.setTool('lasso', { mode });
|
||||
};
|
||||
|
||||
return menu.subMenu({
|
||||
name: 'Lasso',
|
||||
prefix: LassoFreeHandIcon,
|
||||
select: createSelect(LassoMode.FreeHand),
|
||||
isSelected: isActive,
|
||||
options: {
|
||||
items: [
|
||||
menu.action({
|
||||
prefix: LassoFreeHandIcon,
|
||||
name: 'Free',
|
||||
select: createSelect(LassoMode.FreeHand),
|
||||
// isSelected: isActive && prevMode === LassoMode.FreeHand,
|
||||
}),
|
||||
menu.action({
|
||||
prefix: LassoPolygonalIcon,
|
||||
name: 'Polygonal',
|
||||
select: createSelect(LassoMode.Polygonal),
|
||||
// isSelected: isActive && prevMode === LassoMode.Polygonal,
|
||||
}),
|
||||
],
|
||||
},
|
||||
});
|
||||
};
|
||||
@@ -1,99 +0,0 @@
|
||||
import { LassoMode } from '@blocksuite/affine-shared/types';
|
||||
import { QuickToolMixin } from '@blocksuite/affine-widget-edgeless-toolbar';
|
||||
import { WithDisposable } from '@blocksuite/global/lit';
|
||||
import { effect } from '@preact/signals-core';
|
||||
import { css, html, LitElement } from 'lit';
|
||||
import { query, state } from 'lit/decorators.js';
|
||||
|
||||
import { LassoFreeHandIcon, LassoPolygonalIcon } from './icons.js';
|
||||
|
||||
export class EdgelessLassoToolButton extends QuickToolMixin(
|
||||
WithDisposable(LitElement)
|
||||
) {
|
||||
static override styles = css`
|
||||
.current-icon {
|
||||
transition: 100ms;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
.current-icon > svg {
|
||||
display: block;
|
||||
}
|
||||
`;
|
||||
|
||||
private readonly _changeTool = () => {
|
||||
const tool = this.edgelessTool;
|
||||
if (tool.type !== 'lasso') {
|
||||
this.setEdgelessTool({ type: 'lasso', mode: this.curMode });
|
||||
return;
|
||||
}
|
||||
|
||||
this._fadeOut();
|
||||
setTimeout(() => {
|
||||
this.curMode === LassoMode.FreeHand
|
||||
? this.setEdgelessTool({ type: 'lasso', mode: LassoMode.Polygonal })
|
||||
: this.setEdgelessTool({ type: 'lasso', mode: LassoMode.FreeHand });
|
||||
this._fadeIn();
|
||||
}, 100);
|
||||
};
|
||||
|
||||
override type = 'lasso' as const;
|
||||
|
||||
private _fadeIn() {
|
||||
this.currentIcon.style.opacity = '1';
|
||||
this.currentIcon.style.transform = `translateY(0px)`;
|
||||
}
|
||||
|
||||
private _fadeOut() {
|
||||
this.currentIcon.style.opacity = '0';
|
||||
this.currentIcon.style.transform = `translateY(-5px)`;
|
||||
}
|
||||
|
||||
override connectedCallback(): void {
|
||||
super.connectedCallback();
|
||||
|
||||
this.disposables.add(
|
||||
effect(() => {
|
||||
const tool = this.gfx.tool.currentToolOption$.value;
|
||||
|
||||
if (tool?.type === 'lasso') {
|
||||
const { mode } = tool;
|
||||
this.curMode = mode;
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
override render() {
|
||||
const type = this.edgelessTool?.type;
|
||||
const mode = this.curMode === LassoMode.FreeHand ? 'freehand' : 'polygonal';
|
||||
|
||||
return html`
|
||||
<edgeless-tool-icon-button
|
||||
class="edgeless-lasso-button ${mode}"
|
||||
.tooltip=${html`<affine-tooltip-content-with-shortcut
|
||||
data-tip="${'Lasso'}"
|
||||
data-shortcut="${'L'}"
|
||||
></affine-tooltip-content-with-shortcut>`}
|
||||
.tooltipOffset=${17}
|
||||
.active=${type === 'lasso'}
|
||||
.iconContainerPadding=${6}
|
||||
.iconSize=${'24px'}
|
||||
@click=${this._changeTool}
|
||||
>
|
||||
<span class="current-icon">
|
||||
${this.curMode === LassoMode.FreeHand
|
||||
? LassoFreeHandIcon
|
||||
: LassoPolygonalIcon}
|
||||
</span>
|
||||
<toolbar-arrow-up-icon></toolbar-arrow-up-icon>
|
||||
</edgeless-tool-icon-button>
|
||||
`;
|
||||
}
|
||||
|
||||
@state()
|
||||
accessor curMode: LassoMode = LassoMode.FreeHand;
|
||||
|
||||
@query('.current-icon')
|
||||
accessor currentIcon!: HTMLInputElement;
|
||||
}
|
||||
@@ -1,326 +0,0 @@
|
||||
import {
|
||||
Overlay,
|
||||
type SurfaceBlockComponent,
|
||||
} from '@blocksuite/affine-block-surface';
|
||||
import { ThemeProvider } from '@blocksuite/affine-shared/services';
|
||||
import { LassoMode } from '@blocksuite/affine-shared/types';
|
||||
import type { IPoint, IVec } from '@blocksuite/global/gfx';
|
||||
import {
|
||||
Bound,
|
||||
getBoundFromPoints,
|
||||
getPolygonPathFromPoints,
|
||||
getSvgPathFromStroke,
|
||||
linePolygonIntersects,
|
||||
pointInPolygon,
|
||||
rotatePoints,
|
||||
Vec,
|
||||
} from '@blocksuite/global/gfx';
|
||||
import type { PointerEventState } from '@blocksuite/std';
|
||||
import { BaseTool } from '@blocksuite/std/gfx';
|
||||
|
||||
class LassoOverlay extends Overlay {
|
||||
d = '';
|
||||
|
||||
startPoint: IVec | null = null;
|
||||
|
||||
render(ctx: CanvasRenderingContext2D): void {
|
||||
const path = new Path2D(this.d);
|
||||
const zoom = this._renderer?.viewport.zoom ?? 1.0;
|
||||
ctx.save();
|
||||
const primaryColor = this.gfx.std
|
||||
.get(ThemeProvider)
|
||||
.getCssVariableColor('--affine-primary-color');
|
||||
const strokeColor = this.gfx.std
|
||||
.get(ThemeProvider)
|
||||
.getCssVariableColor('--affine-secondary-color');
|
||||
if (this.startPoint) {
|
||||
const [x, y] = this.startPoint;
|
||||
ctx.beginPath();
|
||||
ctx.arc(x, y, 2 / zoom, 0, Math.PI * 2);
|
||||
ctx.fillStyle = primaryColor;
|
||||
ctx.fill();
|
||||
}
|
||||
|
||||
ctx.strokeStyle = strokeColor;
|
||||
ctx.fillStyle = 'rgba(255, 255, 255, 0.1)';
|
||||
ctx.lineWidth = 2 / zoom;
|
||||
ctx.lineJoin = 'round';
|
||||
ctx.lineCap = 'round';
|
||||
ctx.setLineDash([2, 5]);
|
||||
ctx.fill(path);
|
||||
ctx.stroke(path);
|
||||
ctx.restore();
|
||||
}
|
||||
}
|
||||
|
||||
export type LassoToolOption = {
|
||||
mode: LassoMode;
|
||||
};
|
||||
export class LassoTool extends BaseTool<LassoToolOption> {
|
||||
static override toolName: string = 'lasso';
|
||||
|
||||
private _currentSelectionState = new Set<string>();
|
||||
|
||||
private _isSelecting = false;
|
||||
|
||||
private _lassoPoints: IVec[] = [];
|
||||
|
||||
private _lastPoint: IVec = [0, 0];
|
||||
|
||||
private readonly _loop = () => {
|
||||
const path =
|
||||
this.activatedOption.mode === LassoMode.FreeHand
|
||||
? getSvgPathFromStroke(this._lassoPoints)
|
||||
: getPolygonPathFromPoints(this._lassoPoints);
|
||||
|
||||
this._overlay.d = path;
|
||||
(this.gfx.surfaceComponent as SurfaceBlockComponent)?.refresh?.();
|
||||
this._raf = requestAnimationFrame(this._loop);
|
||||
};
|
||||
|
||||
private readonly _overlay = new LassoOverlay(this.gfx);
|
||||
|
||||
private _raf = 0;
|
||||
|
||||
get isSelecting() {
|
||||
return this._isSelecting;
|
||||
}
|
||||
|
||||
get selection() {
|
||||
return this.gfx.selection;
|
||||
}
|
||||
|
||||
get surfaceComponent() {
|
||||
return this.gfx.surfaceComponent as SurfaceBlockComponent;
|
||||
}
|
||||
|
||||
private _clearLastSelection() {
|
||||
if (this.selection.empty) {
|
||||
this.selection.clearLast();
|
||||
}
|
||||
}
|
||||
|
||||
private _getElementsInsideLasso() {
|
||||
const lassoBounds = getBoundFromPoints(this._lassoPoints);
|
||||
return this.gfx
|
||||
.getElementsByBound(lassoBounds)
|
||||
.filter(e =>
|
||||
this.isInsideLassoSelection(Bound.deserialize(e.xywh), e.rotate)
|
||||
);
|
||||
}
|
||||
|
||||
private _getSelectionMode(ev: PointerEventState): 'add' | 'sub' | 'set' {
|
||||
const shiftKey = ev.keys.shift ?? this.gfx.keyboard.shiftKey$.peek();
|
||||
const altKey = ev.keys.alt ?? false;
|
||||
if (shiftKey) return 'add';
|
||||
else if (altKey) return 'sub';
|
||||
else {
|
||||
return 'set';
|
||||
}
|
||||
}
|
||||
|
||||
private _reset() {
|
||||
cancelAnimationFrame(this._raf);
|
||||
(
|
||||
this.gfx.surfaceComponent as SurfaceBlockComponent
|
||||
)?.renderer.removeOverlay(this._overlay);
|
||||
this._overlay.d = '';
|
||||
this._overlay.startPoint = null;
|
||||
|
||||
const elements = this._getElementsInsideLasso();
|
||||
|
||||
this._currentSelectionState = new Set([
|
||||
...Array.from(this._currentSelectionState),
|
||||
...elements.map(el => el.id),
|
||||
]);
|
||||
|
||||
this._lassoPoints = [];
|
||||
this._isSelecting = false;
|
||||
}
|
||||
|
||||
private _setSelectionState(elements: string[], editing: boolean) {
|
||||
this.selection.set({
|
||||
elements,
|
||||
editing,
|
||||
});
|
||||
}
|
||||
|
||||
private _updateSelection(e: PointerEventState) {
|
||||
// elements inside the lasso selection
|
||||
const elements = this._getElementsInsideLasso()
|
||||
.filter(el => !el.isLocked())
|
||||
.map(el => el.id);
|
||||
|
||||
// current selections
|
||||
const selection = this.selection.selectedElements.map(el => el.id);
|
||||
|
||||
const selectionMode = this._getSelectionMode(e);
|
||||
let set!: Set<string>;
|
||||
switch (selectionMode) {
|
||||
case 'add':
|
||||
set = new Set([
|
||||
...elements,
|
||||
...selection.filter(elId => this._currentSelectionState.has(elId)),
|
||||
]);
|
||||
break;
|
||||
case 'sub': {
|
||||
const toRemove = new Set(elements);
|
||||
set = new Set(
|
||||
Array.from(this._currentSelectionState).filter(
|
||||
el => !toRemove.has(el)
|
||||
)
|
||||
);
|
||||
break;
|
||||
}
|
||||
case 'set':
|
||||
set = new Set(elements);
|
||||
break;
|
||||
}
|
||||
|
||||
this._setSelectionState(Array.from(set), false);
|
||||
}
|
||||
|
||||
private isInsideLassoSelection(bound: Bound, rotate: number): boolean {
|
||||
const { points, center } = bound;
|
||||
|
||||
const firstPoint = this._lassoPoints[0];
|
||||
const lassoPoints = this._lassoPoints.concat(
|
||||
firstPoint ? [firstPoint] : []
|
||||
);
|
||||
|
||||
const elPoly = rotatePoints(points, center, rotate);
|
||||
const lassoLen = lassoPoints.length;
|
||||
return (
|
||||
elPoly.some(point => pointInPolygon(point, lassoPoints)) ||
|
||||
lassoPoints.some((point, i, points) => {
|
||||
return linePolygonIntersects(point, points[(i + 1) % lassoLen], elPoly);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
private toModelCoord(p: IPoint): IVec {
|
||||
return this.gfx.viewport.toModelCoord(p.x, p.y);
|
||||
}
|
||||
|
||||
abort() {
|
||||
this._reset();
|
||||
}
|
||||
|
||||
override activate(): void {
|
||||
this._currentSelectionState = new Set(
|
||||
this.selection.selectedElements.map(el => el.id)
|
||||
);
|
||||
this._reset();
|
||||
}
|
||||
|
||||
override deactivate() {
|
||||
this._clearLastSelection();
|
||||
}
|
||||
|
||||
override dragEnd(e: PointerEventState): void {
|
||||
if (this.activatedOption.mode !== LassoMode.FreeHand) return;
|
||||
|
||||
this._updateSelection(e);
|
||||
|
||||
this._reset();
|
||||
}
|
||||
|
||||
override dragMove(e: PointerEventState): void {
|
||||
if (this.activatedOption.mode !== LassoMode.FreeHand) return;
|
||||
|
||||
const { point } = e;
|
||||
const [x, y] = this.toModelCoord(point);
|
||||
this._lassoPoints.push([x, y]);
|
||||
|
||||
this._updateSelection(e);
|
||||
}
|
||||
|
||||
// For Freehand Mode =
|
||||
override dragStart(e: PointerEventState): void {
|
||||
if (this.activatedOption.mode !== LassoMode.FreeHand) return;
|
||||
const { alt, shift } = e.keys;
|
||||
|
||||
if (!shift && !alt) {
|
||||
this._currentSelectionState.clear();
|
||||
this.selection.clear();
|
||||
}
|
||||
|
||||
this._currentSelectionState = new Set(
|
||||
this.selection.selectedElements.map(el => el.id)
|
||||
);
|
||||
|
||||
this._isSelecting = true;
|
||||
|
||||
const { point } = e;
|
||||
const [x, y] = this.toModelCoord(point);
|
||||
this._lassoPoints = [[x, y]];
|
||||
this._raf = requestAnimationFrame(this._loop);
|
||||
this._overlay.startPoint = this._lassoPoints[0];
|
||||
this.surfaceComponent.renderer.addOverlay(this._overlay);
|
||||
}
|
||||
|
||||
override pointerDown(e: PointerEventState): void {
|
||||
const { mode } = this.activatedOption;
|
||||
if (mode !== LassoMode.Polygonal) return;
|
||||
|
||||
const { alt, shift } = e.keys;
|
||||
if (!shift && !alt) {
|
||||
this._currentSelectionState.clear();
|
||||
this.selection.clear();
|
||||
}
|
||||
|
||||
this._isSelecting = true;
|
||||
|
||||
const { point } = e;
|
||||
const [x, y] = this.toModelCoord(point);
|
||||
if (this._lassoPoints.length < 2) {
|
||||
this._currentSelectionState = new Set(
|
||||
this.selection.selectedElements.map(el => el.id)
|
||||
);
|
||||
|
||||
const a: IVec = [x, y];
|
||||
const b: IVec = [x, y];
|
||||
this._lassoPoints = [a, b];
|
||||
this._lastPoint = b;
|
||||
this._overlay.startPoint = a;
|
||||
this._raf = requestAnimationFrame(this._loop);
|
||||
this.surfaceComponent.renderer.addOverlay(this._overlay);
|
||||
} else {
|
||||
const firstPoint = this._lassoPoints[0];
|
||||
const lastPoint = this._lastPoint;
|
||||
const dx = lastPoint[0] - firstPoint[0];
|
||||
const dy = lastPoint[1] - firstPoint[1];
|
||||
if (Vec.len2([dx, dy]) < 20 ** 2) {
|
||||
this._updateSelection(e);
|
||||
|
||||
return this._reset();
|
||||
}
|
||||
|
||||
this._lastPoint = [x, y];
|
||||
this._lassoPoints.push(this._lastPoint);
|
||||
}
|
||||
}
|
||||
|
||||
override pointerMove(e: PointerEventState): void {
|
||||
if (this.activatedOption.mode !== LassoMode.Polygonal || !this._isSelecting)
|
||||
return;
|
||||
|
||||
const lastPoint = this._lastPoint;
|
||||
const [x, y] = this.toModelCoord(e.point);
|
||||
if (lastPoint) {
|
||||
lastPoint[0] = x;
|
||||
lastPoint[1] = y;
|
||||
}
|
||||
this._updateSelection(e);
|
||||
}
|
||||
}
|
||||
|
||||
declare module '@blocksuite/std/gfx' {
|
||||
interface GfxToolsMap {
|
||||
lasso: LassoTool;
|
||||
}
|
||||
|
||||
interface GfxToolsOption {
|
||||
lasso: LassoToolOption;
|
||||
}
|
||||
}
|
||||
@@ -1,138 +0,0 @@
|
||||
import { createLitPortal } from '@blocksuite/affine-components/portal';
|
||||
import type {
|
||||
EditorIconButton,
|
||||
MenuItemGroup,
|
||||
} from '@blocksuite/affine-components/toolbar';
|
||||
import { renderGroups } from '@blocksuite/affine-components/toolbar';
|
||||
import { noop } from '@blocksuite/global/utils';
|
||||
import { MoreVerticalIcon } from '@blocksuite/icons/lit';
|
||||
import { flip, offset } from '@floating-ui/dom';
|
||||
import { html, LitElement } from 'lit';
|
||||
import { property, query, state } from 'lit/decorators.js';
|
||||
import { styleMap } from 'lit/directives/style-map.js';
|
||||
|
||||
import type { ImageToolbarContext } from '../context.js';
|
||||
import { styles } from '../styles.js';
|
||||
|
||||
export class AffineImageToolbar extends LitElement {
|
||||
static override styles = styles;
|
||||
|
||||
private _currentOpenMenu: AbortController | null = null;
|
||||
|
||||
private _popMenuAbortController: AbortController | null = null;
|
||||
|
||||
closeCurrentMenu = () => {
|
||||
if (this._currentOpenMenu && !this._currentOpenMenu.signal.aborted) {
|
||||
this._currentOpenMenu.abort();
|
||||
this._currentOpenMenu = null;
|
||||
}
|
||||
};
|
||||
|
||||
private _clearPopMenu() {
|
||||
if (this._popMenuAbortController) {
|
||||
this._popMenuAbortController.abort();
|
||||
this._popMenuAbortController = null;
|
||||
}
|
||||
}
|
||||
|
||||
private _toggleMoreMenu() {
|
||||
// If the menu we're trying to open is already open, return
|
||||
if (
|
||||
this._currentOpenMenu &&
|
||||
!this._currentOpenMenu.signal.aborted &&
|
||||
this._currentOpenMenu === this._popMenuAbortController
|
||||
) {
|
||||
this.closeCurrentMenu();
|
||||
this._moreMenuOpen = false;
|
||||
return;
|
||||
}
|
||||
|
||||
this.closeCurrentMenu();
|
||||
this._popMenuAbortController = new AbortController();
|
||||
this._popMenuAbortController.signal.addEventListener('abort', () => {
|
||||
this._moreMenuOpen = false;
|
||||
this.onActiveStatusChange(false);
|
||||
});
|
||||
this.onActiveStatusChange(true);
|
||||
|
||||
this._currentOpenMenu = this._popMenuAbortController;
|
||||
|
||||
if (!this._moreButton) {
|
||||
return;
|
||||
}
|
||||
|
||||
createLitPortal({
|
||||
template: html`
|
||||
<editor-menu-content
|
||||
data-show
|
||||
class="image-more-popup-menu"
|
||||
style=${styleMap({
|
||||
'--content-padding': '8px',
|
||||
'--packed-height': '4px',
|
||||
})}
|
||||
>
|
||||
<div data-size="large" data-orientation="vertical">
|
||||
${renderGroups(this.moreGroups, this.context)}
|
||||
</div>
|
||||
</editor-menu-content>
|
||||
`,
|
||||
container: this.context.host,
|
||||
// stacking-context(editor-host)
|
||||
portalStyles: {
|
||||
zIndex: 'var(--affine-z-index-popover)',
|
||||
},
|
||||
computePosition: {
|
||||
referenceElement: this._moreButton,
|
||||
placement: 'bottom-start',
|
||||
middleware: [flip(), offset(4)],
|
||||
autoUpdate: { animationFrame: true },
|
||||
},
|
||||
abortController: this._popMenuAbortController,
|
||||
closeOnClickAway: true,
|
||||
});
|
||||
this._moreMenuOpen = true;
|
||||
}
|
||||
|
||||
override disconnectedCallback() {
|
||||
super.disconnectedCallback();
|
||||
this.closeCurrentMenu();
|
||||
this._clearPopMenu();
|
||||
}
|
||||
|
||||
override render() {
|
||||
return html`
|
||||
<editor-toolbar class="affine-image-toolbar-container" data-without-bg>
|
||||
${renderGroups(this.primaryGroups, this.context)}
|
||||
<editor-icon-button
|
||||
class="image-toolbar-button more"
|
||||
aria-label="More"
|
||||
.tooltip=${'More'}
|
||||
.tooltipOffset=${4}
|
||||
.showTooltip=${!this._moreMenuOpen}
|
||||
.iconSize=${'20px'}
|
||||
@click=${() => this._toggleMoreMenu()}
|
||||
>
|
||||
${MoreVerticalIcon()}
|
||||
</editor-icon-button>
|
||||
</editor-toolbar>
|
||||
`;
|
||||
}
|
||||
|
||||
@query('editor-icon-button.more')
|
||||
private accessor _moreButton!: EditorIconButton;
|
||||
|
||||
@state()
|
||||
private accessor _moreMenuOpen = false;
|
||||
|
||||
@property({ attribute: false })
|
||||
accessor context!: ImageToolbarContext;
|
||||
|
||||
@property({ attribute: false })
|
||||
accessor moreGroups!: MenuItemGroup<ImageToolbarContext>[];
|
||||
|
||||
@property({ attribute: false })
|
||||
accessor onActiveStatusChange: (active: boolean) => void = noop;
|
||||
|
||||
@property({ attribute: false })
|
||||
accessor primaryGroups!: MenuItemGroup<ImageToolbarContext>[];
|
||||
}
|
||||
@@ -1,144 +0,0 @@
|
||||
import {
|
||||
CaptionIcon,
|
||||
CopyIcon,
|
||||
DeleteIcon,
|
||||
DownloadIcon,
|
||||
} from '@blocksuite/affine-components/icons';
|
||||
import type { MenuItemGroup } from '@blocksuite/affine-components/toolbar';
|
||||
import { BookmarkIcon, DuplicateIcon } from '@blocksuite/icons/lit';
|
||||
import { html } from 'lit';
|
||||
import { ifDefined } from 'lit/directives/if-defined.js';
|
||||
|
||||
import type { ImageToolbarContext } from './context.js';
|
||||
import { duplicate } from './utils.js';
|
||||
|
||||
export const PRIMARY_GROUPS: MenuItemGroup<ImageToolbarContext>[] = [
|
||||
{
|
||||
type: 'primary',
|
||||
items: [
|
||||
{
|
||||
type: 'download',
|
||||
label: 'Download',
|
||||
icon: DownloadIcon,
|
||||
generate: ({ blockComponent }) => {
|
||||
return {
|
||||
action: () => {
|
||||
blockComponent.download();
|
||||
},
|
||||
render: item => html`
|
||||
<editor-icon-button
|
||||
class="image-toolbar-button download"
|
||||
aria-label=${ifDefined(item.label)}
|
||||
.tooltip=${item.label}
|
||||
.tooltipOffset=${4}
|
||||
@click=${(e: MouseEvent) => {
|
||||
e.stopPropagation();
|
||||
item.action();
|
||||
}}
|
||||
>
|
||||
${item.icon}
|
||||
</editor-icon-button>
|
||||
`,
|
||||
};
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'caption',
|
||||
label: 'Caption',
|
||||
icon: CaptionIcon,
|
||||
when: ({ doc }) => !doc.readonly,
|
||||
generate: ({ blockComponent }) => {
|
||||
return {
|
||||
action: () => {
|
||||
blockComponent.captionEditor?.show();
|
||||
},
|
||||
render: item => html`
|
||||
<editor-icon-button
|
||||
class="image-toolbar-button caption"
|
||||
aria-label=${ifDefined(item.label)}
|
||||
.tooltip=${item.label}
|
||||
.tooltipOffset=${4}
|
||||
@click=${(e: MouseEvent) => {
|
||||
e.stopPropagation();
|
||||
item.action();
|
||||
}}
|
||||
>
|
||||
${item.icon}
|
||||
</editor-icon-button>
|
||||
`,
|
||||
};
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
// Clipboard Group
|
||||
export const clipboardGroup: MenuItemGroup<ImageToolbarContext> = {
|
||||
type: 'clipboard',
|
||||
items: [
|
||||
{
|
||||
type: 'copy',
|
||||
label: 'Copy',
|
||||
icon: CopyIcon,
|
||||
action: ({ blockComponent, close }) => {
|
||||
blockComponent.copy();
|
||||
close();
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'duplicate',
|
||||
label: 'Duplicate',
|
||||
icon: DuplicateIcon(),
|
||||
when: ({ doc }) => !doc.readonly,
|
||||
action: ({ blockComponent, abortController }) => {
|
||||
duplicate(blockComponent, abortController);
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
// Conversions Group
|
||||
export const conversionsGroup: MenuItemGroup<ImageToolbarContext> = {
|
||||
type: 'conversions',
|
||||
items: [
|
||||
{
|
||||
label: 'Turn into card view',
|
||||
type: 'turn-into-card-view',
|
||||
icon: BookmarkIcon(),
|
||||
when: ({ doc, blockComponent }) => {
|
||||
const supportAttachment =
|
||||
doc.schema.flavourSchemaMap.has('affine:attachment');
|
||||
const readonly = doc.readonly;
|
||||
return supportAttachment && !readonly && !!blockComponent.blob;
|
||||
},
|
||||
action: ({ blockComponent, close }) => {
|
||||
blockComponent.convertToCardView();
|
||||
close();
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
// Delete Group
|
||||
export const deleteGroup: MenuItemGroup<ImageToolbarContext> = {
|
||||
type: 'delete',
|
||||
items: [
|
||||
{
|
||||
type: 'delete',
|
||||
label: 'Delete',
|
||||
icon: DeleteIcon,
|
||||
when: ({ doc }) => !doc.readonly,
|
||||
action: ({ doc, blockComponent, close }) => {
|
||||
doc.deleteBlock(blockComponent.model);
|
||||
close();
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export const MORE_GROUPS: MenuItemGroup<ImageToolbarContext>[] = [
|
||||
clipboardGroup,
|
||||
conversionsGroup,
|
||||
deleteGroup,
|
||||
];
|
||||
@@ -1,43 +0,0 @@
|
||||
import type { ImageBlockComponent } from '@blocksuite/affine-block-image';
|
||||
import { MenuContext } from '@blocksuite/affine-components/toolbar';
|
||||
|
||||
export class ImageToolbarContext extends MenuContext {
|
||||
override close = () => {
|
||||
this.abortController.abort();
|
||||
};
|
||||
|
||||
get doc() {
|
||||
return this.blockComponent.doc;
|
||||
}
|
||||
|
||||
get host() {
|
||||
return this.blockComponent.host;
|
||||
}
|
||||
|
||||
get selectedBlockModels() {
|
||||
return [this.blockComponent.model];
|
||||
}
|
||||
|
||||
get std() {
|
||||
return this.blockComponent.std;
|
||||
}
|
||||
|
||||
constructor(
|
||||
public blockComponent: ImageBlockComponent,
|
||||
public abortController: AbortController
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
isEmpty() {
|
||||
return false;
|
||||
}
|
||||
|
||||
isMultiple() {
|
||||
return false;
|
||||
}
|
||||
|
||||
isSingle() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,173 +0,0 @@
|
||||
import type { ImageBlockComponent } from '@blocksuite/affine-block-image';
|
||||
import { HoverController } from '@blocksuite/affine-components/hover';
|
||||
import type {
|
||||
AdvancedMenuItem,
|
||||
MenuItemGroup,
|
||||
} from '@blocksuite/affine-components/toolbar';
|
||||
import {
|
||||
cloneGroups,
|
||||
getMoreMenuConfig,
|
||||
} from '@blocksuite/affine-components/toolbar';
|
||||
import type { ImageBlockModel } from '@blocksuite/affine-model';
|
||||
import { PAGE_HEADER_HEIGHT } from '@blocksuite/affine-shared/consts';
|
||||
import {
|
||||
BlockSelection,
|
||||
TextSelection,
|
||||
WidgetComponent,
|
||||
} from '@blocksuite/std';
|
||||
import { limitShift, shift } from '@floating-ui/dom';
|
||||
import { html } from 'lit';
|
||||
|
||||
import { MORE_GROUPS, PRIMARY_GROUPS } from './config.js';
|
||||
import { ImageToolbarContext } from './context.js';
|
||||
|
||||
export const AFFINE_IMAGE_TOOLBAR_WIDGET = 'affine-image-toolbar-widget';
|
||||
|
||||
export class AffineImageToolbarWidget extends WidgetComponent<
|
||||
ImageBlockModel,
|
||||
ImageBlockComponent
|
||||
> {
|
||||
private _hoverController: HoverController | null = null;
|
||||
|
||||
private _isActivated = false;
|
||||
|
||||
private readonly _setHoverController = () => {
|
||||
this._hoverController = null;
|
||||
this._hoverController = new HoverController(
|
||||
this,
|
||||
({ abortController }) => {
|
||||
const imageBlock = this.block;
|
||||
if (!imageBlock) {
|
||||
return null;
|
||||
}
|
||||
const selection = this.host.selection;
|
||||
|
||||
const textSelection = selection.find(TextSelection);
|
||||
if (
|
||||
!!textSelection &&
|
||||
(!!textSelection.to || !!textSelection.from.length)
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const blockSelections = selection.filter(BlockSelection);
|
||||
if (
|
||||
blockSelections.length > 1 ||
|
||||
(blockSelections.length === 1 &&
|
||||
blockSelections[0].blockId !== imageBlock.blockId)
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const imageContainer =
|
||||
imageBlock.resizableImg ?? imageBlock.fallbackCard;
|
||||
if (!imageContainer) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const context = new ImageToolbarContext(imageBlock, abortController);
|
||||
|
||||
return {
|
||||
template: html`<affine-image-toolbar
|
||||
.context=${context}
|
||||
.primaryGroups=${this.primaryGroups}
|
||||
.moreGroups=${this.moreGroups}
|
||||
.onActiveStatusChange=${(active: boolean) => {
|
||||
this._isActivated = active;
|
||||
if (!active && !this._hoverController?.isHovering) {
|
||||
this._hoverController?.abort();
|
||||
}
|
||||
}}
|
||||
></affine-image-toolbar>`,
|
||||
container: this.block,
|
||||
// stacking-context(editor-host)
|
||||
portalStyles: {
|
||||
zIndex: 'var(--affine-z-index-popover)',
|
||||
},
|
||||
computePosition: {
|
||||
referenceElement: imageContainer,
|
||||
placement: 'right-start',
|
||||
middleware: [
|
||||
shift({
|
||||
crossAxis: true,
|
||||
padding: {
|
||||
top: PAGE_HEADER_HEIGHT + 12,
|
||||
bottom: 12,
|
||||
right: 12,
|
||||
},
|
||||
limiter: limitShift(),
|
||||
}),
|
||||
],
|
||||
autoUpdate: true,
|
||||
},
|
||||
};
|
||||
},
|
||||
{ allowMultiple: true }
|
||||
);
|
||||
|
||||
const imageBlock = this.block;
|
||||
if (!imageBlock) {
|
||||
return;
|
||||
}
|
||||
this._hoverController.setReference(imageBlock);
|
||||
this._hoverController.onAbort = () => {
|
||||
// If the more menu is opened, don't close it.
|
||||
if (this._isActivated) return;
|
||||
this._hoverController?.abort();
|
||||
return;
|
||||
};
|
||||
};
|
||||
|
||||
addMoreItems = (
|
||||
items: AdvancedMenuItem<ImageToolbarContext>[],
|
||||
index?: number,
|
||||
type?: string
|
||||
) => {
|
||||
let group;
|
||||
if (type) {
|
||||
group = this.moreGroups.find(g => g.type === type);
|
||||
}
|
||||
if (!group) {
|
||||
group = this.moreGroups[0];
|
||||
}
|
||||
|
||||
if (index === undefined) {
|
||||
group.items.push(...items);
|
||||
return this;
|
||||
}
|
||||
|
||||
group.items.splice(index, 0, ...items);
|
||||
return this;
|
||||
};
|
||||
|
||||
addPrimaryItems = (
|
||||
items: AdvancedMenuItem<ImageToolbarContext>[],
|
||||
index?: number
|
||||
) => {
|
||||
if (index === undefined) {
|
||||
this.primaryGroups[0].items.push(...items);
|
||||
return this;
|
||||
}
|
||||
|
||||
this.primaryGroups[0].items.splice(index, 0, ...items);
|
||||
return this;
|
||||
};
|
||||
|
||||
/*
|
||||
* Caches the more menu items.
|
||||
* Currently only supports configuring more menu.
|
||||
*/
|
||||
moreGroups: MenuItemGroup<ImageToolbarContext>[] = cloneGroups(MORE_GROUPS);
|
||||
|
||||
primaryGroups: MenuItemGroup<ImageToolbarContext>[] =
|
||||
cloneGroups(PRIMARY_GROUPS);
|
||||
|
||||
override firstUpdated() {
|
||||
if (this.doc.getParent(this.model.id)?.flavour === 'affine:surface') {
|
||||
return;
|
||||
}
|
||||
|
||||
this.moreGroups = getMoreMenuConfig(this.std).configure(this.moreGroups);
|
||||
this._setHoverController();
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
import { css } from 'lit';
|
||||
|
||||
export const styles = css`
|
||||
:host {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
z-index: var(--affine-z-index-popover);
|
||||
}
|
||||
|
||||
.affine-image-toolbar-container {
|
||||
height: 24px;
|
||||
gap: 4px;
|
||||
padding: 4px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.image-toolbar-button {
|
||||
color: var(--affine-icon-color);
|
||||
background-color: var(--affine-background-primary-color);
|
||||
box-shadow: var(--affine-shadow-1);
|
||||
border-radius: 4px;
|
||||
}
|
||||
`;
|
||||
@@ -1,56 +0,0 @@
|
||||
import type { ImageBlockComponent } from '@blocksuite/affine-block-image';
|
||||
import {
|
||||
getBlockProps,
|
||||
isInsidePageEditor,
|
||||
} from '@blocksuite/affine-shared/utils';
|
||||
import { BlockSelection } from '@blocksuite/std';
|
||||
|
||||
export function duplicate(
|
||||
block: ImageBlockComponent,
|
||||
abortController?: AbortController
|
||||
) {
|
||||
const model = block.model;
|
||||
const blockProps = getBlockProps(model);
|
||||
const {
|
||||
width: _width,
|
||||
height: _height,
|
||||
xywh: _xywh,
|
||||
rotate: _rotate,
|
||||
zIndex: _zIndex,
|
||||
...duplicateProps
|
||||
} = blockProps;
|
||||
|
||||
const { doc } = model;
|
||||
const parent = doc.getParent(model);
|
||||
if (!parent) {
|
||||
console.error(`Parent not found for block(${model.flavour}) ${model.id}`);
|
||||
return;
|
||||
}
|
||||
|
||||
const index = parent?.children.indexOf(model);
|
||||
const duplicateId = doc.addBlock(
|
||||
model.flavour,
|
||||
duplicateProps,
|
||||
parent,
|
||||
index + 1
|
||||
);
|
||||
abortController?.abort();
|
||||
|
||||
const editorHost = block.host;
|
||||
editorHost.updateComplete
|
||||
.then(() => {
|
||||
const { selection } = editorHost;
|
||||
selection.setGroup('note', [
|
||||
selection.create(BlockSelection, {
|
||||
blockId: duplicateId,
|
||||
}),
|
||||
]);
|
||||
if (isInsidePageEditor(editorHost)) {
|
||||
const duplicateElement = editorHost.view.getBlock(duplicateId);
|
||||
if (duplicateElement) {
|
||||
duplicateElement.scrollIntoView(true);
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(console.error);
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
{
|
||||
"extends": "../../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"rootDir": "./src",
|
||||
"outDir": "./dist",
|
||||
"tsBuildInfoFile": "./dist/tsconfig.tsbuildinfo"
|
||||
},
|
||||
"include": ["./src"],
|
||||
"references": [
|
||||
{ "path": "../block-attachment" },
|
||||
{ "path": "../block-bookmark" },
|
||||
{ "path": "../block-data-view" },
|
||||
{ "path": "../block-database" },
|
||||
{ "path": "../block-edgeless-text" },
|
||||
{ "path": "../block-embed" },
|
||||
{ "path": "../block-frame" },
|
||||
{ "path": "../block-image" },
|
||||
{ "path": "../block-latex" },
|
||||
{ "path": "../block-list" },
|
||||
{ "path": "../block-note" },
|
||||
{ "path": "../block-paragraph" },
|
||||
{ "path": "../block-surface" },
|
||||
{ "path": "../block-surface-ref" },
|
||||
{ "path": "../block-table" },
|
||||
{ "path": "../../components" },
|
||||
{ "path": "../../fragments/fragment-doc-title" },
|
||||
{ "path": "../../gfx/brush" },
|
||||
{ "path": "../../gfx/connector" },
|
||||
{ "path": "../../gfx/group" },
|
||||
{ "path": "../../gfx/mindmap" },
|
||||
{ "path": "../../gfx/note" },
|
||||
{ "path": "../../gfx/shape" },
|
||||
{ "path": "../../gfx/text" },
|
||||
{ "path": "../../inlines/latex" },
|
||||
{ "path": "../../inlines/link" },
|
||||
{ "path": "../../inlines/preset" },
|
||||
{ "path": "../../inlines/reference" },
|
||||
{ "path": "../../model" },
|
||||
{ "path": "../../rich-text" },
|
||||
{ "path": "../../shared" },
|
||||
{ "path": "../../widgets/widget-drag-handle" },
|
||||
{ "path": "../../widgets/widget-edgeless-auto-connect" },
|
||||
{ "path": "../../widgets/widget-edgeless-toolbar" },
|
||||
{ "path": "../../widgets/widget-frame-title" },
|
||||
{ "path": "../../widgets/widget-remote-selection" },
|
||||
{ "path": "../../widgets/widget-scroll-anchoring" },
|
||||
{ "path": "../../widgets/widget-slash-menu" },
|
||||
{ "path": "../../widgets/widget-toolbar" },
|
||||
{ "path": "../../data-view" },
|
||||
{ "path": "../../../framework/global" },
|
||||
{ "path": "../../../framework/std" },
|
||||
{ "path": "../../../framework/store" }
|
||||
]
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
import type { SurfaceRefBlockModel } from '@blocksuite/affine-model';
|
||||
import { BlockComponent } from '@blocksuite/std';
|
||||
import { nothing } from 'lit';
|
||||
|
||||
export class EdgelessSurfaceRefBlockComponent extends BlockComponent<SurfaceRefBlockModel> {
|
||||
override render() {
|
||||
return nothing;
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'affine-edgeless-surface-ref': EdgelessSurfaceRefBlockComponent;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
export {
|
||||
EdgelessSurfaceBlockAdapterExtensions,
|
||||
SurfaceBlockAdapterExtensions,
|
||||
} from './extension.js';
|
||||
@@ -1,15 +0,0 @@
|
||||
import { brushToMarkdownAdapterMatcher } from './brush.js';
|
||||
import { connectorToMarkdownAdapterMatcher } from './connector.js';
|
||||
import { groupToMarkdownAdapterMatcher } from './group.js';
|
||||
import { mindmapToMarkdownAdapterMatcher } from './mindmap.js';
|
||||
import { shapeToMarkdownAdapterMatcher } from './shape.js';
|
||||
import { textToMarkdownAdapterMatcher } from './text.js';
|
||||
|
||||
export const elementToMarkdownAdapterMatchers = [
|
||||
groupToMarkdownAdapterMatcher,
|
||||
shapeToMarkdownAdapterMatcher,
|
||||
connectorToMarkdownAdapterMatcher,
|
||||
brushToMarkdownAdapterMatcher,
|
||||
textToMarkdownAdapterMatcher,
|
||||
mindmapToMarkdownAdapterMatcher,
|
||||
];
|
||||
@@ -1,15 +0,0 @@
|
||||
import { brushToPlainTextAdapterMatcher } from './brush.js';
|
||||
import { connectorToPlainTextAdapterMatcher } from './connector.js';
|
||||
import { groupToPlainTextAdapterMatcher } from './group.js';
|
||||
import { mindmapToPlainTextAdapterMatcher } from './mindmap.js';
|
||||
import { shapeToPlainTextAdapterMatcher } from './shape.js';
|
||||
import { textToPlainTextAdapterMatcher } from './text.js';
|
||||
|
||||
export const elementToPlainTextAdapterMatchers = [
|
||||
groupToPlainTextAdapterMatcher,
|
||||
shapeToPlainTextAdapterMatcher,
|
||||
connectorToPlainTextAdapterMatcher,
|
||||
brushToPlainTextAdapterMatcher,
|
||||
textToPlainTextAdapterMatcher,
|
||||
mindmapToPlainTextAdapterMatcher,
|
||||
];
|
||||
@@ -1,162 +0,0 @@
|
||||
import type { DeltaInsert } from '@blocksuite/store';
|
||||
|
||||
import type { MindMapTreeNode } from '../types/mindmap.js';
|
||||
import { buildMindMapTree } from './mindmap.js';
|
||||
|
||||
export function getShapeType(elementModel: Record<string, unknown>): string {
|
||||
let shapeType = '';
|
||||
if (elementModel.type !== 'shape') {
|
||||
return shapeType;
|
||||
}
|
||||
|
||||
if (
|
||||
'shapeType' in elementModel &&
|
||||
typeof elementModel.shapeType === 'string'
|
||||
) {
|
||||
shapeType = elementModel.shapeType;
|
||||
}
|
||||
return shapeType;
|
||||
}
|
||||
|
||||
export function getShapeText(elementModel: Record<string, unknown>): string {
|
||||
let text = '';
|
||||
if (elementModel.type !== 'shape') {
|
||||
return text;
|
||||
}
|
||||
|
||||
if (
|
||||
'text' in elementModel &&
|
||||
typeof elementModel.text === 'object' &&
|
||||
elementModel.text
|
||||
) {
|
||||
let delta: DeltaInsert[] = [];
|
||||
if ('delta' in elementModel.text) {
|
||||
delta = elementModel.text.delta as DeltaInsert[];
|
||||
}
|
||||
text = delta.map(d => d.insert).join('');
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
export function getConnectorText(
|
||||
elementModel: Record<string, unknown>
|
||||
): string {
|
||||
let text = '';
|
||||
if (elementModel.type !== 'connector') {
|
||||
return text;
|
||||
}
|
||||
|
||||
if (
|
||||
'text' in elementModel &&
|
||||
typeof elementModel.text === 'object' &&
|
||||
elementModel.text
|
||||
) {
|
||||
let delta: DeltaInsert[] = [];
|
||||
if ('delta' in elementModel.text) {
|
||||
delta = elementModel.text.delta as DeltaInsert[];
|
||||
}
|
||||
text = delta.map(d => d.insert).join('');
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
export function getGroupTitle(elementModel: Record<string, unknown>): string {
|
||||
let title = '';
|
||||
if (elementModel.type !== 'group') {
|
||||
return title;
|
||||
}
|
||||
|
||||
if (
|
||||
'title' in elementModel &&
|
||||
typeof elementModel.title === 'object' &&
|
||||
elementModel.title
|
||||
) {
|
||||
let delta: DeltaInsert[] = [];
|
||||
if ('delta' in elementModel.title) {
|
||||
delta = elementModel.title.delta as DeltaInsert[];
|
||||
}
|
||||
title = delta.map(d => d.insert).join('');
|
||||
}
|
||||
return title;
|
||||
}
|
||||
|
||||
export function getTextElementText(
|
||||
elementModel: Record<string, unknown>
|
||||
): string {
|
||||
let text = '';
|
||||
if (elementModel.type !== 'text') {
|
||||
return text;
|
||||
}
|
||||
if (
|
||||
'text' in elementModel &&
|
||||
typeof elementModel.text === 'object' &&
|
||||
elementModel.text
|
||||
) {
|
||||
let delta: DeltaInsert[] = [];
|
||||
if ('delta' in elementModel.text) {
|
||||
delta = elementModel.text.delta as DeltaInsert[];
|
||||
}
|
||||
text = delta.map(d => d.insert).join('');
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
/**
|
||||
* traverse the mindMapTree and construct the content string
|
||||
* like:
|
||||
* - Root
|
||||
* - Child 1
|
||||
* - Child 1.1
|
||||
* - Child 1.2
|
||||
* - Child 2
|
||||
* - Child 2.1
|
||||
* - Child 2.2
|
||||
* - Child 3
|
||||
* - Child 3.1
|
||||
* - Child 3.2
|
||||
* @param elementModel - the mindmap element model
|
||||
* @param elements - the elements map
|
||||
* @returns the mindmap tree text
|
||||
*/
|
||||
export function getMindMapTreeText(
|
||||
elementModel: Record<string, unknown>,
|
||||
elements: Record<string, Record<string, unknown>>,
|
||||
options: {
|
||||
prefix: string;
|
||||
repeat: number;
|
||||
} = {
|
||||
prefix: ' ',
|
||||
repeat: 2,
|
||||
}
|
||||
): string {
|
||||
let mindMapContent = '';
|
||||
if (elementModel.type !== 'mindmap') {
|
||||
return mindMapContent;
|
||||
}
|
||||
|
||||
const mindMapTree = buildMindMapTree(elementModel);
|
||||
if (!mindMapTree) {
|
||||
return mindMapContent;
|
||||
}
|
||||
|
||||
let layer = 0;
|
||||
const traverseMindMapTree = (
|
||||
node: MindMapTreeNode,
|
||||
prefix: string,
|
||||
repeat: number
|
||||
) => {
|
||||
const shapeElement = elements[node.id as string];
|
||||
const shapeText = getShapeText(shapeElement);
|
||||
if (shapeElement) {
|
||||
mindMapContent += `${prefix.repeat(layer * repeat)}- ${shapeText}\n`;
|
||||
}
|
||||
node.children.forEach(child => {
|
||||
layer++;
|
||||
traverseMindMapTree(child, prefix, repeat);
|
||||
layer--;
|
||||
});
|
||||
};
|
||||
traverseMindMapTree(mindMapTree, options.prefix, options.repeat);
|
||||
|
||||
return mindMapContent;
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
import type { IBound } from '@blocksuite/global/gfx';
|
||||
import type { GfxPrimitiveElementModel } from '@blocksuite/std/gfx';
|
||||
|
||||
import type { RoughCanvas } from '../../index.js';
|
||||
import type { CanvasRenderer } from '../canvas-renderer.js';
|
||||
import { brush } from './brush/index.js';
|
||||
import { connector } from './connector/index.js';
|
||||
import { group } from './group/index.js';
|
||||
import { highlighter } from './highlighter/index.js';
|
||||
import { mindmap } from './mindmap.js';
|
||||
import { shape } from './shape/index.js';
|
||||
import { text } from './text/index.js';
|
||||
export { normalizeShapeBound } from './shape/utils.js';
|
||||
|
||||
export type ElementRenderer<
|
||||
T extends GfxPrimitiveElementModel = GfxPrimitiveElementModel,
|
||||
> = (
|
||||
model: T,
|
||||
ctx: CanvasRenderingContext2D,
|
||||
matrix: DOMMatrix,
|
||||
renderer: CanvasRenderer,
|
||||
rc: RoughCanvas,
|
||||
viewportBound: IBound
|
||||
) => void;
|
||||
|
||||
export const elementRenderers = {
|
||||
brush,
|
||||
highlighter,
|
||||
connector,
|
||||
group,
|
||||
shape,
|
||||
text,
|
||||
mindmap,
|
||||
} as Record<string, ElementRenderer<any>>;
|
||||
@@ -1,37 +0,0 @@
|
||||
import { BlockService } from '@blocksuite/std';
|
||||
import { GfxControllerIdentifier } from '@blocksuite/std/gfx';
|
||||
|
||||
import { type SurfaceBlockModel, SurfaceBlockSchema } from './surface-model.js';
|
||||
import { getSurfaceBlock } from './utils/get-surface-block.js';
|
||||
|
||||
export class SurfaceBlockService extends BlockService {
|
||||
static override readonly flavour = SurfaceBlockSchema.model.flavour;
|
||||
|
||||
surface!: SurfaceBlockModel;
|
||||
|
||||
get layer() {
|
||||
return this.std.get(GfxControllerIdentifier).layer;
|
||||
}
|
||||
|
||||
override mounted(): void {
|
||||
super.mounted();
|
||||
|
||||
const surface = getSurfaceBlock(this.doc);
|
||||
|
||||
// FIXME: BS-2271
|
||||
this.surface = surface!;
|
||||
|
||||
if (!this.surface) {
|
||||
const disposable = this.doc.slots.blockUpdated.subscribe(payload => {
|
||||
if (payload.flavour === 'affine:surface') {
|
||||
disposable.unsubscribe();
|
||||
const surface = this.doc.getModelById(
|
||||
payload.id
|
||||
) as SurfaceBlockModel | null;
|
||||
if (!surface) return;
|
||||
this.surface = surface;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,7 @@
|
||||
"@blocksuite/affine-shared": "workspace:*",
|
||||
"@blocksuite/affine-widget-slash-menu": "workspace:*",
|
||||
"@blocksuite/global": "workspace:*",
|
||||
"@blocksuite/icons": "^2.2.8",
|
||||
"@blocksuite/icons": "^2.2.10",
|
||||
"@blocksuite/std": "workspace:*",
|
||||
"@blocksuite/store": "workspace:*",
|
||||
"@lit/context": "^1.1.2",
|
||||
@@ -39,5 +39,5 @@
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.20.0"
|
||||
"version": "0.21.0"
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
import {
|
||||
type InsertedLinkType,
|
||||
insertEmbedIframeWithUrlCommand,
|
||||
insertEmbedLinkedDocCommand,
|
||||
type LinkableFlavour,
|
||||
} from '@blocksuite/affine-block-embed';
|
||||
import { QuickSearchProvider } from '@blocksuite/affine-shared/services';
|
||||
import type { Command } from '@blocksuite/std';
|
||||
|
||||
import { insertBookmarkCommand } from './insert-bookmark';
|
||||
|
||||
export const insertLinkByQuickSearchCommand: Command<
|
||||
{},
|
||||
{ insertedLinkType: Promise<InsertedLinkType> }
|
||||
> = (ctx, next) => {
|
||||
const { std } = ctx;
|
||||
const quickSearchService = std.getOptional(QuickSearchProvider);
|
||||
if (!quickSearchService) {
|
||||
next();
|
||||
return;
|
||||
}
|
||||
|
||||
const insertedLinkType: Promise<InsertedLinkType> = quickSearchService
|
||||
.openQuickSearch()
|
||||
.then(result => {
|
||||
if (!result) return null;
|
||||
|
||||
// add linked doc
|
||||
if ('docId' in result) {
|
||||
std.command.exec(insertEmbedLinkedDocCommand, {
|
||||
docId: result.docId,
|
||||
params: result.params,
|
||||
});
|
||||
return {
|
||||
flavour: 'affine:embed-linked-doc',
|
||||
};
|
||||
}
|
||||
|
||||
// add normal link;
|
||||
if ('externalUrl' in result) {
|
||||
// try to insert embed iframe block first
|
||||
const [success, { flavour }] = std.command
|
||||
.chain()
|
||||
.try(chain => [
|
||||
chain.pipe(insertEmbedIframeWithUrlCommand, {
|
||||
url: result.externalUrl,
|
||||
}),
|
||||
chain.pipe(insertBookmarkCommand, { url: result.externalUrl }),
|
||||
])
|
||||
.run();
|
||||
if (!success || !flavour) return null;
|
||||
return {
|
||||
flavour: flavour as LinkableFlavour,
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
});
|
||||
|
||||
next({ insertedLinkType });
|
||||
};
|
||||
@@ -2,7 +2,7 @@ import { getEmbedCardIcons } from '@blocksuite/affine-block-embed';
|
||||
import { WebIcon16 } from '@blocksuite/affine-components/icons';
|
||||
import { ThemeProvider } from '@blocksuite/affine-shared/services';
|
||||
import { getHostName } from '@blocksuite/affine-shared/utils';
|
||||
import { WithDisposable } from '@blocksuite/global/lit';
|
||||
import { SignalWatcher, WithDisposable } from '@blocksuite/global/lit';
|
||||
import { OpenInNewIcon } from '@blocksuite/icons/lit';
|
||||
import { BlockSelection, ShadowlessElement } from '@blocksuite/std';
|
||||
import { html } from 'lit';
|
||||
@@ -12,7 +12,9 @@ import { classMap } from 'lit/directives/class-map.js';
|
||||
import type { BookmarkBlockComponent } from '../bookmark-block.js';
|
||||
import { styles } from '../styles.js';
|
||||
|
||||
export class BookmarkCard extends WithDisposable(ShadowlessElement) {
|
||||
export class BookmarkCard extends SignalWatcher(
|
||||
WithDisposable(ShadowlessElement)
|
||||
) {
|
||||
static override styles = styles;
|
||||
|
||||
private _handleClick(event: MouseEvent) {
|
||||
@@ -125,11 +127,11 @@ export class BookmarkCard extends WithDisposable(ShadowlessElement) {
|
||||
<div class="affine-bookmark-content-description">
|
||||
${descriptionText}
|
||||
</div>
|
||||
<div
|
||||
class="affine-bookmark-content-url-wrapper"
|
||||
@click=${this.bookmark.open}
|
||||
>
|
||||
<div class="affine-bookmark-content-url">
|
||||
<div class="affine-bookmark-content-url-wrapper">
|
||||
<div
|
||||
class="affine-bookmark-content-url"
|
||||
@click=${this.bookmark.open}
|
||||
>
|
||||
<span>${getHostName(url)}</span>
|
||||
<div class="affine-bookmark-content-url-icon">
|
||||
${OpenInNewIcon({ width: '12', height: '12' })}
|
||||
@@ -0,0 +1,29 @@
|
||||
import { EdgelessClipboardConfig } from '@blocksuite/affine-block-surface';
|
||||
import { type BlockSnapshot } from '@blocksuite/store';
|
||||
|
||||
export class EdgelessClipboardBookmarkConfig extends EdgelessClipboardConfig {
|
||||
static override readonly key = 'affine:bookmark';
|
||||
|
||||
override createBlock(bookmark: BlockSnapshot): string | null {
|
||||
if (!this.surface) return null;
|
||||
|
||||
const { xywh, style, url, caption, description, icon, image, title } =
|
||||
bookmark.props;
|
||||
|
||||
const bookmarkId = this.crud.addBlock(
|
||||
'affine:bookmark',
|
||||
{
|
||||
xywh,
|
||||
style,
|
||||
url,
|
||||
caption,
|
||||
description,
|
||||
icon,
|
||||
image,
|
||||
title,
|
||||
},
|
||||
this.surface.model.id
|
||||
);
|
||||
return bookmarkId;
|
||||
}
|
||||
}
|
||||
@@ -4,3 +4,4 @@ export * from './bookmark-spec';
|
||||
export * from './commands';
|
||||
export * from './components';
|
||||
export { BookmarkSlashMenuConfigIdentifier } from './configs/slash-menu';
|
||||
export * from './edgeless-clipboard-config';
|
||||
@@ -26,7 +26,6 @@ export const styles = css`
|
||||
|
||||
.affine-bookmark-content {
|
||||
width: calc(100% - 204px);
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-self: stretch;
|
||||
@@ -7,12 +7,12 @@
|
||||
},
|
||||
"include": ["./src"],
|
||||
"references": [
|
||||
{ "path": "../block-embed" },
|
||||
{ "path": "../block-surface" },
|
||||
{ "path": "../embed" },
|
||||
{ "path": "../surface" },
|
||||
{ "path": "../../components" },
|
||||
{ "path": "../../model" },
|
||||
{ "path": "../../shared" },
|
||||
{ "path": "../../widgets/widget-slash-menu" },
|
||||
{ "path": "../../widgets/slash-menu" },
|
||||
{ "path": "../../../framework/global" },
|
||||
{ "path": "../../../framework/std" },
|
||||
{ "path": "../../../framework/store" }
|
||||
@@ -17,7 +17,7 @@
|
||||
"@blocksuite/affine-shared": "workspace:*",
|
||||
"@blocksuite/affine-widget-slash-menu": "workspace:*",
|
||||
"@blocksuite/global": "workspace:*",
|
||||
"@blocksuite/icons": "^2.2.8",
|
||||
"@blocksuite/icons": "^2.2.10",
|
||||
"@blocksuite/std": "workspace:*",
|
||||
"@blocksuite/store": "workspace:*",
|
||||
"@emoji-mart/data": "^1.2.1",
|
||||
@@ -42,5 +42,5 @@
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.20.0"
|
||||
"version": "0.21.0"
|
||||
}
|
||||
@@ -2,7 +2,7 @@ import { CaptionedBlockComponent } from '@blocksuite/affine-components/caption';
|
||||
import { createLitPortal } from '@blocksuite/affine-components/portal';
|
||||
import { DefaultInlineManagerExtension } from '@blocksuite/affine-inline-preset';
|
||||
import { type CalloutBlockModel } from '@blocksuite/affine-model';
|
||||
import { NOTE_SELECTOR } from '@blocksuite/affine-shared/consts';
|
||||
import { EDGELESS_TOP_CONTENTEDITABLE_SELECTOR } from '@blocksuite/affine-shared/consts';
|
||||
import {
|
||||
DocModeProvider,
|
||||
ThemeProvider,
|
||||
@@ -95,7 +95,9 @@ export class CalloutBlockComponent extends CaptionedBlockComponent<CalloutBlockM
|
||||
|
||||
override get topContenteditableElement() {
|
||||
if (this.std.get(DocModeProvider).getEditorMode() === 'edgeless') {
|
||||
return this.closest<BlockComponent>(NOTE_SELECTOR);
|
||||
return this.closest<BlockComponent>(
|
||||
EDGELESS_TOP_CONTENTEDITABLE_SELECTOR
|
||||
);
|
||||
}
|
||||
return this.rootComponent;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user