mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
chore: listen backend notification from Tauri (#1743)
This commit is contained in:
10
frontend/.vscode/launch.json
vendored
10
frontend/.vscode/launch.json
vendored
@ -106,6 +106,16 @@
|
|||||||
"preLaunchTask": "AF: Tauri UI Dev",
|
"preLaunchTask": "AF: Tauri UI Dev",
|
||||||
"cwd": "${workspaceRoot}/appflowy_tauri/"
|
"cwd": "${workspaceRoot}/appflowy_tauri/"
|
||||||
},
|
},
|
||||||
|
// {
|
||||||
|
// "type": "lldb",
|
||||||
|
// "request": "launch",
|
||||||
|
// "name": "AF-tauri: Production Debug",
|
||||||
|
// "cargo": {
|
||||||
|
// "args": ["build", "--release", "--manifest-path=./appflowy_tauri/src-tauri/Cargo.toml"]
|
||||||
|
// },
|
||||||
|
// "preLaunchTask": "AF: Tauri UI Build",
|
||||||
|
// "cwd": "${workspaceRoot}/appflowy_tauri/"
|
||||||
|
// },
|
||||||
{
|
{
|
||||||
"name": "AF: Debug Rust",
|
"name": "AF: Debug Rust",
|
||||||
"request": "attach",
|
"request": "attach",
|
||||||
|
10
frontend/.vscode/settings.json
vendored
10
frontend/.vscode/settings.json
vendored
@ -9,6 +9,16 @@
|
|||||||
"editor.tabCompletion": "onlySnippets",
|
"editor.tabCompletion": "onlySnippets",
|
||||||
"editor.wordBasedSuggestions": false,
|
"editor.wordBasedSuggestions": false,
|
||||||
},
|
},
|
||||||
|
"[javascript]": {
|
||||||
|
"editor.formatOnSave": true,
|
||||||
|
"editor.rulers": [80],
|
||||||
|
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||||
|
},
|
||||||
|
"[typescript]": {
|
||||||
|
"editor.formatOnSave": true,
|
||||||
|
"editor.rulers": [80],
|
||||||
|
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||||
|
},
|
||||||
"svgviewer.enableautopreview": true,
|
"svgviewer.enableautopreview": true,
|
||||||
"svgviewer.previewcolumn": "Active",
|
"svgviewer.previewcolumn": "Active",
|
||||||
"svgviewer.showzoominout": true,
|
"svgviewer.showzoominout": true,
|
||||||
|
11
frontend/.vscode/tasks.json
vendored
11
frontend/.vscode/tasks.json
vendored
@ -190,7 +190,16 @@
|
|||||||
"label": "AF: Tauri UI Dev",
|
"label": "AF: Tauri UI Dev",
|
||||||
"type": "shell",
|
"type": "shell",
|
||||||
"isBackground": true,
|
"isBackground": true,
|
||||||
"command": "yarn dev",
|
"command": "npm run dev",
|
||||||
|
"problemMatcher": ["$tsc"],
|
||||||
|
"options": {
|
||||||
|
"cwd": "${workspaceFolder}/appflowy_tauri"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "AF: Tauri UI Build",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "npm run build",
|
||||||
"problemMatcher": ["$tsc"],
|
"problemMatcher": ["$tsc"],
|
||||||
"options": {
|
"options": {
|
||||||
"cwd": "${workspaceFolder}/appflowy_tauri"
|
"cwd": "${workspaceFolder}/appflowy_tauri"
|
||||||
|
@ -29,9 +29,10 @@ fn main() {
|
|||||||
});
|
});
|
||||||
})
|
})
|
||||||
.setup(|app| {
|
.setup(|app| {
|
||||||
let window = app.get_window("main").unwrap();
|
if cfg!(debug_assertions) {
|
||||||
#[cfg(debug_assertions)]
|
let window = app.get_window("main").unwrap();
|
||||||
window.open_devtools();
|
window.open_devtools();
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
.run(tauri::generate_context!())
|
.run(tauri::generate_context!())
|
||||||
|
@ -5,7 +5,6 @@ use tauri::{AppHandle, Event, Manager, Wry};
|
|||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub const AF_EVENT: &str = "af-event";
|
pub const AF_EVENT: &str = "af-event";
|
||||||
#[allow(dead_code)]
|
|
||||||
pub const AF_NOTIFICATION: &str = "af-notification";
|
pub const AF_NOTIFICATION: &str = "af-notification";
|
||||||
|
|
||||||
#[tracing::instrument(level = "trace")]
|
#[tracing::instrument(level = "trace")]
|
||||||
|
@ -4,25 +4,33 @@ import {
|
|||||||
SignInPayloadPB,
|
SignInPayloadPB,
|
||||||
} from "../services/backend/events/flowy-user/index";
|
} from "../services/backend/events/flowy-user/index";
|
||||||
import { nanoid } from "nanoid";
|
import { nanoid } from "nanoid";
|
||||||
|
import { UserNotificationListener } from "./components/user/application/notifications";
|
||||||
|
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
async function greet() {
|
async function sendSignInEvent() {
|
||||||
let make_payload = () =>
|
let make_payload = () =>
|
||||||
SignInPayloadPB.fromObject({
|
SignInPayloadPB.fromObject({
|
||||||
email: nanoid(4) + "@gmail.com",
|
email: nanoid(4) + "@gmail.com",
|
||||||
password: "A!@123abc",
|
password: "A!@123abc",
|
||||||
name: "abc",
|
name: "abc",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let listener = await new UserNotificationListener("", (userProfile) => {
|
||||||
|
console.log(userProfile);
|
||||||
|
listener.stop();
|
||||||
|
});
|
||||||
|
|
||||||
|
listener.start();
|
||||||
|
|
||||||
await UserEventSignIn(make_payload());
|
await UserEventSignIn(make_payload());
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="container">
|
<div className="container">
|
||||||
<h1>Welcome to AppFlowy!</h1>
|
<h1>Welcome to AppFlowy!</h1>
|
||||||
|
<button type="button" onClick={() => sendSignInEvent()}>
|
||||||
<button type="button" onClick={() => greet()}>
|
Test Sign In Event
|
||||||
Sign in
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
export * from "./user_listener";
|
@ -0,0 +1,27 @@
|
|||||||
|
import { Result } from "ts-results/result";
|
||||||
|
import { UserNotification, FlowyError } from "../../../../../services/backend";
|
||||||
|
import { NotificationParser, OnNotificationError } from "../../../../../services/backend/notifications/parser";
|
||||||
|
|
||||||
|
declare type UserNotificationCallback = (ty: UserNotification, payload: Uint8Array) => void;
|
||||||
|
|
||||||
|
export class UserNotificationParser extends NotificationParser<UserNotification> {
|
||||||
|
constructor(callback: UserNotificationCallback, id?: String, onError?: OnNotificationError) {
|
||||||
|
super(
|
||||||
|
callback,
|
||||||
|
(ty) => {
|
||||||
|
let notification = UserNotification[ty];
|
||||||
|
if (isUserNotification(notification)) {
|
||||||
|
return UserNotification[notification];
|
||||||
|
} else {
|
||||||
|
return UserNotification.Unknown;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
id,
|
||||||
|
onError
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const isUserNotification = (notification: string): notification is keyof typeof UserNotification => {
|
||||||
|
return Object.values(UserNotification).indexOf(notification) !== -1;
|
||||||
|
};
|
@ -0,0 +1,34 @@
|
|||||||
|
import { FlowyError, UserNotification, UserProfilePB } from "../../../../../services/backend";
|
||||||
|
import { AFNotificationListener, OnNotificationError } from "../../../../../services/backend/notifications";
|
||||||
|
import { UserNotificationParser } from "./parser";
|
||||||
|
|
||||||
|
declare type OnUserProfileUpdate = (userProfile: UserProfilePB) => void;
|
||||||
|
|
||||||
|
export class UserNotificationListener extends AFNotificationListener<UserNotification> {
|
||||||
|
onProfileUpdate?: OnUserProfileUpdate;
|
||||||
|
|
||||||
|
constructor(userId?: String, onProfileUpdate?: OnUserProfileUpdate, onError?: OnNotificationError) {
|
||||||
|
let parser = new UserNotificationParser(
|
||||||
|
(notification, payload) => {
|
||||||
|
switch (notification) {
|
||||||
|
case UserNotification.UserAuthChanged:
|
||||||
|
break;
|
||||||
|
case UserNotification.UserProfileUpdated:
|
||||||
|
break;
|
||||||
|
case UserNotification.UserUnauthorized:
|
||||||
|
break;
|
||||||
|
case UserNotification.UserSignIn:
|
||||||
|
let userProfile = UserProfilePB.deserializeBinary(payload);
|
||||||
|
this.onProfileUpdate?.(userProfile);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
userId,
|
||||||
|
onError
|
||||||
|
);
|
||||||
|
super(parser);
|
||||||
|
this.onProfileUpdate = onProfileUpdate;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,2 @@
|
|||||||
|
export * from "./listener";
|
||||||
|
export * from "./parser";
|
||||||
|
@ -0,0 +1,29 @@
|
|||||||
|
import { listen, UnlistenFn } from "@tauri-apps/api/event";
|
||||||
|
import { FlowyError } from "../classes/flowy-error";
|
||||||
|
import { SubscribeObject } from "../classes/flowy-notification";
|
||||||
|
import { NotificationParser } from "./parser";
|
||||||
|
|
||||||
|
declare type OnError = (error: FlowyError) => void;
|
||||||
|
|
||||||
|
export abstract class AFNotificationListener<T> {
|
||||||
|
parser?: NotificationParser<T> | null;
|
||||||
|
private _listener?: UnlistenFn;
|
||||||
|
|
||||||
|
protected constructor(parser?: NotificationParser<T>) {
|
||||||
|
this.parser = parser;
|
||||||
|
}
|
||||||
|
|
||||||
|
async start() {
|
||||||
|
this._listener = await listen("af-notification", (notification) => {
|
||||||
|
let object = SubscribeObject.fromObject(notification.payload as {});
|
||||||
|
this.parser?.parse(object);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async stop() {
|
||||||
|
if (this._listener != null) {
|
||||||
|
this._listener();
|
||||||
|
}
|
||||||
|
this.parser = null;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,42 @@
|
|||||||
|
import { Ok, Err, Result } from "ts-results/result";
|
||||||
|
import { FlowyError } from "../classes/flowy-error";
|
||||||
|
import { SubscribeObject } from "../classes/flowy-notification";
|
||||||
|
|
||||||
|
export declare type OnNotificationPayload<T> = (ty: T, payload: Uint8Array) => void;
|
||||||
|
export declare type OnNotificationError = (error: FlowyError) => void;
|
||||||
|
export declare type NotificationTyParser<T> = (num: number) => T | null;
|
||||||
|
export declare type ErrParser<E> = (data: Uint8Array) => E;
|
||||||
|
|
||||||
|
export abstract class NotificationParser<T> {
|
||||||
|
id?: String;
|
||||||
|
onPayload: OnNotificationPayload<T>;
|
||||||
|
onError?: OnNotificationError;
|
||||||
|
tyParser: NotificationTyParser<T>;
|
||||||
|
|
||||||
|
constructor(onPayload: OnNotificationPayload<T>, tyParser: NotificationTyParser<T>, id?: String, onError?: OnNotificationError) {
|
||||||
|
this.id = id;
|
||||||
|
this.onPayload = onPayload;
|
||||||
|
this.onError = onError;
|
||||||
|
this.tyParser = tyParser;
|
||||||
|
}
|
||||||
|
|
||||||
|
parse(subject: SubscribeObject) {
|
||||||
|
if (typeof this.id !== "undefined" && this.id.length == 0) {
|
||||||
|
if (subject.id != this.id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let ty = this.tyParser(subject.ty);
|
||||||
|
if (ty == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (subject.has_error) {
|
||||||
|
let error = FlowyError.deserializeBinary(subject.error);
|
||||||
|
this.onError?.(error);
|
||||||
|
} else {
|
||||||
|
this.onPayload(ty, subject.payload);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -5,7 +5,7 @@ use crate::{
|
|||||||
entities::workspace::RepeatedWorkspacePB,
|
entities::workspace::RepeatedWorkspacePB,
|
||||||
errors::FlowyResult,
|
errors::FlowyResult,
|
||||||
event_map::{FolderCouldServiceV1, WorkspaceDatabase, WorkspaceUser},
|
event_map::{FolderCouldServiceV1, WorkspaceDatabase, WorkspaceUser},
|
||||||
notification::{send_dart_notification, FolderNotification},
|
notification::{send_notification, FolderNotification},
|
||||||
services::{
|
services::{
|
||||||
folder_editor::FolderEditor, persistence::FolderPersistence, set_current_workspace, AppController,
|
folder_editor::FolderEditor, persistence::FolderPersistence, set_current_workspace, AppController,
|
||||||
TrashController, ViewController, WorkspaceController,
|
TrashController, ViewController, WorkspaceController,
|
||||||
@ -249,7 +249,7 @@ impl DefaultFolderBuilder {
|
|||||||
let repeated_workspace = RepeatedWorkspacePB {
|
let repeated_workspace = RepeatedWorkspacePB {
|
||||||
items: vec![workspace_rev.into()],
|
items: vec![workspace_rev.into()],
|
||||||
};
|
};
|
||||||
send_dart_notification(token, FolderNotification::UserCreateWorkspace)
|
send_notification(token, FolderNotification::UserCreateWorkspace)
|
||||||
.payload(repeated_workspace)
|
.payload(repeated_workspace)
|
||||||
.send();
|
.send();
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -33,11 +33,11 @@ impl std::convert::From<FolderNotification> for i32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument(level = "trace")]
|
#[tracing::instrument(level = "trace")]
|
||||||
pub(crate) fn send_dart_notification(id: &str, ty: FolderNotification) -> NotificationBuilder {
|
pub(crate) fn send_notification(id: &str, ty: FolderNotification) -> NotificationBuilder {
|
||||||
NotificationBuilder::new(id, ty, OBSERVABLE_CATEGORY)
|
NotificationBuilder::new(id, ty, OBSERVABLE_CATEGORY)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument(level = "trace")]
|
#[tracing::instrument(level = "trace")]
|
||||||
pub(crate) fn send_anonymous_dart_notification(ty: FolderNotification) -> NotificationBuilder {
|
pub(crate) fn send_anonymous_notification(ty: FolderNotification) -> NotificationBuilder {
|
||||||
NotificationBuilder::new("", ty, OBSERVABLE_CATEGORY)
|
NotificationBuilder::new("", ty, OBSERVABLE_CATEGORY)
|
||||||
}
|
}
|
||||||
|
@ -91,7 +91,7 @@ impl AppController {
|
|||||||
})
|
})
|
||||||
.await?
|
.await?
|
||||||
.into();
|
.into();
|
||||||
send_dart_notification(&app_id, FolderNotification::AppUpdated)
|
send_notification(&app_id, FolderNotification::AppUpdated)
|
||||||
.payload(app)
|
.payload(app)
|
||||||
.send();
|
.send();
|
||||||
self.update_app_on_server(params)?;
|
self.update_app_on_server(params)?;
|
||||||
@ -163,7 +163,7 @@ impl AppController {
|
|||||||
{
|
{
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
let app: AppPB = app_rev.into();
|
let app: AppPB = app_rev.into();
|
||||||
send_dart_notification(&app.id, FolderNotification::AppUpdated)
|
send_notification(&app.id, FolderNotification::AppUpdated)
|
||||||
.payload(app)
|
.payload(app)
|
||||||
.send();
|
.send();
|
||||||
}
|
}
|
||||||
@ -248,7 +248,7 @@ fn notify_apps_changed<'a>(
|
|||||||
.map(|app_rev| app_rev.into())
|
.map(|app_rev| app_rev.into())
|
||||||
.collect();
|
.collect();
|
||||||
let repeated_app = RepeatedAppPB { items };
|
let repeated_app = RepeatedAppPB { items };
|
||||||
send_dart_notification(workspace_id, FolderNotification::WorkspaceAppsChanged)
|
send_notification(workspace_id, FolderNotification::WorkspaceAppsChanged)
|
||||||
.payload(repeated_app)
|
.payload(repeated_app)
|
||||||
.send();
|
.send();
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -2,7 +2,7 @@ use crate::{
|
|||||||
entities::trash::{RepeatedTrashIdPB, RepeatedTrashPB, TrashIdPB, TrashPB, TrashType},
|
entities::trash::{RepeatedTrashIdPB, RepeatedTrashPB, TrashIdPB, TrashPB, TrashType},
|
||||||
errors::{FlowyError, FlowyResult},
|
errors::{FlowyError, FlowyResult},
|
||||||
event_map::{FolderCouldServiceV1, WorkspaceUser},
|
event_map::{FolderCouldServiceV1, WorkspaceUser},
|
||||||
notification::{send_anonymous_dart_notification, FolderNotification},
|
notification::{send_anonymous_notification, FolderNotification},
|
||||||
services::persistence::{FolderPersistence, FolderPersistenceTransaction},
|
services::persistence::{FolderPersistence, FolderPersistenceTransaction},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -283,7 +283,7 @@ impl TrashController {
|
|||||||
fn notify_trash_changed<T: Into<RepeatedTrashPB>>(repeated_trash: T) {
|
fn notify_trash_changed<T: Into<RepeatedTrashPB>>(repeated_trash: T) {
|
||||||
let repeated_trash = repeated_trash.into();
|
let repeated_trash = repeated_trash.into();
|
||||||
tracing::Span::current().record("n_trash", repeated_trash.len());
|
tracing::Span::current().record("n_trash", repeated_trash.len());
|
||||||
send_anonymous_dart_notification(FolderNotification::TrashUpdated)
|
send_anonymous_notification(FolderNotification::TrashUpdated)
|
||||||
.payload(repeated_trash)
|
.payload(repeated_trash)
|
||||||
.send();
|
.send();
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ use crate::{
|
|||||||
},
|
},
|
||||||
errors::{FlowyError, FlowyResult},
|
errors::{FlowyError, FlowyResult},
|
||||||
event_map::{FolderCouldServiceV1, WorkspaceUser},
|
event_map::{FolderCouldServiceV1, WorkspaceUser},
|
||||||
notification::{send_dart_notification, FolderNotification},
|
notification::{send_notification, FolderNotification},
|
||||||
services::{
|
services::{
|
||||||
persistence::{FolderPersistence, FolderPersistenceTransaction, ViewChangeset},
|
persistence::{FolderPersistence, FolderPersistenceTransaction, ViewChangeset},
|
||||||
TrashController, TrashEvent,
|
TrashController, TrashEvent,
|
||||||
@ -225,7 +225,7 @@ impl ViewController {
|
|||||||
})
|
})
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
send_dart_notification(&view_id, FolderNotification::ViewMoveToTrash)
|
send_notification(&view_id, FolderNotification::ViewMoveToTrash)
|
||||||
.payload(deleted_view)
|
.payload(deleted_view)
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
@ -291,7 +291,7 @@ impl ViewController {
|
|||||||
transaction.update_view(changeset)?;
|
transaction.update_view(changeset)?;
|
||||||
let view_rev = transaction.read_view(&view_id)?;
|
let view_rev = transaction.read_view(&view_id)?;
|
||||||
let view: ViewPB = view_rev.clone().into();
|
let view: ViewPB = view_rev.clone().into();
|
||||||
send_dart_notification(&view_id, FolderNotification::ViewUpdated)
|
send_notification(&view_id, FolderNotification::ViewUpdated)
|
||||||
.payload(view)
|
.payload(view)
|
||||||
.send();
|
.send();
|
||||||
notify_views_changed(&view_rev.app_id, self.trash_controller.clone(), &transaction)?;
|
notify_views_changed(&view_rev.app_id, self.trash_controller.clone(), &transaction)?;
|
||||||
@ -356,7 +356,7 @@ impl ViewController {
|
|||||||
{
|
{
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
let view: ViewPB = view_rev.into();
|
let view: ViewPB = view_rev.into();
|
||||||
send_dart_notification(&view.id, FolderNotification::ViewUpdated)
|
send_notification(&view.id, FolderNotification::ViewUpdated)
|
||||||
.payload(view)
|
.payload(view)
|
||||||
.send();
|
.send();
|
||||||
}
|
}
|
||||||
@ -518,7 +518,7 @@ fn read_local_views_with_transaction<'a>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn notify_dart(view: ViewPB, notification: FolderNotification) {
|
fn notify_dart(view: ViewPB, notification: FolderNotification) {
|
||||||
send_dart_notification(&view.id, notification).payload(view).send();
|
send_notification(&view.id, notification).payload(view).send();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument(
|
#[tracing::instrument(
|
||||||
@ -537,7 +537,7 @@ fn notify_views_changed<'a>(
|
|||||||
app_rev.belongings.retain(|view| !trash_ids.contains(&view.id));
|
app_rev.belongings.retain(|view| !trash_ids.contains(&view.id));
|
||||||
let app: AppPB = app_rev.into();
|
let app: AppPB = app_rev.into();
|
||||||
|
|
||||||
send_dart_notification(belong_to_id, FolderNotification::AppUpdated)
|
send_notification(belong_to_id, FolderNotification::AppUpdated)
|
||||||
.payload(app)
|
.payload(app)
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ impl WorkspaceController {
|
|||||||
.map(|workspace_rev| workspace_rev.into())
|
.map(|workspace_rev| workspace_rev.into())
|
||||||
.collect();
|
.collect();
|
||||||
let repeated_workspace = RepeatedWorkspacePB { items: workspaces };
|
let repeated_workspace = RepeatedWorkspacePB { items: workspaces };
|
||||||
send_dart_notification(&token, FolderNotification::UserCreateWorkspace)
|
send_notification(&token, FolderNotification::UserCreateWorkspace)
|
||||||
.payload(repeated_workspace)
|
.payload(repeated_workspace)
|
||||||
.send();
|
.send();
|
||||||
set_current_workspace(&user_id, &workspace.id);
|
set_current_workspace(&user_id, &workspace.id);
|
||||||
@ -73,7 +73,7 @@ impl WorkspaceController {
|
|||||||
})
|
})
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
send_dart_notification(&workspace_id, FolderNotification::WorkspaceUpdated)
|
send_notification(&workspace_id, FolderNotification::WorkspaceUpdated)
|
||||||
.payload(workspace)
|
.payload(workspace)
|
||||||
.send();
|
.send();
|
||||||
self.update_workspace_on_server(params)?;
|
self.update_workspace_on_server(params)?;
|
||||||
@ -92,7 +92,7 @@ impl WorkspaceController {
|
|||||||
self.read_local_workspaces(None, &user_id, &transaction)
|
self.read_local_workspaces(None, &user_id, &transaction)
|
||||||
})
|
})
|
||||||
.await?;
|
.await?;
|
||||||
send_dart_notification(&token, FolderNotification::UserDeleteWorkspace)
|
send_notification(&token, FolderNotification::UserDeleteWorkspace)
|
||||||
.payload(repeated_workspace)
|
.payload(repeated_workspace)
|
||||||
.send();
|
.send();
|
||||||
self.delete_workspace_on_server(workspace_id)?;
|
self.delete_workspace_on_server(workspace_id)?;
|
||||||
@ -236,7 +236,7 @@ pub async fn notify_workspace_setting_did_change(
|
|||||||
})
|
})
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
send_dart_notification(&token, FolderNotification::WorkspaceSetting)
|
send_notification(&token, FolderNotification::WorkspaceSetting)
|
||||||
.payload(workspace_setting)
|
.payload(workspace_setting)
|
||||||
.send();
|
.send();
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -6,7 +6,7 @@ use crate::entities::{
|
|||||||
use crate::{
|
use crate::{
|
||||||
errors::FlowyError,
|
errors::FlowyError,
|
||||||
manager::FolderManager,
|
manager::FolderManager,
|
||||||
notification::{send_dart_notification, FolderNotification},
|
notification::{send_notification, FolderNotification},
|
||||||
services::{get_current_workspace, read_local_workspace_apps, WorkspaceController},
|
services::{get_current_workspace, read_local_workspace_apps, WorkspaceController},
|
||||||
};
|
};
|
||||||
use lib_dispatch::prelude::{data_result, AFPluginData, AFPluginState, DataResult};
|
use lib_dispatch::prelude::{data_result, AFPluginData, AFPluginState, DataResult};
|
||||||
@ -151,7 +151,7 @@ fn read_workspaces_on_server(
|
|||||||
.collect(),
|
.collect(),
|
||||||
};
|
};
|
||||||
|
|
||||||
send_dart_notification(&token, FolderNotification::WorkspaceListUpdated)
|
send_notification(&token, FolderNotification::WorkspaceListUpdated)
|
||||||
.payload(repeated_workspace)
|
.payload(repeated_workspace)
|
||||||
.send();
|
.send();
|
||||||
Result::<(), FlowyError>::Ok(())
|
Result::<(), FlowyError>::Ok(())
|
||||||
|
@ -35,6 +35,6 @@ impl std::convert::From<GridDartNotification> for i32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument(level = "trace")]
|
#[tracing::instrument(level = "trace")]
|
||||||
pub fn send_dart_notification(id: &str, ty: GridDartNotification) -> NotificationBuilder {
|
pub fn send_notification(id: &str, ty: GridDartNotification) -> NotificationBuilder {
|
||||||
NotificationBuilder::new(id, ty, OBSERVABLE_CATEGORY)
|
NotificationBuilder::new(id, ty, OBSERVABLE_CATEGORY)
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::entities::{CellChangesetPB, InsertedRowPB, UpdatedRowPB};
|
use crate::entities::{CellChangesetPB, InsertedRowPB, UpdatedRowPB};
|
||||||
use crate::manager::GridUser;
|
use crate::manager::GridUser;
|
||||||
use crate::notification::{send_dart_notification, GridDartNotification};
|
use crate::notification::{send_notification, GridDartNotification};
|
||||||
use crate::services::block_editor::{GridBlockRevisionEditor, GridBlockRevisionMergeable};
|
use crate::services::block_editor::{GridBlockRevisionEditor, GridBlockRevisionMergeable};
|
||||||
use crate::services::persistence::block_index::BlockIndexCache;
|
use crate::services::persistence::block_index::BlockIndexCache;
|
||||||
use crate::services::persistence::rev_sqlite::{
|
use crate::services::persistence::rev_sqlite::{
|
||||||
@ -262,7 +262,7 @@ impl GridBlockManager {
|
|||||||
|
|
||||||
async fn notify_did_update_cell(&self, changeset: CellChangesetPB) -> FlowyResult<()> {
|
async fn notify_did_update_cell(&self, changeset: CellChangesetPB) -> FlowyResult<()> {
|
||||||
let id = format!("{}:{}", changeset.row_id, changeset.field_id);
|
let id = format!("{}:{}", changeset.row_id, changeset.field_id);
|
||||||
send_dart_notification(&id, GridDartNotification::DidUpdateCell).send();
|
send_notification(&id, GridDartNotification::DidUpdateCell).send();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::entities::CellPathParams;
|
use crate::entities::CellPathParams;
|
||||||
use crate::entities::*;
|
use crate::entities::*;
|
||||||
use crate::manager::GridUser;
|
use crate::manager::GridUser;
|
||||||
use crate::notification::{send_dart_notification, GridDartNotification};
|
use crate::notification::{send_notification, GridDartNotification};
|
||||||
use crate::services::block_manager::GridBlockManager;
|
use crate::services::block_manager::GridBlockManager;
|
||||||
use crate::services::cell::{
|
use crate::services::cell::{
|
||||||
apply_cell_data_changeset, decode_type_cell_data, stringify_cell_data, AnyTypeCache, AtomicCellDataCache,
|
apply_cell_data_changeset, decode_type_cell_data, stringify_cell_data, AnyTypeCache, AtomicCellDataCache,
|
||||||
@ -852,7 +852,7 @@ impl GridRevisionEditor {
|
|||||||
let notified_changeset = GridFieldChangesetPB::update(&self.grid_id, vec![updated_field.clone()]);
|
let notified_changeset = GridFieldChangesetPB::update(&self.grid_id, vec![updated_field.clone()]);
|
||||||
self.notify_did_update_grid(notified_changeset).await?;
|
self.notify_did_update_grid(notified_changeset).await?;
|
||||||
|
|
||||||
send_dart_notification(field_id, GridDartNotification::DidUpdateField)
|
send_notification(field_id, GridDartNotification::DidUpdateField)
|
||||||
.payload(updated_field)
|
.payload(updated_field)
|
||||||
.send();
|
.send();
|
||||||
}
|
}
|
||||||
@ -861,7 +861,7 @@ impl GridRevisionEditor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn notify_did_update_grid(&self, changeset: GridFieldChangesetPB) -> FlowyResult<()> {
|
async fn notify_did_update_grid(&self, changeset: GridFieldChangesetPB) -> FlowyResult<()> {
|
||||||
send_dart_notification(&self.grid_id, GridDartNotification::DidUpdateGridFields)
|
send_notification(&self.grid_id, GridDartNotification::DidUpdateGridFields)
|
||||||
.payload(changeset)
|
.payload(changeset)
|
||||||
.send();
|
.send();
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use crate::entities::{GridRowsVisibilityChangesetPB, ReorderAllRowsPB, ReorderSingleRowPB};
|
use crate::entities::{GridRowsVisibilityChangesetPB, ReorderAllRowsPB, ReorderSingleRowPB};
|
||||||
use crate::notification::{send_dart_notification, GridDartNotification};
|
use crate::notification::{send_notification, GridDartNotification};
|
||||||
use crate::services::filter::FilterResultNotification;
|
use crate::services::filter::FilterResultNotification;
|
||||||
use crate::services::sort::{ReorderAllRowsResult, ReorderSingleRowResult};
|
use crate::services::sort::{ReorderAllRowsResult, ReorderSingleRowResult};
|
||||||
use async_stream::stream;
|
use async_stream::stream;
|
||||||
@ -37,7 +37,7 @@ impl GridViewChangedReceiverRunner {
|
|||||||
invisible_rows: notification.invisible_rows,
|
invisible_rows: notification.invisible_rows,
|
||||||
};
|
};
|
||||||
|
|
||||||
send_dart_notification(
|
send_notification(
|
||||||
&changeset.view_id,
|
&changeset.view_id,
|
||||||
GridDartNotification::DidUpdateGridViewRowsVisibility,
|
GridDartNotification::DidUpdateGridViewRowsVisibility,
|
||||||
)
|
)
|
||||||
@ -48,7 +48,7 @@ impl GridViewChangedReceiverRunner {
|
|||||||
let row_orders = ReorderAllRowsPB {
|
let row_orders = ReorderAllRowsPB {
|
||||||
row_orders: notification.row_orders,
|
row_orders: notification.row_orders,
|
||||||
};
|
};
|
||||||
send_dart_notification(¬ification.view_id, GridDartNotification::DidReorderRows)
|
send_notification(¬ification.view_id, GridDartNotification::DidReorderRows)
|
||||||
.payload(row_orders)
|
.payload(row_orders)
|
||||||
.send()
|
.send()
|
||||||
}
|
}
|
||||||
@ -58,7 +58,7 @@ impl GridViewChangedReceiverRunner {
|
|||||||
old_index: notification.old_index as i32,
|
old_index: notification.old_index as i32,
|
||||||
new_index: notification.new_index as i32,
|
new_index: notification.new_index as i32,
|
||||||
};
|
};
|
||||||
send_dart_notification(¬ification.view_id, GridDartNotification::DidReorderSingleRow)
|
send_notification(¬ification.view_id, GridDartNotification::DidReorderSingleRow)
|
||||||
.payload(reorder_row)
|
.payload(reorder_row)
|
||||||
.send()
|
.send()
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use crate::entities::*;
|
use crate::entities::*;
|
||||||
use crate::notification::{send_dart_notification, GridDartNotification};
|
use crate::notification::{send_notification, GridDartNotification};
|
||||||
use crate::services::block_manager::GridBlockEvent;
|
use crate::services::block_manager::GridBlockEvent;
|
||||||
use crate::services::cell::{AtomicCellDataCache, TypeCellData};
|
use crate::services::cell::{AtomicCellDataCache, TypeCellData};
|
||||||
use crate::services::field::{RowSingleCellData, TypeOptionCellDataHandler};
|
use crate::services::field::{RowSingleCellData, TypeOptionCellDataHandler};
|
||||||
@ -184,7 +184,7 @@ impl GridViewRevisionEditor {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
send_dart_notification(&self.view_id, GridDartNotification::DidUpdateGridViewRows)
|
send_notification(&self.view_id, GridDartNotification::DidUpdateGridViewRows)
|
||||||
.payload(changeset)
|
.payload(changeset)
|
||||||
.send();
|
.send();
|
||||||
}
|
}
|
||||||
@ -616,7 +616,7 @@ impl GridViewRevisionEditor {
|
|||||||
|
|
||||||
debug_assert!(!changeset.is_empty());
|
debug_assert!(!changeset.is_empty());
|
||||||
if !changeset.is_empty() {
|
if !changeset.is_empty() {
|
||||||
send_dart_notification(&changeset.view_id, GridDartNotification::DidGroupByNewField)
|
send_notification(&changeset.view_id, GridDartNotification::DidGroupByNewField)
|
||||||
.payload(changeset)
|
.payload(changeset)
|
||||||
.send();
|
.send();
|
||||||
}
|
}
|
||||||
@ -630,33 +630,33 @@ impl GridViewRevisionEditor {
|
|||||||
|
|
||||||
async fn notify_did_update_setting(&self) {
|
async fn notify_did_update_setting(&self) {
|
||||||
let setting = self.get_view_setting().await;
|
let setting = self.get_view_setting().await;
|
||||||
send_dart_notification(&self.view_id, GridDartNotification::DidUpdateGridSetting)
|
send_notification(&self.view_id, GridDartNotification::DidUpdateGridSetting)
|
||||||
.payload(setting)
|
.payload(setting)
|
||||||
.send();
|
.send();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn notify_did_update_group_rows(&self, payload: GroupRowsNotificationPB) {
|
pub async fn notify_did_update_group_rows(&self, payload: GroupRowsNotificationPB) {
|
||||||
send_dart_notification(&payload.group_id, GridDartNotification::DidUpdateGroup)
|
send_notification(&payload.group_id, GridDartNotification::DidUpdateGroup)
|
||||||
.payload(payload)
|
.payload(payload)
|
||||||
.send();
|
.send();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn notify_did_update_filter(&self, notification: FilterChangesetNotificationPB) {
|
pub async fn notify_did_update_filter(&self, notification: FilterChangesetNotificationPB) {
|
||||||
send_dart_notification(¬ification.view_id, GridDartNotification::DidUpdateFilter)
|
send_notification(¬ification.view_id, GridDartNotification::DidUpdateFilter)
|
||||||
.payload(notification)
|
.payload(notification)
|
||||||
.send();
|
.send();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn notify_did_update_sort(&self, notification: SortChangesetNotificationPB) {
|
pub async fn notify_did_update_sort(&self, notification: SortChangesetNotificationPB) {
|
||||||
if !notification.is_empty() {
|
if !notification.is_empty() {
|
||||||
send_dart_notification(¬ification.view_id, GridDartNotification::DidUpdateSort)
|
send_notification(¬ification.view_id, GridDartNotification::DidUpdateSort)
|
||||||
.payload(notification)
|
.payload(notification)
|
||||||
.send();
|
.send();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn notify_did_update_view(&self, changeset: GroupViewChangesetPB) {
|
async fn notify_did_update_view(&self, changeset: GroupViewChangesetPB) {
|
||||||
send_dart_notification(&self.view_id, GridDartNotification::DidUpdateGroupView)
|
send_notification(&self.view_id, GridDartNotification::DidUpdateGroupView)
|
||||||
.payload(changeset)
|
.payload(changeset)
|
||||||
.send();
|
.send();
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ pub(crate) enum UserNotification {
|
|||||||
UserProfileUpdated = 2,
|
UserProfileUpdated = 2,
|
||||||
UserUnauthorized = 3,
|
UserUnauthorized = 3,
|
||||||
UserWsConnectStateChanged = 4,
|
UserWsConnectStateChanged = 4,
|
||||||
|
UserSignIn = 5,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::default::Default for UserNotification {
|
impl std::default::Default for UserNotification {
|
||||||
@ -23,6 +24,10 @@ impl std::convert::From<UserNotification> for i32 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn dart_notify(id: &str, ty: UserNotification) -> NotificationBuilder {
|
pub(crate) fn send_notification(id: &str, ty: UserNotification) -> NotificationBuilder {
|
||||||
NotificationBuilder::new(id, ty, OBSERVABLE_CATEGORY)
|
NotificationBuilder::new(id, ty, OBSERVABLE_CATEGORY)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn send_sign_in_notification() -> NotificationBuilder {
|
||||||
|
NotificationBuilder::new("", UserNotification::UserSignIn, OBSERVABLE_CATEGORY)
|
||||||
|
}
|
||||||
|
@ -84,7 +84,13 @@ impl UserSession {
|
|||||||
#[tracing::instrument(level = "debug", skip(self))]
|
#[tracing::instrument(level = "debug", skip(self))]
|
||||||
pub async fn sign_in(&self, params: SignInParams) -> Result<UserProfilePB, FlowyError> {
|
pub async fn sign_in(&self, params: SignInParams) -> Result<UserProfilePB, FlowyError> {
|
||||||
if self.is_user_login(¶ms.email) {
|
if self.is_user_login(¶ms.email) {
|
||||||
self.get_user_profile().await
|
match self.get_user_profile().await {
|
||||||
|
Ok(profile) => {
|
||||||
|
send_sign_in_notification().payload(profile.clone()).send();
|
||||||
|
Ok(profile)
|
||||||
|
}
|
||||||
|
Err(err) => Err(err),
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
let resp = self.cloud_service.sign_in(params).await?;
|
let resp = self.cloud_service.sign_in(params).await?;
|
||||||
let session: Session = resp.clone().into();
|
let session: Session = resp.clone().into();
|
||||||
@ -92,6 +98,7 @@ impl UserSession {
|
|||||||
let user_table = self.save_user(resp.into()).await?;
|
let user_table = self.save_user(resp.into()).await?;
|
||||||
let user_profile: UserProfilePB = user_table.into();
|
let user_profile: UserProfilePB = user_table.into();
|
||||||
self.notifier.notify_login(&user_profile.token, &user_profile.id);
|
self.notifier.notify_login(&user_profile.token, &user_profile.id);
|
||||||
|
send_sign_in_notification().payload(user_profile.clone()).send();
|
||||||
Ok(user_profile)
|
Ok(user_profile)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -134,7 +141,7 @@ impl UserSession {
|
|||||||
diesel_update_table!(user_table, changeset, &*self.db_connection()?);
|
diesel_update_table!(user_table, changeset, &*self.db_connection()?);
|
||||||
|
|
||||||
let user_profile = self.get_user_profile().await?;
|
let user_profile = self.get_user_profile().await?;
|
||||||
dart_notify(&session.token, UserNotification::UserProfileUpdated)
|
send_notification(&session.token, UserNotification::UserProfileUpdated)
|
||||||
.payload(user_profile)
|
.payload(user_profile)
|
||||||
.send();
|
.send();
|
||||||
self.update_user_on_server(&session.token, params).await?;
|
self.update_user_on_server(&session.token, params).await?;
|
||||||
|
@ -1,11 +1,5 @@
|
|||||||
[tasks.tauri_build]
|
[tasks.tauri_build]
|
||||||
script = ["""
|
description = "Build the Tauri backend & Run Code Generation"
|
||||||
cd appflowy_tauri/src-tauri
|
|
||||||
npm run tauri build
|
|
||||||
"""]
|
|
||||||
script_runner = "@shell"
|
|
||||||
|
|
||||||
[tasks.tauri_pb]
|
|
||||||
script = ["""
|
script = ["""
|
||||||
cd appflowy_tauri/src-tauri
|
cd appflowy_tauri/src-tauri
|
||||||
cargo build
|
cargo build
|
||||||
@ -20,6 +14,7 @@ script = ["""
|
|||||||
script_runner = "@shell"
|
script_runner = "@shell"
|
||||||
|
|
||||||
[tasks.tauri_clean]
|
[tasks.tauri_clean]
|
||||||
|
description = "Remove all the building artifacts"
|
||||||
run_task = { name = [
|
run_task = { name = [
|
||||||
"rust_lib_clean",
|
"rust_lib_clean",
|
||||||
"rm_macro_build_cache",
|
"rm_macro_build_cache",
|
||||||
|
Reference in New Issue
Block a user