refactor: remove unused package desktop (#1815)
2
.vscode/settings.json
vendored
@@ -26,7 +26,7 @@
|
|||||||
"[toml]": {
|
"[toml]": {
|
||||||
"editor.defaultFormatter": "tamasfe.even-better-toml"
|
"editor.defaultFormatter": "tamasfe.even-better-toml"
|
||||||
},
|
},
|
||||||
"rust-analyzer.linkedProjects": ["apps/desktop/src-tauri/Cargo.toml"],
|
"rust-analyzer.linkedProjects": ["packages/octobase-node/Cargo.toml"],
|
||||||
"[typescriptreact]": {
|
"[typescriptreact]": {
|
||||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||||
}
|
}
|
||||||
|
|||||||
3
apps/desktop/.gitignore
vendored
@@ -1,3 +0,0 @@
|
|||||||
# generated assets
|
|
||||||
public/affine-out
|
|
||||||
public/preload
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
# Client App
|
|
||||||
|
|
||||||
AFFiNE App client powered by Tauri.
|
|
||||||
|
|
||||||
## Quick Start
|
|
||||||
|
|
||||||
Please follow the Tauri [getting started guide](https://tauri.app/v1/guides/getting-started/setup/) for environment setup.
|
|
||||||
|
|
||||||
After the environment is ready, start development build:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
yarn tauri dev
|
|
||||||
```
|
|
||||||
|
|
||||||
## Development
|
|
||||||
|
|
||||||
Currently desktop client depends on a rapidly developing rust library "Octobase", we use git-submodule to link it currently.
|
|
||||||
|
|
||||||
We will provide its binary binding soon, to replace the git-submodule, before Octobase become opensource.
|
|
||||||
|
|
||||||
### Scripts
|
|
||||||
|
|
||||||
On this folder:
|
|
||||||
|
|
||||||
- `yarn dev:app` will start a vite server
|
|
||||||
- `yarn build:prerequisite` will link the Octobase and prepare affine dist html and tauri preload script, also will generate ts type from rs. You should run this before start your first development time.
|
|
||||||
|
|
||||||
On project root folder:
|
|
||||||
|
|
||||||
### Recommended IDE Setup
|
|
||||||
|
|
||||||
- [VS Code](https://code.visualstudio.com/) + [Tauri](https://marketplace.visualstudio.com/items?itemName=tauri-apps.tauri-vscode) + [rust-analyzer](https://marketplace.visualstudio.com/items?itemName=rust-lang.rust-analyzer)
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "@affine/client-app",
|
|
||||||
"private": true,
|
|
||||||
"version": "0.0.0",
|
|
||||||
"type": "module",
|
|
||||||
"license": "MPL-2.0",
|
|
||||||
"module": "true",
|
|
||||||
"scripts": {
|
|
||||||
"dev:app": "NODE_ENV=development tauri dev",
|
|
||||||
"dev:web": "yarn workspace @affine/web dev",
|
|
||||||
"build:rs-types": "zx scripts/generateTsTypingsFromJsonSchema.mjs",
|
|
||||||
"build:affine": "zx scripts/buildAffine.mjs",
|
|
||||||
"build:preload": "esbuild src/preload/index.ts --outdir=public/preload",
|
|
||||||
"build:app": "tauri build"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@blocksuite/blocks": "0.5.0-20230404060355-e26ee252",
|
|
||||||
"@blocksuite/editor": "0.5.0-20230404060355-e26ee252",
|
|
||||||
"@blocksuite/icons": "2.1.2",
|
|
||||||
"@blocksuite/store": "0.5.0-20230404060355-e26ee252",
|
|
||||||
"@emotion/react": "^11.10.6",
|
|
||||||
"@emotion/styled": "^11.10.6",
|
|
||||||
"@tauri-apps/api": "^1.2.0",
|
|
||||||
"json-schema-to-typescript": "^12.0.0",
|
|
||||||
"lib0": "^0.2.73",
|
|
||||||
"next": "=13.2.3",
|
|
||||||
"react": "^18.2.0",
|
|
||||||
"react-dom": "^18.2.0",
|
|
||||||
"y-protocols": "^1.0.5",
|
|
||||||
"yjs": "^13.5.51"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@tauri-apps/cli": "^1.2.3",
|
|
||||||
"@types/node": "^18.15.11",
|
|
||||||
"@types/react": "^18.0.31",
|
|
||||||
"@types/react-dom": "^18.0.11",
|
|
||||||
"esbuild": "^0.17.14",
|
|
||||||
"lit": "^2.7.0",
|
|
||||||
"prettier": "2.8.7",
|
|
||||||
"rimraf": "^4.4.1",
|
|
||||||
"typescript": "^5.0.3",
|
|
||||||
"typesync": "^0.10.0",
|
|
||||||
"vite": "^4.2.1",
|
|
||||||
"zx": "^7.2.1"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
const repoDirectory = path.join(__dirname, '..', '..', '..');
|
|
||||||
const clientAppDirectory = path.join(__dirname, '..');
|
|
||||||
const publicDistributionDirectory = path.join(clientAppDirectory, 'public');
|
|
||||||
const affineSrcDirectory = path.join(repoDirectory, 'apps', 'web');
|
|
||||||
const affineSrcOutDirectory = path.join(affineSrcDirectory, 'out');
|
|
||||||
const publicAffineOutDirectory = path.join(
|
|
||||||
publicDistributionDirectory,
|
|
||||||
'affine-out'
|
|
||||||
);
|
|
||||||
|
|
||||||
if (process.platform === 'win32') $.shell = 'pwsh';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Build affine dist html
|
|
||||||
*/
|
|
||||||
cd(repoDirectory);
|
|
||||||
await $`yarn install`;
|
|
||||||
await $`yarn build`;
|
|
||||||
cd(affineSrcDirectory);
|
|
||||||
$.env.NEXT_BASE_PATH = '/affine-out';
|
|
||||||
await $`yarn build`;
|
|
||||||
await $`yarn export`;
|
|
||||||
await fs.remove(publicAffineOutDirectory);
|
|
||||||
await fs.move(affineSrcOutDirectory, publicAffineOutDirectory);
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
import fs from 'fs';
|
|
||||||
// TODO: use https://github.com/quicktype/quicktype#installation instead
|
|
||||||
import { compileFromFile } from 'json-schema-to-typescript';
|
|
||||||
import path from 'path';
|
|
||||||
import { cd } from 'zx/core';
|
|
||||||
|
|
||||||
const projectRoot = path.join(__dirname, '..', '..');
|
|
||||||
const tsTypingsFolder = path.join(
|
|
||||||
projectRoot,
|
|
||||||
'packages/data-center/src/provider/tauri-ipc/ipc/types'
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 1. generate JSONSchema using rs crate `schemars`, this happened on rs side script `src-tauri/examples/generate-jsonschema.rs`
|
|
||||||
*/
|
|
||||||
cd('./src-tauri');
|
|
||||||
try {
|
|
||||||
fs.mkdirSync(tsTypingsFolder);
|
|
||||||
} catch {}
|
|
||||||
await $`cargo run --example generate-jsonschema`;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 2. generate TS from JSON schema, this is efficient on NodeJS side.
|
|
||||||
*/
|
|
||||||
const fileNames = fs.readdirSync(tsTypingsFolder);
|
|
||||||
const jsonSchemaFilePaths = fileNames
|
|
||||||
.filter(fileName => fileName.endsWith('.json'))
|
|
||||||
.map(fileName => path.join(tsTypingsFolder, fileName));
|
|
||||||
|
|
||||||
await Promise.all(
|
|
||||||
jsonSchemaFilePaths.map(
|
|
||||||
async fileName =>
|
|
||||||
await compileFromFile(fileName).then(tsContent =>
|
|
||||||
fs.writeFileSync(fileName.replace('.json', '.ts'), tsContent)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 3. fix eslint error on generated ts files
|
|
||||||
*/
|
|
||||||
cd(path.join(projectRoot, 'packages/data-center'));
|
|
||||||
await $`eslint ${tsTypingsFolder} --ext ts --fix`;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 4. // TODO: parse all #[tauri::command] and generate ts method code
|
|
||||||
*/
|
|
||||||
4
apps/desktop/src-tauri/.gitignore
vendored
@@ -1,4 +0,0 @@
|
|||||||
# Generated by Cargo
|
|
||||||
# will have compiled files and executables
|
|
||||||
/target/
|
|
||||||
|
|
||||||
5832
apps/desktop/src-tauri/Cargo.lock
generated
@@ -1,55 +0,0 @@
|
|||||||
[package]
|
|
||||||
name = "affine-client"
|
|
||||||
version = "0.0.1"
|
|
||||||
description = "Multiple platform client for AFFiNE"
|
|
||||||
authors = [
|
|
||||||
"linonetwo <linonetwo012@gmail.com>",
|
|
||||||
"DarkSky <darksky2048@gmail.com>",
|
|
||||||
]
|
|
||||||
license = "MPL-2.0"
|
|
||||||
repository = "https://github.com/toeverything/AFFiNE"
|
|
||||||
edition = "2021"
|
|
||||||
|
|
||||||
[features]
|
|
||||||
# by default Tauri runs in production mode
|
|
||||||
# when `tauri dev` runs it is executed with `cargo run --no-default-features` if `devPath` is an URL
|
|
||||||
default = ["custom-protocol"]
|
|
||||||
# this feature is used used for production builds where `devPath` points to the filesystem
|
|
||||||
# DO NOT remove this
|
|
||||||
custom-protocol = ["tauri/custom-protocol"]
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
bytes = "1.3.0"
|
|
||||||
ipc_types = { path = "./types" }
|
|
||||||
futures = "^0.3.25"
|
|
||||||
js-sys = "0.3.60"
|
|
||||||
jwst = { git = "https://github.com/toeverything/OctoBase", rev = "5f1162b" }
|
|
||||||
jwst-storage = { git = "https://github.com/toeverything/OctoBase", rev = "5f1162b", features = [
|
|
||||||
"sqlite",
|
|
||||||
] }
|
|
||||||
cloud-database = { git = "https://github.com/toeverything/OctoBase", rev = "5f1162b", features = [
|
|
||||||
"sqlite",
|
|
||||||
] }
|
|
||||||
project-root = "0.2.2"
|
|
||||||
schemars = "0.8.3"
|
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
|
||||||
serde_json = "1.0"
|
|
||||||
dotenvy = "0.15.6"
|
|
||||||
tauri = { version = "1.2", features = ["api-all", "devtools", "system-tray"] }
|
|
||||||
tokio = { version = "1.23.0", features = ["rt", "macros"] }
|
|
||||||
lib0 = "0.12.0"
|
|
||||||
moka = { version = "0.9.6", features = ["future"] }
|
|
||||||
y-sync = "0.1.0"
|
|
||||||
yrs = "=0.12.0"
|
|
||||||
|
|
||||||
[build-dependencies]
|
|
||||||
tauri-build = { version = "1.2", features = [] }
|
|
||||||
|
|
||||||
[patch.crates-io]
|
|
||||||
rust-embed = { git = "https://github.com/pyrossh/rust-embed", rev = "7c0fc42" }
|
|
||||||
yrs = { git = "https://github.com/toeverything/y-crdt", rev = "a1034b4" }
|
|
||||||
y-sync = { git = "https://github.com/toeverything/y-sync", rev = "e061fa3" }
|
|
||||||
|
|
||||||
[profile.release.package.wry]
|
|
||||||
debug = true
|
|
||||||
debug-assertions = true
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
fn main() {
|
|
||||||
tauri_build::build()
|
|
||||||
}
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
use ipc_types::{
|
|
||||||
blob::IBlobParameters, document::IDocumentParameters, user::IUserParameters,
|
|
||||||
workspace::IWorkspaceParameters,
|
|
||||||
};
|
|
||||||
/**
|
|
||||||
* convert serde to jsonschema: https://imfeld.dev/writing/generating_typescript_types_from_rust
|
|
||||||
* with way to optimize
|
|
||||||
* convert jsonschema to ts: https://github.com/bcherny/json-schema-to-typescript
|
|
||||||
*/
|
|
||||||
use project_root::get_project_root;
|
|
||||||
use schemars::{schema_for, JsonSchema};
|
|
||||||
use std::{
|
|
||||||
fs::write,
|
|
||||||
path::{Path, PathBuf},
|
|
||||||
};
|
|
||||||
|
|
||||||
fn generate<T>(path: PathBuf)
|
|
||||||
where
|
|
||||||
T: ?Sized + JsonSchema, // Sized or ?Sized are both ok, click https://zhuanlan.zhihu.com/p/21820917 to learn why
|
|
||||||
{
|
|
||||||
let schema = schema_for!(T);
|
|
||||||
let output = serde_json::to_string_pretty(&schema).unwrap();
|
|
||||||
write(path, output).expect("can not write json-schema file")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let project_root = &get_project_root().unwrap();
|
|
||||||
let mono_repo_root = Path::join(project_root, "../..");
|
|
||||||
let data_center_ipc_type_folder = Path::join(
|
|
||||||
&mono_repo_root,
|
|
||||||
"packages/data-center/src/provider/tauri-ipc/ipc/types",
|
|
||||||
);
|
|
||||||
generate::<IDocumentParameters>(Path::join(&data_center_ipc_type_folder, "document.json"));
|
|
||||||
generate::<IWorkspaceParameters>(Path::join(&data_center_ipc_type_folder, "workspace.json"));
|
|
||||||
generate::<IBlobParameters>(Path::join(&data_center_ipc_type_folder, "blob.json"));
|
|
||||||
generate::<IUserParameters>(Path::join(&data_center_ipc_type_folder, "user.json"));
|
|
||||||
}
|
|
||||||
|
Before Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 947 B |
|
Before Width: | Height: | Size: 4.3 KiB |
|
Before Width: | Height: | Size: 6.0 KiB |
|
Before Width: | Height: | Size: 6.3 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 85 KiB |
@@ -1 +0,0 @@
|
|||||||
tab_spaces = 2
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
pub mod blob;
|
|
||||||
pub mod workspace;
|
|
||||||
pub mod document;
|
|
||||||
pub mod user;
|
|
||||||
|
|
||||||
use blob::*;
|
|
||||||
use workspace::*;
|
|
||||||
use document::*;
|
|
||||||
use user::*;
|
|
||||||
|
|
||||||
pub fn invoke_handler() -> impl Fn(tauri::Invoke) + Send + Sync + 'static {
|
|
||||||
tauri::generate_handler![
|
|
||||||
update_y_document,
|
|
||||||
create_workspace,
|
|
||||||
update_workspace,
|
|
||||||
get_workspaces,
|
|
||||||
get_workspace,
|
|
||||||
create_user,
|
|
||||||
get_user,
|
|
||||||
create_doc,
|
|
||||||
get_doc,
|
|
||||||
put_blob,
|
|
||||||
get_blob
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
use bytes::Bytes;
|
|
||||||
use futures::{
|
|
||||||
stream::{self},
|
|
||||||
StreamExt,
|
|
||||||
};
|
|
||||||
|
|
||||||
use ipc_types::blob::{GetBlob, PutBlob};
|
|
||||||
use jwst::BlobStorage;
|
|
||||||
|
|
||||||
use crate::state::AppState;
|
|
||||||
|
|
||||||
#[tauri::command]
|
|
||||||
pub async fn put_blob<'s>(
|
|
||||||
state: tauri::State<'s, AppState>,
|
|
||||||
parameters: PutBlob,
|
|
||||||
) -> Result<String, String> {
|
|
||||||
let blob_storage = &state.0.lock().await.blob_storage;
|
|
||||||
if let Ok(path) = blob_storage
|
|
||||||
.put_blob(
|
|
||||||
// TODO: ask octobase to accept blob directly or wrap/await tauri command to create a real stream, so we don't need to construct stream manually
|
|
||||||
parameters.workspace_id,
|
|
||||||
stream::iter::<Vec<Bytes>>(vec![Bytes::from(parameters.blob)]),
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
{
|
|
||||||
Ok(path)
|
|
||||||
} else {
|
|
||||||
Err("Failed to create".to_string())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tauri::command]
|
|
||||||
pub async fn get_blob<'s>(
|
|
||||||
state: tauri::State<'s, AppState>,
|
|
||||||
parameters: GetBlob,
|
|
||||||
) -> Result<Vec<u8>, String> {
|
|
||||||
let GetBlob { workspace_id, id } = parameters;
|
|
||||||
// TODO: check user permission? Or just assume there will only be one user
|
|
||||||
let blob_storage = &state.0.lock().await.blob_storage;
|
|
||||||
if let Ok(mut file_stream) = blob_storage.get_blob(workspace_id.clone(), id.clone()).await {
|
|
||||||
// Read all of the chunks into a vector.
|
|
||||||
let mut stream_contents = Vec::new();
|
|
||||||
let mut error_message = "".to_string();
|
|
||||||
while let Some(chunk) = file_stream.next().await {
|
|
||||||
match chunk {
|
|
||||||
Ok(chunk_bytes) => stream_contents.extend_from_slice(&chunk_bytes),
|
|
||||||
Err(err) => {
|
|
||||||
error_message = format!(
|
|
||||||
"Failed to read blob file {}/{} from stream, error: {}",
|
|
||||||
workspace_id.clone().unwrap_or_default().to_string(),
|
|
||||||
id,
|
|
||||||
err
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if error_message.len() > 0 {
|
|
||||||
return Err(error_message);
|
|
||||||
}
|
|
||||||
Ok(stream_contents)
|
|
||||||
} else {
|
|
||||||
Err(format!(
|
|
||||||
"Failed to read blob file {}/{} ",
|
|
||||||
workspace_id.unwrap_or_default().to_string(),
|
|
||||||
id
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,81 +0,0 @@
|
|||||||
use ipc_types::document::{
|
|
||||||
CreateDocumentParameter, GetDocumentParameter, GetDocumentResponse, YDocumentUpdate,
|
|
||||||
};
|
|
||||||
use jwst::DocStorage;
|
|
||||||
use jwst::Workspace as OctoBaseWorkspace;
|
|
||||||
use lib0::any::Any;
|
|
||||||
|
|
||||||
use crate::state::AppState;
|
|
||||||
|
|
||||||
#[tauri::command]
|
|
||||||
/// get yDoc created by create_workspace, using same id
|
|
||||||
pub async fn create_doc<'s>(
|
|
||||||
state: tauri::State<'s, AppState>,
|
|
||||||
parameters: CreateDocumentParameter,
|
|
||||||
) -> Result<(), String> {
|
|
||||||
let workspace_doc = OctoBaseWorkspace::new(parameters.workspace_id.clone());
|
|
||||||
|
|
||||||
workspace_doc.with_trx(|mut workspace_doc_transaction| {
|
|
||||||
workspace_doc_transaction.set_metadata(
|
|
||||||
"name",
|
|
||||||
Any::String(parameters.workspace_name.clone().into_boxed_str()),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
if let Err(error_message) = &state
|
|
||||||
.0
|
|
||||||
.lock()
|
|
||||||
.await
|
|
||||||
.doc_db
|
|
||||||
.write_doc(parameters.workspace_id.clone(), workspace_doc.doc())
|
|
||||||
.await
|
|
||||||
{
|
|
||||||
Err(format!(
|
|
||||||
"Failed to write_doc during create_workspace with error {}",
|
|
||||||
error_message.to_string()
|
|
||||||
))
|
|
||||||
} else {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tauri::command]
|
|
||||||
/// get yDoc created by create_workspace, using same id
|
|
||||||
pub async fn get_doc<'s>(
|
|
||||||
state: tauri::State<'s, AppState>,
|
|
||||||
parameters: GetDocumentParameter,
|
|
||||||
) -> Result<GetDocumentResponse, String> {
|
|
||||||
// TODO: check user permission
|
|
||||||
let state = &state.0.lock().await;
|
|
||||||
let doc_db = &state.doc_db;
|
|
||||||
|
|
||||||
if let Ok(all_updates_of_workspace) = doc_db.all(¶meters.id).await {
|
|
||||||
let all_updates = all_updates_of_workspace
|
|
||||||
.iter()
|
|
||||||
.map(|model| model.blob.clone())
|
|
||||||
.collect::<Vec<Vec<u8>>>();
|
|
||||||
Ok(GetDocumentResponse {
|
|
||||||
updates: all_updates,
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
Err(format!(
|
|
||||||
"Failed to get yDoc from workspace {}",
|
|
||||||
parameters.id
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tauri::command]
|
|
||||||
pub async fn update_y_document<'s>(
|
|
||||||
state: tauri::State<'s, AppState>,
|
|
||||||
parameters: YDocumentUpdate,
|
|
||||||
) -> Result<bool, String> {
|
|
||||||
let state = &state.0.lock().await;
|
|
||||||
let doc_db = &state.doc_db;
|
|
||||||
|
|
||||||
doc_db
|
|
||||||
.replace_with(¶meters.id.clone(), parameters.update)
|
|
||||||
.await
|
|
||||||
.ok();
|
|
||||||
|
|
||||||
Ok(true)
|
|
||||||
}
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
use cloud_database::{CreateUser, User};
|
|
||||||
use ipc_types::{document::CreateDocumentParameter, user::GetUserParameters};
|
|
||||||
|
|
||||||
use crate::state::AppState;
|
|
||||||
|
|
||||||
use super::document::create_doc;
|
|
||||||
|
|
||||||
#[tauri::command]
|
|
||||||
/// create new user and a private workspace
|
|
||||||
pub async fn create_user<'s>(
|
|
||||||
state: tauri::State<'s, AppState>,
|
|
||||||
parameters: CreateUser,
|
|
||||||
) -> Result<User, String> {
|
|
||||||
let new_user_result = &state
|
|
||||||
.0
|
|
||||||
.lock()
|
|
||||||
.await
|
|
||||||
.metadata_db
|
|
||||||
.create_user(parameters.clone())
|
|
||||||
.await;
|
|
||||||
match new_user_result {
|
|
||||||
Ok(new_user_option) => match new_user_option {
|
|
||||||
Some((new_user, new_workspace)) => {
|
|
||||||
// a new private workspace is created, we have to create a yDoc for it
|
|
||||||
create_doc(
|
|
||||||
state,
|
|
||||||
CreateDocumentParameter {
|
|
||||||
workspace_id: new_workspace.id.clone(),
|
|
||||||
workspace_name: parameters.name.clone(),
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
.ok();
|
|
||||||
Ok(new_user.clone())
|
|
||||||
}
|
|
||||||
None => Err("User creation failed".to_string()),
|
|
||||||
},
|
|
||||||
Err(error_message) => Err(error_message.to_string()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tauri::command]
|
|
||||||
/// get the only one user in local sqlite
|
|
||||||
pub async fn get_user<'s>(
|
|
||||||
state: tauri::State<'s, AppState>,
|
|
||||||
parameters: GetUserParameters,
|
|
||||||
) -> Result<User, String> {
|
|
||||||
let db = &state.0.lock().await.metadata_db;
|
|
||||||
match db.get_user_by_email(¶meters.email).await.ok().unwrap() {
|
|
||||||
Some(user) => Ok(user),
|
|
||||||
None => Err("User not found".to_string()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,102 +0,0 @@
|
|||||||
use ipc_types::{
|
|
||||||
document::CreateDocumentParameter,
|
|
||||||
workspace::{
|
|
||||||
CreateWorkspace, CreateWorkspaceResult, GetWorkspace, GetWorkspaceResult, GetWorkspaces,
|
|
||||||
GetWorkspacesResult, UpdateWorkspace,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::state::AppState;
|
|
||||||
|
|
||||||
use super::document::create_doc;
|
|
||||||
|
|
||||||
#[tauri::command]
|
|
||||||
/// create yDoc for a workspace
|
|
||||||
pub async fn get_workspaces<'s>(
|
|
||||||
state: tauri::State<'s, AppState>,
|
|
||||||
parameters: GetWorkspaces,
|
|
||||||
) -> Result<GetWorkspacesResult, String> {
|
|
||||||
match &state
|
|
||||||
.0
|
|
||||||
.lock()
|
|
||||||
.await
|
|
||||||
.metadata_db
|
|
||||||
.get_user_workspaces(parameters.user_id.to_string())
|
|
||||||
.await
|
|
||||||
{
|
|
||||||
Ok(user_workspaces) => Ok(GetWorkspacesResult {
|
|
||||||
workspaces: user_workspaces.clone(),
|
|
||||||
}),
|
|
||||||
Err(error_message) => Err(error_message.to_string()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tauri::command]
|
|
||||||
/// create yDoc for a workspace
|
|
||||||
pub async fn get_workspace<'s>(
|
|
||||||
state: tauri::State<'s, AppState>,
|
|
||||||
parameters: GetWorkspace,
|
|
||||||
) -> Result<GetWorkspaceResult, String> {
|
|
||||||
match &state
|
|
||||||
.0
|
|
||||||
.lock()
|
|
||||||
.await
|
|
||||||
.metadata_db
|
|
||||||
.get_workspace_by_id(parameters.id)
|
|
||||||
.await
|
|
||||||
{
|
|
||||||
Ok(user_workspace_option) => match user_workspace_option {
|
|
||||||
Some(user_workspace) => Ok(GetWorkspaceResult {
|
|
||||||
workspace: user_workspace.clone(),
|
|
||||||
}),
|
|
||||||
None => Err("Get workspace has no result".to_string()),
|
|
||||||
},
|
|
||||||
Err(error_message) => Err(error_message.to_string()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tauri::command]
|
|
||||||
/// create yDoc for a workspace
|
|
||||||
pub async fn create_workspace<'s>(
|
|
||||||
state: tauri::State<'s, AppState>,
|
|
||||||
parameters: CreateWorkspace,
|
|
||||||
) -> Result<CreateWorkspaceResult, String> {
|
|
||||||
let new_workspace_result = &state
|
|
||||||
.0
|
|
||||||
.lock()
|
|
||||||
.await
|
|
||||||
.metadata_db
|
|
||||||
.create_normal_workspace(parameters.user_id.to_string())
|
|
||||||
.await;
|
|
||||||
match new_workspace_result {
|
|
||||||
Ok(new_workspace) => {
|
|
||||||
create_doc(
|
|
||||||
state,
|
|
||||||
CreateDocumentParameter {
|
|
||||||
workspace_id: new_workspace.id.clone(),
|
|
||||||
workspace_name: parameters.name.clone(),
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
.ok();
|
|
||||||
Ok(CreateWorkspaceResult {
|
|
||||||
id: new_workspace.id.clone(),
|
|
||||||
name: parameters.name,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
Err(error_message) => Err(format!(
|
|
||||||
"Failed to create_workspace with error {}",
|
|
||||||
error_message.to_string()
|
|
||||||
)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tauri::command]
|
|
||||||
pub async fn update_workspace<'s>(
|
|
||||||
_state: tauri::State<'s, AppState>,
|
|
||||||
_parameters: UpdateWorkspace,
|
|
||||||
) -> Result<bool, String> {
|
|
||||||
// TODO: check user permission
|
|
||||||
// No thing to update now. The avatar is update in YDoc using websocket or yrs.update
|
|
||||||
Ok(true)
|
|
||||||
}
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
#![cfg_attr(
|
|
||||||
all(not(debug_assertions), target_os = "windows"),
|
|
||||||
windows_subsystem = "windows"
|
|
||||||
)]
|
|
||||||
|
|
||||||
mod commands;
|
|
||||||
mod state;
|
|
||||||
mod menu;
|
|
||||||
use dotenvy::dotenv;
|
|
||||||
use state::AppState;
|
|
||||||
use std::env;
|
|
||||||
#[cfg(target_os = "macos")]
|
|
||||||
use tauri::TitleBarStyle;
|
|
||||||
use tokio::sync::Mutex;
|
|
||||||
|
|
||||||
#[tokio::main]
|
|
||||||
async fn main() {
|
|
||||||
tauri::async_runtime::set(tokio::runtime::Handle::current());
|
|
||||||
dotenv().ok();
|
|
||||||
let preload = include_str!("../../public/preload/index.js");
|
|
||||||
let is_dev = env::var("NODE_ENV").unwrap_or_default() == "development";
|
|
||||||
// this only work in production mode, in dev mode, we load `devPath` in tauri.conf.json
|
|
||||||
let initial_path = if is_dev {
|
|
||||||
// just a place holder here
|
|
||||||
"index.html"
|
|
||||||
} else {
|
|
||||||
"affine-out/index.html"
|
|
||||||
};
|
|
||||||
tauri::Builder::default()
|
|
||||||
.manage(AppState(Mutex::new(
|
|
||||||
state::AppStateRaw::new().await.unwrap(),
|
|
||||||
)))
|
|
||||||
// manually create window here, instead of in the tauri.conf.json, to add `initialization_script` here
|
|
||||||
.setup(move |app| {
|
|
||||||
let _window =
|
|
||||||
tauri::WindowBuilder::new(app, "label", tauri::WindowUrl::App(initial_path.into()))
|
|
||||||
.title("AFFiNE")
|
|
||||||
.inner_size(1000.0, 800.0)
|
|
||||||
.initialization_script(&preload);
|
|
||||||
// fix `title_bar_style` found for struct `WindowBuilder` in the current scope
|
|
||||||
#[cfg(target_os = "macos")]
|
|
||||||
let _window = _window
|
|
||||||
.hidden_title(true)
|
|
||||||
.title_bar_style(TitleBarStyle::Overlay);
|
|
||||||
let _window = _window.build()?;
|
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
_window.open_devtools();
|
|
||||||
Ok(())
|
|
||||||
})
|
|
||||||
.invoke_handler(commands::invoke_handler())
|
|
||||||
.menu(menu::init())
|
|
||||||
.on_menu_event(menu::menu_handler)
|
|
||||||
.run(tauri::generate_context!())
|
|
||||||
.expect("error while running tauri application");
|
|
||||||
}
|
|
||||||
@@ -1,108 +0,0 @@
|
|||||||
use tauri::{CustomMenuItem, Manager, Menu, MenuItem, Submenu, WindowMenuEvent};
|
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
|
||||||
use tauri::AboutMetadata;
|
|
||||||
|
|
||||||
// --- Menu
|
|
||||||
pub fn init() -> Menu {
|
|
||||||
let name = "AFFiNE";
|
|
||||||
let app_menu = Submenu::new(
|
|
||||||
name,
|
|
||||||
Menu::with_items([
|
|
||||||
#[cfg(target_os = "macos")]
|
|
||||||
MenuItem::About(name.into(), AboutMetadata::default()).into(),
|
|
||||||
MenuItem::Services.into(),
|
|
||||||
MenuItem::Hide.into(),
|
|
||||||
MenuItem::HideOthers.into(),
|
|
||||||
MenuItem::ShowAll.into(),
|
|
||||||
MenuItem::Separator.into(),
|
|
||||||
MenuItem::Quit.into(),
|
|
||||||
]),
|
|
||||||
);
|
|
||||||
|
|
||||||
let edit_menu = Submenu::new(
|
|
||||||
"Edit",
|
|
||||||
Menu::new()
|
|
||||||
.add_native_item(MenuItem::Undo)
|
|
||||||
.add_native_item(MenuItem::Redo)
|
|
||||||
.add_native_item(MenuItem::Separator)
|
|
||||||
.add_native_item(MenuItem::Cut)
|
|
||||||
.add_native_item(MenuItem::Copy)
|
|
||||||
.add_native_item(MenuItem::Paste)
|
|
||||||
.add_native_item(MenuItem::SelectAll),
|
|
||||||
);
|
|
||||||
|
|
||||||
let view_menu = Submenu::new(
|
|
||||||
"View",
|
|
||||||
Menu::new()
|
|
||||||
.add_item(CustomMenuItem::new("go_back".to_string(), "Go Back").accelerator("CmdOrCtrl+["))
|
|
||||||
.add_item(
|
|
||||||
CustomMenuItem::new("go_forward".to_string(), "Go Forward").accelerator("CmdOrCtrl+]"),
|
|
||||||
)
|
|
||||||
.add_native_item(MenuItem::Separator)
|
|
||||||
.add_item(
|
|
||||||
CustomMenuItem::new("zoom_0".to_string(), "Zoom to Actual Size").accelerator("CmdOrCtrl+0"),
|
|
||||||
)
|
|
||||||
.add_item(CustomMenuItem::new("zoom_out".to_string(), "Zoom Out").accelerator("CmdOrCtrl+-"))
|
|
||||||
.add_item(CustomMenuItem::new("zoom_in".to_string(), "Zoom In").accelerator("CmdOrCtrl+Plus"))
|
|
||||||
.add_native_item(MenuItem::Separator)
|
|
||||||
.add_item(
|
|
||||||
CustomMenuItem::new("reload".to_string(), "Refresh the Screen").accelerator("CmdOrCtrl+R"),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
let window_menu = Submenu::new(
|
|
||||||
"Window",
|
|
||||||
Menu::new()
|
|
||||||
.add_item(CustomMenuItem::new(
|
|
||||||
"official_website".to_string(),
|
|
||||||
"About AFFiNE",
|
|
||||||
))
|
|
||||||
.add_native_item(MenuItem::Separator)
|
|
||||||
.add_native_item(MenuItem::Minimize)
|
|
||||||
.add_native_item(MenuItem::Zoom),
|
|
||||||
);
|
|
||||||
|
|
||||||
let help_menu = Submenu::new(
|
|
||||||
"Help",
|
|
||||||
Menu::new()
|
|
||||||
.add_item(CustomMenuItem::new("update_log".to_string(), "Update Log"))
|
|
||||||
.add_item(CustomMenuItem::new("report_bug".to_string(), "Report Bug"))
|
|
||||||
.add_item(
|
|
||||||
CustomMenuItem::new("dev_tools".to_string(), "Toggle Developer Tools")
|
|
||||||
.accelerator("CmdOrCtrl+Shift+I"),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
Menu::new()
|
|
||||||
.add_submenu(app_menu)
|
|
||||||
.add_submenu(window_menu)
|
|
||||||
.add_submenu(edit_menu)
|
|
||||||
.add_submenu(view_menu)
|
|
||||||
.add_submenu(help_menu)
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- Menu Event
|
|
||||||
pub fn menu_handler(event: WindowMenuEvent<tauri::Wry>) {
|
|
||||||
let win = Some(event.window()).unwrap();
|
|
||||||
let app = win.app_handle();
|
|
||||||
let menu_id = event.menu_item_id();
|
|
||||||
|
|
||||||
match menu_id {
|
|
||||||
// App
|
|
||||||
"restart" => tauri::api::process::restart(&app.env()),
|
|
||||||
// Window
|
|
||||||
// View
|
|
||||||
"zoom_0" => win.eval("window.__zoom0 && window.__zoom0()").unwrap(),
|
|
||||||
"zoom_out" => win.eval("window.__zoomOut && window.__zoomOut()").unwrap(),
|
|
||||||
"zoom_in" => win.eval("window.__zoomIn && window.__zoomIn()").unwrap(),
|
|
||||||
"reload" => win.eval("window.location.reload()").unwrap(),
|
|
||||||
"go_back" => win.eval("window.history.go(-1)").unwrap(),
|
|
||||||
"go_forward" => win.eval("window.history.go(1)").unwrap(),
|
|
||||||
"dev_tools" => {
|
|
||||||
win.open_devtools();
|
|
||||||
win.close_devtools();
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
use cloud_database::SqliteDBContext;
|
|
||||||
use jwst_storage::{BlobAutoStorage, DocAutoStorage};
|
|
||||||
use std::{fs, path::Path};
|
|
||||||
use tauri::api::path::document_dir;
|
|
||||||
use tokio::sync::Mutex;
|
|
||||||
|
|
||||||
pub struct AppStateRaw {
|
|
||||||
pub doc_db: DocAutoStorage,
|
|
||||||
pub blob_storage: BlobAutoStorage,
|
|
||||||
pub metadata_db: SqliteDBContext,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AppStateRaw {
|
|
||||||
pub async fn new() -> Option<AppStateRaw> {
|
|
||||||
let affine_document_path = Path::new(&document_dir()?.into_os_string()).join("affine");
|
|
||||||
let metadata_db_env = format!(
|
|
||||||
"sqlite://{}?mode=rwc",
|
|
||||||
affine_document_path
|
|
||||||
.join("metadata")
|
|
||||||
.with_extension("db")
|
|
||||||
.display()
|
|
||||||
);
|
|
||||||
let blob_db_env = format!(
|
|
||||||
"sqlite://{}?mode=rwc",
|
|
||||||
affine_document_path
|
|
||||||
.join("blob")
|
|
||||||
.with_extension("db")
|
|
||||||
.display()
|
|
||||||
);
|
|
||||||
let doc_db_env = format!(
|
|
||||||
"sqlite://{}?mode=rwc",
|
|
||||||
affine_document_path
|
|
||||||
.join("doc")
|
|
||||||
.with_extension("db")
|
|
||||||
.display()
|
|
||||||
);
|
|
||||||
fs::create_dir_all(affine_document_path.clone()).unwrap();
|
|
||||||
|
|
||||||
Some(Self {
|
|
||||||
doc_db: DocAutoStorage::init_pool(&doc_db_env).await.unwrap(),
|
|
||||||
blob_storage: BlobAutoStorage::init_pool(&blob_db_env).await.unwrap(),
|
|
||||||
metadata_db: SqliteDBContext::new(metadata_db_env).await,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct AppState(pub Mutex<AppStateRaw>); // need pub, otherwise will be "field `0` of struct `types::state::AppState` is private"
|
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
{
|
|
||||||
"build": {
|
|
||||||
"beforeDevCommand": "yarn dev:web",
|
|
||||||
"beforeBuildCommand": "yarn build:preload && yarn build:affine",
|
|
||||||
"devPath": "http://localhost:8080",
|
|
||||||
"distDir": "../public",
|
|
||||||
"withGlobalTauri": false
|
|
||||||
},
|
|
||||||
"package": {
|
|
||||||
"productName": "Affine",
|
|
||||||
"version": "0.1.0"
|
|
||||||
},
|
|
||||||
"tauri": {
|
|
||||||
"allowlist": {
|
|
||||||
"all": true,
|
|
||||||
"fs": {
|
|
||||||
"all": true,
|
|
||||||
"scope": ["$RESOURCE", "$RESOURCE/*", "$APP/*"]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"systemTray": {
|
|
||||||
"iconPath": "icons/128x128@2x.png",
|
|
||||||
"iconAsTemplate": true,
|
|
||||||
"menuOnLeftClick": false
|
|
||||||
},
|
|
||||||
"bundle": {
|
|
||||||
"active": true,
|
|
||||||
"category": "DeveloperTool",
|
|
||||||
"copyright": "",
|
|
||||||
"deb": {
|
|
||||||
"depends": []
|
|
||||||
},
|
|
||||||
"externalBin": [],
|
|
||||||
"icon": [
|
|
||||||
"icons/32x32.png",
|
|
||||||
"icons/128x128.png",
|
|
||||||
"icons/128x128@2x.png",
|
|
||||||
"icons/icon.icns",
|
|
||||||
"icons/icon.ico"
|
|
||||||
],
|
|
||||||
"identifier": "com.affine.client",
|
|
||||||
"longDescription": "",
|
|
||||||
"macOS": {
|
|
||||||
"entitlements": null,
|
|
||||||
"exceptionDomain": "",
|
|
||||||
"frameworks": [],
|
|
||||||
"providerShortName": null,
|
|
||||||
"signingIdentity": null
|
|
||||||
},
|
|
||||||
"resources": [],
|
|
||||||
"shortDescription": "",
|
|
||||||
"targets": "all",
|
|
||||||
"windows": {
|
|
||||||
"certificateThumbprint": null,
|
|
||||||
"digestAlgorithm": "sha256",
|
|
||||||
"timestampUrl": ""
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"updater": {
|
|
||||||
"active": false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
[package]
|
|
||||||
name = "ipc_types"
|
|
||||||
version = "0.1.0"
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
cloud-database = { git = "https://github.com/toeverything/OctoBase", rev = "5f1162b", features = [
|
|
||||||
"sqlite",
|
|
||||||
] }
|
|
||||||
jwst-storage = { git = "https://github.com/toeverything/OctoBase", rev = "5f1162b", features = [
|
|
||||||
"sqlite",
|
|
||||||
] }
|
|
||||||
project-root = "0.2.2"
|
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
|
||||||
serde_json = "1.0"
|
|
||||||
schemars = "0.8.3"
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
use schemars::JsonSchema;
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
|
|
||||||
pub struct PutBlob {
|
|
||||||
pub workspace_id: Option<String>,
|
|
||||||
pub blob: Vec<u8>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
|
|
||||||
pub struct GetBlob {
|
|
||||||
pub workspace_id: Option<String>,
|
|
||||||
pub id: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
|
|
||||||
pub enum IBlobParameters {
|
|
||||||
Put(PutBlob),
|
|
||||||
Get(GetBlob),
|
|
||||||
}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
use schemars::JsonSchema;
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
|
|
||||||
pub struct YDocumentUpdate {
|
|
||||||
pub update: Vec<u8>,
|
|
||||||
pub id: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
|
|
||||||
pub struct GetDocumentParameter {
|
|
||||||
pub id: String,
|
|
||||||
}
|
|
||||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
|
|
||||||
pub struct CreateDocumentParameter {
|
|
||||||
pub workspace_id: String,
|
|
||||||
pub workspace_name: String,
|
|
||||||
}
|
|
||||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
|
|
||||||
pub struct GetDocumentResponse {
|
|
||||||
pub updates: Vec<Vec<u8>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
|
|
||||||
pub enum IDocumentParameters {
|
|
||||||
YDocumentUpdate(YDocumentUpdate),
|
|
||||||
CreateDocumentParameter(CreateDocumentParameter),
|
|
||||||
GetDocumentParameter(GetDocumentParameter),
|
|
||||||
GetDocumentResponse(GetDocumentResponse),
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
#[allow(unused_imports)]
|
|
||||||
extern crate serde;
|
|
||||||
extern crate schemars;
|
|
||||||
extern crate jwst_storage;
|
|
||||||
extern crate cloud_database;
|
|
||||||
|
|
||||||
pub mod blob;
|
|
||||||
pub mod document;
|
|
||||||
pub mod workspace;
|
|
||||||
pub mod user;
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
use cloud_database::{CreateUser, User};
|
|
||||||
use schemars::JsonSchema;
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
|
|
||||||
pub struct GetUserParameters {
|
|
||||||
pub email: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
|
|
||||||
pub enum IUserParameters {
|
|
||||||
CreateUser(CreateUser),
|
|
||||||
User(User),
|
|
||||||
GetUserParameters(GetUserParameters),
|
|
||||||
}
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
use cloud_database::{WorkspaceWithPermission, WorkspaceDetail};
|
|
||||||
use schemars::JsonSchema;
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
|
|
||||||
pub struct CreateWorkspace {
|
|
||||||
pub user_id: String,
|
|
||||||
/**
|
|
||||||
* only set name, avatar is update in datacenter to yDoc directly
|
|
||||||
*/
|
|
||||||
pub name: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
|
|
||||||
pub struct GetWorkspaces {
|
|
||||||
pub user_id: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
|
|
||||||
pub struct GetWorkspace {
|
|
||||||
pub id: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
|
|
||||||
pub struct CreateWorkspaceResult {
|
|
||||||
pub id: String,
|
|
||||||
pub name: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
|
|
||||||
pub struct GetWorkspacesResult {
|
|
||||||
pub workspaces: Vec<WorkspaceWithPermission>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
|
|
||||||
pub struct GetWorkspaceResult {
|
|
||||||
pub workspace: WorkspaceDetail,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
|
|
||||||
pub struct UpdateWorkspace {
|
|
||||||
pub id: i64,
|
|
||||||
pub public: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
|
|
||||||
pub enum IWorkspaceParameters {
|
|
||||||
CreateWorkspace(CreateWorkspace),
|
|
||||||
GetWorkspace(GetWorkspace),
|
|
||||||
GetWorkspaces(GetWorkspaces),
|
|
||||||
GetWorkspaceResult(GetWorkspaceResult),
|
|
||||||
GetWorkspacesResult(GetWorkspacesResult),
|
|
||||||
UpdateWorkspace(UpdateWorkspace),
|
|
||||||
CreateWorkspaceResult(CreateWorkspaceResult),
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
# Preload Scripts
|
|
||||||
|
|
||||||
Here are preload scripts (See [tauri's doc](https://tauri.app/v1/references/architecture/inter-process-communication/isolation)). This is simillar to Electron's [preload script](https://www.electronjs.org/docs/latest/tutorial/sandbox#preload-scripts).
|
|
||||||
|
|
||||||
We pass env variables to AFFiNE side from here.
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
// tauri preload script can't have `export {}`
|
|
||||||
// @ts-ignore 'index.ts' cannot be compiled under '--isolatedModules' because it is considered a global script file. Add an import, export, or an empty 'export {}' statement to make it a module.ts(1208)
|
|
||||||
window.__TAURI_ISOLATION_HOOK__ = payload => {
|
|
||||||
console.log('Tauri isolation hook', payload);
|
|
||||||
|
|
||||||
return payload;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Give AFFiNE app code some env to know it is inside a tauri app.
|
|
||||||
*/
|
|
||||||
function setEnvironmentVariables() {
|
|
||||||
window.CLIENT_APP = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
setEnvironmentVariables();
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
declare global {
|
|
||||||
// eslint-disable-next-line no-var
|
|
||||||
var __editoVersion: unknown;
|
|
||||||
|
|
||||||
interface Window {
|
|
||||||
CLIENT_APP?: boolean;
|
|
||||||
__TAURI_ISOLATION_HOOK_: (payload: any) => any;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export {};
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
{
|
|
||||||
"extends": "../../tsconfig.json",
|
|
||||||
"include": ["./src"]
|
|
||||||
}
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
import { defineConfig } from 'vite';
|
|
||||||
|
|
||||||
// https://vitejs.dev/config/
|
|
||||||
export default defineConfig({
|
|
||||||
// Vite options tailored for Tauri development and only applied in `tauri dev` or `tauri build`
|
|
||||||
// prevent vite from obscuring rust errors
|
|
||||||
clearScreen: false,
|
|
||||||
// tauri expects a fixed port, fail if that port is not available
|
|
||||||
server: {
|
|
||||||
port: 1420,
|
|
||||||
strictPort: true,
|
|
||||||
},
|
|
||||||
// to make use of `TAURI_DEBUG` and other env variables
|
|
||||||
// https://tauri.studio/v1/api/config#buildconfig.beforedevcommand
|
|
||||||
envPrefix: ['VITE_', 'TAURI_'],
|
|
||||||
build: {
|
|
||||||
// Tauri supports es2021
|
|
||||||
target: ['es2021', 'chrome100', 'safari13'],
|
|
||||||
// don't minify for debug builds
|
|
||||||
minify: !process.env.TAURI_DEBUG ? 'esbuild' : false,
|
|
||||||
// produce sourcemaps for debug builds
|
|
||||||
sourcemap: !!process.env.TAURI_DEBUG,
|
|
||||||
},
|
|
||||||
esbuild: {
|
|
||||||
jsxInject: `import React from 'react';`,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
@@ -39,9 +39,6 @@
|
|||||||
{
|
{
|
||||||
"path": "./apps/web"
|
"path": "./apps/web"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"path": "./apps/desktop"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"path": "./packages/component"
|
"path": "./packages/component"
|
||||||
},
|
},
|
||||||
|
|||||||