mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
Merge branch 'main' into feat/history
This commit is contained in:
@ -33,6 +33,7 @@ lazy_static = "1.4.0"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
tracing = { version = "0.1", features = ["log"] }
|
||||
bytes = { version = "1.0" }
|
||||
unicode-segmentation = "1.8"
|
||||
|
||||
[dev-dependencies]
|
||||
serde_json = "1.0"
|
||||
|
@ -1,3 +1,3 @@
|
||||
|
||||
proto_crates = ["src/entities", "src/event_map.rs", "src/dart_notification.rs"]
|
||||
# Check out the FlowyConfig (located in flowy_toml.rs) for more details.
|
||||
proto_input = ["src/entities", "src/event_map.rs", "src/dart_notification.rs"]
|
||||
event_files = ["src/event_map.rs"]
|
@ -2,7 +2,7 @@ use lib_infra::code_gen;
|
||||
|
||||
fn main() {
|
||||
let crate_name = env!("CARGO_PKG_NAME");
|
||||
code_gen::protobuf_file::gen(crate_name, "./src/protobuf/proto");
|
||||
code_gen::protobuf_file::gen(crate_name);
|
||||
|
||||
#[cfg(feature = "dart")]
|
||||
code_gen::dart_event::gen(crate_name);
|
||||
|
219
frontend/rust-lib/flowy-folder/src/entities/app.rs
Normal file
219
frontend/rust-lib/flowy-folder/src/entities/app.rs
Normal file
@ -0,0 +1,219 @@
|
||||
use crate::{
|
||||
entities::parser::{
|
||||
app::{AppColorStyle, AppIdentify, AppName},
|
||||
workspace::WorkspaceIdentify,
|
||||
},
|
||||
entities::view::RepeatedViewPB,
|
||||
errors::ErrorCode,
|
||||
impl_def_and_def_mut,
|
||||
};
|
||||
use flowy_derive::ProtoBuf;
|
||||
use flowy_folder_data_model::revision::AppRevision;
|
||||
use std::convert::TryInto;
|
||||
|
||||
#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]
|
||||
pub struct AppPB {
|
||||
#[pb(index = 1)]
|
||||
pub id: String,
|
||||
|
||||
#[pb(index = 2)]
|
||||
pub workspace_id: String,
|
||||
|
||||
#[pb(index = 3)]
|
||||
pub name: String,
|
||||
|
||||
#[pb(index = 4)]
|
||||
pub desc: String,
|
||||
|
||||
#[pb(index = 5)]
|
||||
pub belongings: RepeatedViewPB,
|
||||
|
||||
#[pb(index = 6)]
|
||||
pub version: i64,
|
||||
|
||||
#[pb(index = 7)]
|
||||
pub modified_time: i64,
|
||||
|
||||
#[pb(index = 8)]
|
||||
pub create_time: i64,
|
||||
}
|
||||
|
||||
impl std::convert::From<AppRevision> for AppPB {
|
||||
fn from(app_serde: AppRevision) -> Self {
|
||||
AppPB {
|
||||
id: app_serde.id,
|
||||
workspace_id: app_serde.workspace_id,
|
||||
name: app_serde.name,
|
||||
desc: app_serde.desc,
|
||||
belongings: app_serde.belongings.into(),
|
||||
version: app_serde.version,
|
||||
modified_time: app_serde.modified_time,
|
||||
create_time: app_serde.create_time,
|
||||
}
|
||||
}
|
||||
}
|
||||
#[derive(Eq, PartialEq, Debug, Default, ProtoBuf, Clone)]
|
||||
pub struct RepeatedAppPB {
|
||||
#[pb(index = 1)]
|
||||
pub items: Vec<AppPB>,
|
||||
}
|
||||
|
||||
impl_def_and_def_mut!(RepeatedAppPB, AppPB);
|
||||
|
||||
impl std::convert::From<Vec<AppRevision>> for RepeatedAppPB {
|
||||
fn from(values: Vec<AppRevision>) -> Self {
|
||||
let items = values.into_iter().map(|value| value.into()).collect::<Vec<AppPB>>();
|
||||
RepeatedAppPB { items }
|
||||
}
|
||||
}
|
||||
#[derive(ProtoBuf, Default)]
|
||||
pub struct CreateAppPayloadPB {
|
||||
#[pb(index = 1)]
|
||||
pub workspace_id: String,
|
||||
|
||||
#[pb(index = 2)]
|
||||
pub name: String,
|
||||
|
||||
#[pb(index = 3)]
|
||||
pub desc: String,
|
||||
|
||||
#[pb(index = 4)]
|
||||
pub color_style: ColorStylePB,
|
||||
}
|
||||
|
||||
#[derive(ProtoBuf, Default, Debug, Clone)]
|
||||
pub struct ColorStylePB {
|
||||
#[pb(index = 1)]
|
||||
pub theme_color: String,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct CreateAppParams {
|
||||
pub workspace_id: String,
|
||||
pub name: String,
|
||||
pub desc: String,
|
||||
pub color_style: ColorStylePB,
|
||||
}
|
||||
|
||||
impl TryInto<CreateAppParams> for CreateAppPayloadPB {
|
||||
type Error = ErrorCode;
|
||||
|
||||
fn try_into(self) -> Result<CreateAppParams, Self::Error> {
|
||||
let name = AppName::parse(self.name)?;
|
||||
let id = WorkspaceIdentify::parse(self.workspace_id)?;
|
||||
let color_style = AppColorStyle::parse(self.color_style.theme_color.clone())?;
|
||||
|
||||
Ok(CreateAppParams {
|
||||
workspace_id: id.0,
|
||||
name: name.0,
|
||||
desc: self.desc,
|
||||
color_style: color_style.into(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::From<AppColorStyle> for ColorStylePB {
|
||||
fn from(data: AppColorStyle) -> Self {
|
||||
ColorStylePB {
|
||||
theme_color: data.theme_color,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(ProtoBuf, Default, Clone, Debug)]
|
||||
pub struct AppIdPB {
|
||||
#[pb(index = 1)]
|
||||
pub value: String,
|
||||
}
|
||||
|
||||
impl AppIdPB {
|
||||
pub fn new(app_id: &str) -> Self {
|
||||
Self {
|
||||
value: app_id.to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(ProtoBuf, Default)]
|
||||
pub struct UpdateAppPayloadPB {
|
||||
#[pb(index = 1)]
|
||||
pub app_id: String,
|
||||
|
||||
#[pb(index = 2, one_of)]
|
||||
pub name: Option<String>,
|
||||
|
||||
#[pb(index = 3, one_of)]
|
||||
pub desc: Option<String>,
|
||||
|
||||
#[pb(index = 4, one_of)]
|
||||
pub color_style: Option<ColorStylePB>,
|
||||
|
||||
#[pb(index = 5, one_of)]
|
||||
pub is_trash: Option<bool>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct UpdateAppParams {
|
||||
pub app_id: String,
|
||||
|
||||
pub name: Option<String>,
|
||||
|
||||
pub desc: Option<String>,
|
||||
|
||||
pub color_style: Option<ColorStylePB>,
|
||||
|
||||
pub is_trash: Option<bool>,
|
||||
}
|
||||
|
||||
impl UpdateAppParams {
|
||||
pub fn new(app_id: &str) -> Self {
|
||||
Self {
|
||||
app_id: app_id.to_string(),
|
||||
name: None,
|
||||
desc: None,
|
||||
color_style: None,
|
||||
is_trash: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn name(mut self, name: &str) -> Self {
|
||||
self.name = Some(name.to_string());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn desc(mut self, desc: &str) -> Self {
|
||||
self.desc = Some(desc.to_string());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn trash(mut self) -> Self {
|
||||
self.is_trash = Some(true);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl TryInto<UpdateAppParams> for UpdateAppPayloadPB {
|
||||
type Error = ErrorCode;
|
||||
|
||||
fn try_into(self) -> Result<UpdateAppParams, Self::Error> {
|
||||
let app_id = AppIdentify::parse(self.app_id)?.0;
|
||||
|
||||
let name = match self.name {
|
||||
None => None,
|
||||
Some(name) => Some(AppName::parse(name)?.0),
|
||||
};
|
||||
|
||||
let color_style = match self.color_style {
|
||||
None => None,
|
||||
Some(color_style) => Some(AppColorStyle::parse(color_style.theme_color)?.into()),
|
||||
};
|
||||
|
||||
Ok(UpdateAppParams {
|
||||
app_id,
|
||||
name,
|
||||
desc: self.desc,
|
||||
color_style,
|
||||
is_trash: self.is_trash,
|
||||
})
|
||||
}
|
||||
}
|
12
frontend/rust-lib/flowy-folder/src/entities/mod.rs
Normal file
12
frontend/rust-lib/flowy-folder/src/entities/mod.rs
Normal file
@ -0,0 +1,12 @@
|
||||
pub mod app;
|
||||
mod parser;
|
||||
pub mod trash;
|
||||
pub mod view;
|
||||
mod view_info;
|
||||
pub mod workspace;
|
||||
|
||||
pub use app::*;
|
||||
pub use trash::*;
|
||||
pub use view::*;
|
||||
pub use view_info::*;
|
||||
pub use workspace::*;
|
@ -0,0 +1,13 @@
|
||||
use crate::errors::ErrorCode;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct AppColorStyle {
|
||||
pub theme_color: String,
|
||||
}
|
||||
|
||||
impl AppColorStyle {
|
||||
pub fn parse(theme_color: String) -> Result<AppColorStyle, ErrorCode> {
|
||||
// TODO: verify the color style format
|
||||
Ok(AppColorStyle { theme_color })
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
use unicode_segmentation::UnicodeSegmentation;
|
||||
#[derive(Debug)]
|
||||
pub struct AppDesc(pub String);
|
||||
|
||||
impl AppDesc {
|
||||
#[allow(dead_code)]
|
||||
pub fn parse(s: String) -> Result<AppDesc, String> {
|
||||
if s.graphemes(true).count() > 1024 {
|
||||
return Err("Workspace description too long".to_string());
|
||||
}
|
||||
|
||||
Ok(Self(s))
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<str> for AppDesc {
|
||||
fn as_ref(&self) -> &str {
|
||||
&self.0
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
use crate::errors::ErrorCode;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct AppIdentify(pub String);
|
||||
|
||||
impl AppIdentify {
|
||||
pub fn parse(s: String) -> Result<AppIdentify, ErrorCode> {
|
||||
if s.trim().is_empty() {
|
||||
return Err(ErrorCode::AppIdInvalid);
|
||||
}
|
||||
|
||||
Ok(Self(s))
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<str> for AppIdentify {
|
||||
fn as_ref(&self) -> &str {
|
||||
&self.0
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
use crate::errors::ErrorCode;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct AppName(pub String);
|
||||
|
||||
impl AppName {
|
||||
pub fn parse(s: String) -> Result<AppName, ErrorCode> {
|
||||
if s.trim().is_empty() {
|
||||
return Err(ErrorCode::AppNameInvalid);
|
||||
}
|
||||
|
||||
Ok(Self(s))
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<str> for AppName {
|
||||
fn as_ref(&self) -> &str {
|
||||
&self.0
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
mod app_color_style;
|
||||
mod app_desc;
|
||||
mod app_id;
|
||||
mod app_name;
|
||||
|
||||
pub use app_color_style::*;
|
||||
pub use app_desc::*;
|
||||
pub use app_id::*;
|
||||
pub use app_name::*;
|
@ -0,0 +1,4 @@
|
||||
pub mod app;
|
||||
pub mod trash;
|
||||
pub mod view;
|
||||
pub mod workspace;
|
@ -0,0 +1,3 @@
|
||||
mod trash_id;
|
||||
|
||||
pub use trash_id::*;
|
@ -0,0 +1,34 @@
|
||||
#[derive(Debug)]
|
||||
pub struct TrashIdentify(pub String);
|
||||
|
||||
impl TrashIdentify {
|
||||
#[allow(dead_code)]
|
||||
pub fn parse(s: String) -> Result<TrashIdentify, String> {
|
||||
if s.trim().is_empty() {
|
||||
return Err("Trash id can not be empty or whitespace".to_string());
|
||||
}
|
||||
|
||||
Ok(Self(s))
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<str> for TrashIdentify {
|
||||
fn as_ref(&self) -> &str {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct TrashIds(pub Vec<String>);
|
||||
|
||||
impl TrashIds {
|
||||
#[allow(dead_code)]
|
||||
pub fn parse(ids: Vec<String>) -> Result<TrashIds, String> {
|
||||
let mut trash_ids = vec![];
|
||||
for id in ids {
|
||||
let id = TrashIdentify::parse(id)?;
|
||||
trash_ids.push(id.0);
|
||||
}
|
||||
Ok(Self(trash_ids))
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
mod view_desc;
|
||||
mod view_id;
|
||||
mod view_name;
|
||||
mod view_thumbnail;
|
||||
|
||||
pub use view_desc::*;
|
||||
pub use view_id::*;
|
||||
pub use view_name::*;
|
||||
pub use view_thumbnail::*;
|
@ -0,0 +1,21 @@
|
||||
use crate::errors::ErrorCode;
|
||||
use unicode_segmentation::UnicodeSegmentation;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ViewDesc(pub String);
|
||||
|
||||
impl ViewDesc {
|
||||
pub fn parse(s: String) -> Result<ViewDesc, ErrorCode> {
|
||||
if s.graphemes(true).count() > 1000 {
|
||||
return Err(ErrorCode::ViewDescTooLong);
|
||||
}
|
||||
|
||||
Ok(Self(s))
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<str> for ViewDesc {
|
||||
fn as_ref(&self) -> &str {
|
||||
&self.0
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
use crate::errors::ErrorCode;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ViewIdentify(pub String);
|
||||
|
||||
impl ViewIdentify {
|
||||
pub fn parse(s: String) -> Result<ViewIdentify, ErrorCode> {
|
||||
if s.trim().is_empty() {
|
||||
return Err(ErrorCode::ViewIdInvalid);
|
||||
}
|
||||
|
||||
Ok(Self(s))
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<str> for ViewIdentify {
|
||||
fn as_ref(&self) -> &str {
|
||||
&self.0
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
use crate::errors::ErrorCode;
|
||||
use unicode_segmentation::UnicodeSegmentation;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ViewName(pub String);
|
||||
|
||||
impl ViewName {
|
||||
pub fn parse(s: String) -> Result<ViewName, ErrorCode> {
|
||||
if s.trim().is_empty() {
|
||||
return Err(ErrorCode::ViewNameInvalid);
|
||||
}
|
||||
|
||||
if s.graphemes(true).count() > 256 {
|
||||
return Err(ErrorCode::ViewNameTooLong);
|
||||
}
|
||||
|
||||
Ok(Self(s))
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<str> for ViewName {
|
||||
fn as_ref(&self) -> &str {
|
||||
&self.0
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
use crate::errors::ErrorCode;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ViewThumbnail(pub String);
|
||||
|
||||
impl ViewThumbnail {
|
||||
pub fn parse(s: String) -> Result<ViewThumbnail, ErrorCode> {
|
||||
// if s.trim().is_empty() {
|
||||
// return Err(format!("View thumbnail can not be empty or whitespace"));
|
||||
// }
|
||||
// TODO: verify the thumbnail url is valid or not
|
||||
|
||||
Ok(Self(s))
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<str> for ViewThumbnail {
|
||||
fn as_ref(&self) -> &str {
|
||||
&self.0
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
mod workspace_desc;
|
||||
mod workspace_id;
|
||||
mod workspace_name;
|
||||
|
||||
pub use workspace_desc::*;
|
||||
pub use workspace_id::*;
|
||||
pub use workspace_name::*;
|
@ -0,0 +1,21 @@
|
||||
use crate::errors::ErrorCode;
|
||||
use unicode_segmentation::UnicodeSegmentation;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct WorkspaceDesc(pub String);
|
||||
|
||||
impl WorkspaceDesc {
|
||||
pub fn parse(s: String) -> Result<WorkspaceDesc, ErrorCode> {
|
||||
if s.graphemes(true).count() > 1024 {
|
||||
return Err(ErrorCode::WorkspaceNameTooLong);
|
||||
}
|
||||
|
||||
Ok(Self(s))
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<str> for WorkspaceDesc {
|
||||
fn as_ref(&self) -> &str {
|
||||
&self.0
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
use crate::errors::ErrorCode;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct WorkspaceIdentify(pub String);
|
||||
|
||||
impl WorkspaceIdentify {
|
||||
pub fn parse(s: String) -> Result<WorkspaceIdentify, ErrorCode> {
|
||||
if s.trim().is_empty() {
|
||||
return Err(ErrorCode::WorkspaceIdInvalid);
|
||||
}
|
||||
|
||||
Ok(Self(s))
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<str> for WorkspaceIdentify {
|
||||
fn as_ref(&self) -> &str {
|
||||
&self.0
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
use crate::errors::ErrorCode;
|
||||
use unicode_segmentation::UnicodeSegmentation;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct WorkspaceName(pub String);
|
||||
|
||||
impl WorkspaceName {
|
||||
pub fn parse(s: String) -> Result<WorkspaceName, ErrorCode> {
|
||||
if s.trim().is_empty() {
|
||||
return Err(ErrorCode::WorkspaceNameInvalid);
|
||||
}
|
||||
|
||||
if s.graphemes(true).count() > 256 {
|
||||
return Err(ErrorCode::WorkspaceNameTooLong);
|
||||
}
|
||||
|
||||
Ok(Self(s))
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<str> for WorkspaceName {
|
||||
fn as_ref(&self) -> &str {
|
||||
&self.0
|
||||
}
|
||||
}
|
183
frontend/rust-lib/flowy-folder/src/entities/trash.rs
Normal file
183
frontend/rust-lib/flowy-folder/src/entities/trash.rs
Normal file
@ -0,0 +1,183 @@
|
||||
use crate::impl_def_and_def_mut;
|
||||
use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
|
||||
use flowy_folder_data_model::revision::{TrashRevision, TrashTypeRevision};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt::Formatter;
|
||||
|
||||
#[derive(Eq, PartialEq, ProtoBuf, Default, Debug, Clone)]
|
||||
pub struct TrashPB {
|
||||
#[pb(index = 1)]
|
||||
pub id: String,
|
||||
|
||||
#[pb(index = 2)]
|
||||
pub name: String,
|
||||
|
||||
#[pb(index = 3)]
|
||||
pub modified_time: i64,
|
||||
|
||||
#[pb(index = 4)]
|
||||
pub create_time: i64,
|
||||
|
||||
#[pb(index = 5)]
|
||||
pub ty: TrashType,
|
||||
}
|
||||
|
||||
impl std::convert::From<TrashRevision> for TrashPB {
|
||||
fn from(trash_rev: TrashRevision) -> Self {
|
||||
TrashPB {
|
||||
id: trash_rev.id,
|
||||
name: trash_rev.name,
|
||||
modified_time: trash_rev.modified_time,
|
||||
create_time: trash_rev.create_time,
|
||||
ty: trash_rev.ty.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::From<TrashPB> for TrashRevision {
|
||||
fn from(trash: TrashPB) -> Self {
|
||||
TrashRevision {
|
||||
id: trash.id,
|
||||
name: trash.name,
|
||||
modified_time: trash.modified_time,
|
||||
create_time: trash.create_time,
|
||||
ty: trash.ty.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
#[derive(PartialEq, Debug, Default, ProtoBuf, Clone)]
|
||||
pub struct RepeatedTrashPB {
|
||||
#[pb(index = 1)]
|
||||
pub items: Vec<TrashPB>,
|
||||
}
|
||||
|
||||
impl_def_and_def_mut!(RepeatedTrashPB, TrashPB);
|
||||
impl std::convert::From<Vec<TrashRevision>> for RepeatedTrashPB {
|
||||
fn from(trash_revs: Vec<TrashRevision>) -> Self {
|
||||
let items: Vec<TrashPB> = trash_revs.into_iter().map(|trash_rev| trash_rev.into()).collect();
|
||||
RepeatedTrashPB { items }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Eq, PartialEq, Debug, ProtoBuf_Enum, Clone, Serialize, Deserialize)]
|
||||
pub enum TrashType {
|
||||
TrashUnknown = 0,
|
||||
TrashView = 1,
|
||||
TrashApp = 2,
|
||||
}
|
||||
|
||||
impl std::convert::TryFrom<i32> for TrashType {
|
||||
type Error = String;
|
||||
|
||||
fn try_from(value: i32) -> Result<Self, Self::Error> {
|
||||
match value {
|
||||
0 => Ok(TrashType::TrashUnknown),
|
||||
1 => Ok(TrashType::TrashView),
|
||||
2 => Ok(TrashType::TrashApp),
|
||||
_ => Err(format!("Invalid trash type: {}", value)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::From<TrashTypeRevision> for TrashType {
|
||||
fn from(rev: TrashTypeRevision) -> Self {
|
||||
match rev {
|
||||
TrashTypeRevision::Unknown => TrashType::TrashUnknown,
|
||||
TrashTypeRevision::TrashView => TrashType::TrashView,
|
||||
TrashTypeRevision::TrashApp => TrashType::TrashApp,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::From<TrashType> for TrashTypeRevision {
|
||||
fn from(rev: TrashType) -> Self {
|
||||
match rev {
|
||||
TrashType::TrashUnknown => TrashTypeRevision::Unknown,
|
||||
TrashType::TrashView => TrashTypeRevision::TrashView,
|
||||
TrashType::TrashApp => TrashTypeRevision::TrashApp,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::default::Default for TrashType {
|
||||
fn default() -> Self {
|
||||
TrashType::TrashUnknown
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, ProtoBuf, Default, Debug, Clone)]
|
||||
pub struct RepeatedTrashIdPB {
|
||||
#[pb(index = 1)]
|
||||
pub items: Vec<TrashIdPB>,
|
||||
|
||||
#[pb(index = 2)]
|
||||
pub delete_all: bool,
|
||||
}
|
||||
|
||||
impl std::fmt::Display for RepeatedTrashIdPB {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
f.write_str(&format!(
|
||||
"{:?}",
|
||||
&self.items.iter().map(|item| format!("{}", item)).collect::<Vec<_>>()
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
impl RepeatedTrashIdPB {
|
||||
pub fn all() -> RepeatedTrashIdPB {
|
||||
RepeatedTrashIdPB {
|
||||
items: vec![],
|
||||
delete_all: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::From<Vec<TrashIdPB>> for RepeatedTrashIdPB {
|
||||
fn from(items: Vec<TrashIdPB>) -> Self {
|
||||
RepeatedTrashIdPB {
|
||||
items,
|
||||
delete_all: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::From<Vec<TrashRevision>> for RepeatedTrashIdPB {
|
||||
fn from(trash: Vec<TrashRevision>) -> Self {
|
||||
let items = trash
|
||||
.into_iter()
|
||||
.map(|t| TrashIdPB {
|
||||
id: t.id,
|
||||
ty: t.ty.into(),
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
RepeatedTrashIdPB {
|
||||
items,
|
||||
delete_all: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, ProtoBuf, Default, Debug, Clone)]
|
||||
pub struct TrashIdPB {
|
||||
#[pb(index = 1)]
|
||||
pub id: String,
|
||||
|
||||
#[pb(index = 2)]
|
||||
pub ty: TrashType,
|
||||
}
|
||||
|
||||
impl std::fmt::Display for TrashIdPB {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
f.write_str(&format!("{:?}:{}", self.ty, self.id))
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::From<&TrashRevision> for TrashIdPB {
|
||||
fn from(trash: &TrashRevision) -> Self {
|
||||
TrashIdPB {
|
||||
id: trash.id.clone(),
|
||||
ty: trash.ty.clone().into(),
|
||||
}
|
||||
}
|
||||
}
|
339
frontend/rust-lib/flowy-folder/src/entities/view.rs
Normal file
339
frontend/rust-lib/flowy-folder/src/entities/view.rs
Normal file
@ -0,0 +1,339 @@
|
||||
use crate::{
|
||||
entities::parser::{
|
||||
app::AppIdentify,
|
||||
view::{ViewDesc, ViewIdentify, ViewName, ViewThumbnail},
|
||||
},
|
||||
errors::ErrorCode,
|
||||
impl_def_and_def_mut,
|
||||
};
|
||||
use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
|
||||
use flowy_folder_data_model::revision::{gen_view_id, ViewDataTypeRevision, ViewRevision};
|
||||
use std::convert::TryInto;
|
||||
|
||||
#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]
|
||||
pub struct ViewPB {
|
||||
#[pb(index = 1)]
|
||||
pub id: String,
|
||||
|
||||
#[pb(index = 2)]
|
||||
pub belong_to_id: String,
|
||||
|
||||
#[pb(index = 3)]
|
||||
pub name: String,
|
||||
|
||||
#[pb(index = 4)]
|
||||
pub data_type: ViewDataType,
|
||||
|
||||
#[pb(index = 5)]
|
||||
pub modified_time: i64,
|
||||
|
||||
#[pb(index = 6)]
|
||||
pub create_time: i64,
|
||||
|
||||
#[pb(index = 7)]
|
||||
pub plugin_type: i32,
|
||||
}
|
||||
|
||||
impl std::convert::From<ViewRevision> for ViewPB {
|
||||
fn from(rev: ViewRevision) -> Self {
|
||||
ViewPB {
|
||||
id: rev.id,
|
||||
belong_to_id: rev.belong_to_id,
|
||||
name: rev.name,
|
||||
data_type: rev.data_type.into(),
|
||||
modified_time: rev.modified_time,
|
||||
create_time: rev.create_time,
|
||||
plugin_type: rev.plugin_type,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Eq, PartialEq, Hash, Debug, ProtoBuf_Enum, Clone)]
|
||||
pub enum ViewDataType {
|
||||
TextBlock = 0,
|
||||
Grid = 1,
|
||||
}
|
||||
|
||||
impl std::default::Default for ViewDataType {
|
||||
fn default() -> Self {
|
||||
ViewDataTypeRevision::default().into()
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::From<ViewDataTypeRevision> for ViewDataType {
|
||||
fn from(rev: ViewDataTypeRevision) -> Self {
|
||||
match rev {
|
||||
ViewDataTypeRevision::TextBlock => ViewDataType::TextBlock,
|
||||
ViewDataTypeRevision::Grid => ViewDataType::Grid,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::From<ViewDataType> for ViewDataTypeRevision {
|
||||
fn from(ty: ViewDataType) -> Self {
|
||||
match ty {
|
||||
ViewDataType::TextBlock => ViewDataTypeRevision::TextBlock,
|
||||
ViewDataType::Grid => ViewDataTypeRevision::Grid,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Eq, PartialEq, Debug, Default, ProtoBuf, Clone)]
|
||||
pub struct RepeatedViewPB {
|
||||
#[pb(index = 1)]
|
||||
pub items: Vec<ViewPB>,
|
||||
}
|
||||
|
||||
impl_def_and_def_mut!(RepeatedViewPB, ViewPB);
|
||||
|
||||
impl std::convert::From<Vec<ViewRevision>> for RepeatedViewPB {
|
||||
fn from(values: Vec<ViewRevision>) -> Self {
|
||||
let items = values.into_iter().map(|value| value.into()).collect::<Vec<ViewPB>>();
|
||||
RepeatedViewPB { items }
|
||||
}
|
||||
}
|
||||
#[derive(Default, ProtoBuf)]
|
||||
pub struct RepeatedViewIdPB {
|
||||
#[pb(index = 1)]
|
||||
pub items: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Default, ProtoBuf)]
|
||||
pub struct CreateViewPayloadPB {
|
||||
#[pb(index = 1)]
|
||||
pub belong_to_id: String,
|
||||
|
||||
#[pb(index = 2)]
|
||||
pub name: String,
|
||||
|
||||
#[pb(index = 3)]
|
||||
pub desc: String,
|
||||
|
||||
#[pb(index = 4, one_of)]
|
||||
pub thumbnail: Option<String>,
|
||||
|
||||
#[pb(index = 5)]
|
||||
pub data_type: ViewDataType,
|
||||
|
||||
#[pb(index = 6)]
|
||||
pub plugin_type: i32,
|
||||
|
||||
#[pb(index = 7)]
|
||||
pub data: Vec<u8>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct CreateViewParams {
|
||||
pub belong_to_id: String,
|
||||
pub name: String,
|
||||
pub desc: String,
|
||||
pub thumbnail: String,
|
||||
pub data_type: ViewDataType,
|
||||
pub view_id: String,
|
||||
pub data: Vec<u8>,
|
||||
pub plugin_type: i32,
|
||||
}
|
||||
|
||||
impl TryInto<CreateViewParams> for CreateViewPayloadPB {
|
||||
type Error = ErrorCode;
|
||||
|
||||
fn try_into(self) -> Result<CreateViewParams, Self::Error> {
|
||||
let name = ViewName::parse(self.name)?.0;
|
||||
let belong_to_id = AppIdentify::parse(self.belong_to_id)?.0;
|
||||
let view_id = gen_view_id();
|
||||
let thumbnail = match self.thumbnail {
|
||||
None => "".to_string(),
|
||||
Some(thumbnail) => ViewThumbnail::parse(thumbnail)?.0,
|
||||
};
|
||||
|
||||
Ok(CreateViewParams {
|
||||
belong_to_id,
|
||||
name,
|
||||
desc: self.desc,
|
||||
data_type: self.data_type,
|
||||
thumbnail,
|
||||
view_id,
|
||||
data: self.data,
|
||||
plugin_type: self.plugin_type,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, ProtoBuf, Clone, Debug)]
|
||||
pub struct ViewIdPB {
|
||||
#[pb(index = 1)]
|
||||
pub value: String,
|
||||
}
|
||||
|
||||
impl std::convert::From<&str> for ViewIdPB {
|
||||
fn from(value: &str) -> Self {
|
||||
ViewIdPB {
|
||||
value: value.to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Deref for ViewIdPB {
|
||||
type Target = str;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.value
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, ProtoBuf)]
|
||||
pub struct UpdateViewPayloadPB {
|
||||
#[pb(index = 1)]
|
||||
pub view_id: String,
|
||||
|
||||
#[pb(index = 2, one_of)]
|
||||
pub name: Option<String>,
|
||||
|
||||
#[pb(index = 3, one_of)]
|
||||
pub desc: Option<String>,
|
||||
|
||||
#[pb(index = 4, one_of)]
|
||||
pub thumbnail: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct UpdateViewParams {
|
||||
pub view_id: String,
|
||||
pub name: Option<String>,
|
||||
pub desc: Option<String>,
|
||||
pub thumbnail: Option<String>,
|
||||
}
|
||||
|
||||
impl TryInto<UpdateViewParams> for UpdateViewPayloadPB {
|
||||
type Error = ErrorCode;
|
||||
|
||||
fn try_into(self) -> Result<UpdateViewParams, Self::Error> {
|
||||
let view_id = ViewIdentify::parse(self.view_id)?.0;
|
||||
|
||||
let name = match self.name {
|
||||
None => None,
|
||||
Some(name) => Some(ViewName::parse(name)?.0),
|
||||
};
|
||||
|
||||
let desc = match self.desc {
|
||||
None => None,
|
||||
Some(desc) => Some(ViewDesc::parse(desc)?.0),
|
||||
};
|
||||
|
||||
let thumbnail = match self.thumbnail {
|
||||
None => None,
|
||||
Some(thumbnail) => Some(ViewThumbnail::parse(thumbnail)?.0),
|
||||
};
|
||||
|
||||
Ok(UpdateViewParams {
|
||||
view_id,
|
||||
name,
|
||||
desc,
|
||||
thumbnail,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(ProtoBuf_Enum)]
|
||||
pub enum MoveFolderItemType {
|
||||
MoveApp = 0,
|
||||
MoveView = 1,
|
||||
}
|
||||
|
||||
impl std::default::Default for MoveFolderItemType {
|
||||
fn default() -> Self {
|
||||
MoveFolderItemType::MoveApp
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, ProtoBuf)]
|
||||
pub struct MoveFolderItemPayloadPB {
|
||||
#[pb(index = 1)]
|
||||
pub item_id: String,
|
||||
|
||||
#[pb(index = 2)]
|
||||
pub from: i32,
|
||||
|
||||
#[pb(index = 3)]
|
||||
pub to: i32,
|
||||
|
||||
#[pb(index = 4)]
|
||||
pub ty: MoveFolderItemType,
|
||||
}
|
||||
|
||||
pub struct MoveFolderItemParams {
|
||||
pub item_id: String,
|
||||
pub from: usize,
|
||||
pub to: usize,
|
||||
pub ty: MoveFolderItemType,
|
||||
}
|
||||
|
||||
impl TryInto<MoveFolderItemParams> for MoveFolderItemPayloadPB {
|
||||
type Error = ErrorCode;
|
||||
|
||||
fn try_into(self) -> Result<MoveFolderItemParams, Self::Error> {
|
||||
let view_id = ViewIdentify::parse(self.item_id)?.0;
|
||||
Ok(MoveFolderItemParams {
|
||||
item_id: view_id,
|
||||
from: self.from as usize,
|
||||
to: self.to as usize,
|
||||
ty: self.ty,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// impl<'de> Deserialize<'de> for ViewDataType {
|
||||
// fn deserialize<D>(deserializer: D) -> Result<Self, <D as Deserializer<'de>>::Error>
|
||||
// where
|
||||
// D: Deserializer<'de>,
|
||||
// {
|
||||
// struct ViewTypeVisitor();
|
||||
//
|
||||
// impl<'de> Visitor<'de> for ViewTypeVisitor {
|
||||
// type Value = ViewDataType;
|
||||
// fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
// formatter.write_str("RichText, PlainText")
|
||||
// }
|
||||
//
|
||||
// fn visit_u8<E>(self, v: u8) -> Result<Self::Value, E>
|
||||
// where
|
||||
// E: de::Error,
|
||||
// {
|
||||
// let data_type;
|
||||
// match v {
|
||||
// 0 => {
|
||||
// data_type = ViewDataType::RichText;
|
||||
// }
|
||||
// 1 => {
|
||||
// data_type = ViewDataType::PlainText;
|
||||
// }
|
||||
// _ => {
|
||||
// return Err(de::Error::invalid_value(Unexpected::Unsigned(v as u64), &self));
|
||||
// }
|
||||
// }
|
||||
// Ok(data_type)
|
||||
// }
|
||||
//
|
||||
// fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
|
||||
// where
|
||||
// E: de::Error,
|
||||
// {
|
||||
// let data_type;
|
||||
// match s {
|
||||
// "Doc" | "RichText" => {
|
||||
// // Rename ViewDataType::Doc to ViewDataType::RichText, So we need to migrate the ViewType manually.
|
||||
// data_type = ViewDataType::RichText;
|
||||
// }
|
||||
// "PlainText" => {
|
||||
// data_type = ViewDataType::PlainText;
|
||||
// }
|
||||
// unknown => {
|
||||
// return Err(de::Error::invalid_value(Unexpected::Str(unknown), &self));
|
||||
// }
|
||||
// }
|
||||
// Ok(data_type)
|
||||
// }
|
||||
// }
|
||||
// deserializer.deserialize_any(ViewTypeVisitor())
|
||||
// }
|
||||
// }
|
26
frontend/rust-lib/flowy-folder/src/entities/view_info.rs
Normal file
26
frontend/rust-lib/flowy-folder/src/entities/view_info.rs
Normal file
@ -0,0 +1,26 @@
|
||||
use crate::entities::{RepeatedViewPB, ViewDataType};
|
||||
use flowy_derive::ProtoBuf;
|
||||
|
||||
#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]
|
||||
pub struct ViewInfoPB {
|
||||
#[pb(index = 1)]
|
||||
pub id: String,
|
||||
|
||||
#[pb(index = 2)]
|
||||
pub belong_to_id: String,
|
||||
|
||||
#[pb(index = 3)]
|
||||
pub name: String,
|
||||
|
||||
#[pb(index = 4)]
|
||||
pub desc: String,
|
||||
|
||||
#[pb(index = 5)]
|
||||
pub data_type: ViewDataType,
|
||||
|
||||
#[pb(index = 6)]
|
||||
pub belongings: RepeatedViewPB,
|
||||
|
||||
#[pb(index = 7)]
|
||||
pub ext_data: String,
|
||||
}
|
138
frontend/rust-lib/flowy-folder/src/entities/workspace.rs
Normal file
138
frontend/rust-lib/flowy-folder/src/entities/workspace.rs
Normal file
@ -0,0 +1,138 @@
|
||||
use crate::{
|
||||
entities::parser::workspace::{WorkspaceDesc, WorkspaceIdentify, WorkspaceName},
|
||||
entities::{app::RepeatedAppPB, view::ViewPB},
|
||||
errors::*,
|
||||
impl_def_and_def_mut,
|
||||
};
|
||||
use flowy_derive::ProtoBuf;
|
||||
use flowy_folder_data_model::revision::WorkspaceRevision;
|
||||
use std::convert::TryInto;
|
||||
|
||||
#[derive(Eq, PartialEq, ProtoBuf, Default, Debug, Clone)]
|
||||
pub struct WorkspacePB {
|
||||
#[pb(index = 1)]
|
||||
pub id: String,
|
||||
|
||||
#[pb(index = 2)]
|
||||
pub name: String,
|
||||
|
||||
#[pb(index = 3)]
|
||||
pub desc: String,
|
||||
|
||||
#[pb(index = 4)]
|
||||
pub apps: RepeatedAppPB,
|
||||
|
||||
#[pb(index = 5)]
|
||||
pub modified_time: i64,
|
||||
|
||||
#[pb(index = 6)]
|
||||
pub create_time: i64,
|
||||
}
|
||||
|
||||
impl std::convert::From<WorkspaceRevision> for WorkspacePB {
|
||||
fn from(workspace_serde: WorkspaceRevision) -> Self {
|
||||
WorkspacePB {
|
||||
id: workspace_serde.id,
|
||||
name: workspace_serde.name,
|
||||
desc: workspace_serde.desc,
|
||||
apps: workspace_serde.apps.into(),
|
||||
modified_time: workspace_serde.modified_time,
|
||||
create_time: workspace_serde.create_time,
|
||||
}
|
||||
}
|
||||
}
|
||||
#[derive(PartialEq, Debug, Default, ProtoBuf)]
|
||||
pub struct RepeatedWorkspacePB {
|
||||
#[pb(index = 1)]
|
||||
pub items: Vec<WorkspacePB>,
|
||||
}
|
||||
|
||||
impl_def_and_def_mut!(RepeatedWorkspacePB, WorkspacePB);
|
||||
|
||||
#[derive(ProtoBuf, Default)]
|
||||
pub struct CreateWorkspacePayloadPB {
|
||||
#[pb(index = 1)]
|
||||
pub name: String,
|
||||
|
||||
#[pb(index = 2)]
|
||||
pub desc: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct CreateWorkspaceParams {
|
||||
pub name: String,
|
||||
pub desc: String,
|
||||
}
|
||||
|
||||
impl TryInto<CreateWorkspaceParams> for CreateWorkspacePayloadPB {
|
||||
type Error = ErrorCode;
|
||||
|
||||
fn try_into(self) -> Result<CreateWorkspaceParams, Self::Error> {
|
||||
let name = WorkspaceName::parse(self.name)?;
|
||||
let desc = WorkspaceDesc::parse(self.desc)?;
|
||||
|
||||
Ok(CreateWorkspaceParams {
|
||||
name: name.0,
|
||||
desc: desc.0,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Read all workspaces if the workspace_id is None
|
||||
#[derive(Clone, ProtoBuf, Default, Debug)]
|
||||
pub struct WorkspaceIdPB {
|
||||
#[pb(index = 1, one_of)]
|
||||
pub value: Option<String>,
|
||||
}
|
||||
|
||||
impl WorkspaceIdPB {
|
||||
pub fn new(workspace_id: Option<String>) -> Self {
|
||||
Self { value: workspace_id }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, ProtoBuf, Clone)]
|
||||
pub struct CurrentWorkspaceSettingPB {
|
||||
#[pb(index = 1)]
|
||||
pub workspace: WorkspacePB,
|
||||
|
||||
#[pb(index = 2, one_of)]
|
||||
pub latest_view: Option<ViewPB>,
|
||||
}
|
||||
|
||||
#[derive(ProtoBuf, Default)]
|
||||
pub struct UpdateWorkspacePayloadPB {
|
||||
#[pb(index = 1)]
|
||||
pub id: String,
|
||||
|
||||
#[pb(index = 2, one_of)]
|
||||
pub name: Option<String>,
|
||||
|
||||
#[pb(index = 3, one_of)]
|
||||
pub desc: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct UpdateWorkspaceParams {
|
||||
pub id: String,
|
||||
pub name: Option<String>,
|
||||
pub desc: Option<String>,
|
||||
}
|
||||
|
||||
impl TryInto<UpdateWorkspaceParams> for UpdateWorkspacePayloadPB {
|
||||
type Error = ErrorCode;
|
||||
|
||||
fn try_into(self) -> Result<UpdateWorkspaceParams, Self::Error> {
|
||||
let name = match self.name {
|
||||
None => None,
|
||||
Some(name) => Some(WorkspaceName::parse(name)?.0),
|
||||
};
|
||||
let id = WorkspaceIdentify::parse(self.id)?;
|
||||
|
||||
Ok(UpdateWorkspaceParams {
|
||||
id: id.0,
|
||||
name,
|
||||
desc: self.desc,
|
||||
})
|
||||
}
|
||||
}
|
@ -1,9 +1,9 @@
|
||||
use crate::{
|
||||
entities::{
|
||||
app::{App, AppId, CreateAppParams, UpdateAppParams},
|
||||
trash::{RepeatedTrash, RepeatedTrashId},
|
||||
view::{CreateViewParams, RepeatedViewId, UpdateViewParams, View, ViewId},
|
||||
workspace::{CreateWorkspaceParams, RepeatedWorkspace, UpdateWorkspaceParams, Workspace, WorkspaceId},
|
||||
app::{AppIdPB, CreateAppParams, UpdateAppParams},
|
||||
trash::RepeatedTrashIdPB,
|
||||
view::{CreateViewParams, RepeatedViewIdPB, UpdateViewParams, ViewIdPB},
|
||||
workspace::{CreateWorkspaceParams, UpdateWorkspaceParams, WorkspaceIdPB},
|
||||
},
|
||||
errors::FlowyError,
|
||||
manager::FolderManager,
|
||||
@ -11,6 +11,7 @@ use crate::{
|
||||
};
|
||||
use flowy_database::{ConnectionPool, DBConnection};
|
||||
use flowy_derive::{Flowy_Event, ProtoBuf_Enum};
|
||||
use flowy_folder_data_model::revision::{AppRevision, TrashRevision, ViewRevision, WorkspaceRevision};
|
||||
use lib_dispatch::prelude::*;
|
||||
use lib_infra::future::FutureResult;
|
||||
use std::sync::Arc;
|
||||
@ -42,6 +43,7 @@ pub fn create(folder: Arc<FolderManager>) -> Module {
|
||||
.data(folder.trash_controller.clone())
|
||||
.data(folder.clone());
|
||||
|
||||
// Workspace
|
||||
module = module
|
||||
.event(FolderEvent::CreateWorkspace, create_workspace_handler)
|
||||
.event(FolderEvent::ReadCurWorkspace, read_cur_workspace_handler)
|
||||
@ -49,22 +51,26 @@ pub fn create(folder: Arc<FolderManager>) -> Module {
|
||||
.event(FolderEvent::OpenWorkspace, open_workspace_handler)
|
||||
.event(FolderEvent::ReadWorkspaceApps, read_workspace_apps_handler);
|
||||
|
||||
// App
|
||||
module = module
|
||||
.event(FolderEvent::CreateApp, create_app_handler)
|
||||
.event(FolderEvent::ReadApp, read_app_handler)
|
||||
.event(FolderEvent::UpdateApp, update_app_handler)
|
||||
.event(FolderEvent::DeleteApp, delete_app_handler);
|
||||
|
||||
// View
|
||||
module = module
|
||||
.event(FolderEvent::CreateView, create_view_handler)
|
||||
.event(FolderEvent::ReadView, read_view_handler)
|
||||
.event(FolderEvent::UpdateView, update_view_handler)
|
||||
.event(FolderEvent::ReadViewInfo, read_view_info_handler)
|
||||
.event(FolderEvent::DeleteView, delete_view_handler)
|
||||
.event(FolderEvent::DuplicateView, duplicate_view_handler)
|
||||
.event(FolderEvent::SetLatestView, set_latest_view_handler)
|
||||
.event(FolderEvent::CloseView, close_view_handler)
|
||||
.event(FolderEvent::MoveFolderItem, move_item_handler);
|
||||
|
||||
// Trash
|
||||
module = module
|
||||
.event(FolderEvent::ReadTrash, read_trash_handler)
|
||||
.event(FolderEvent::PutbackTrash, putback_trash_handler)
|
||||
@ -78,70 +84,73 @@ pub fn create(folder: Arc<FolderManager>) -> Module {
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, Display, Hash, ProtoBuf_Enum, Flowy_Event)]
|
||||
#[event_err = "FlowyError"]
|
||||
pub enum FolderEvent {
|
||||
#[event(input = "CreateWorkspacePayload", output = "Workspace")]
|
||||
#[event(input = "CreateWorkspacePayloadPB", output = "WorkspacePB")]
|
||||
CreateWorkspace = 0,
|
||||
|
||||
#[event(output = "CurrentWorkspaceSetting")]
|
||||
#[event(output = "CurrentWorkspaceSettingPB")]
|
||||
ReadCurWorkspace = 1,
|
||||
|
||||
#[event(input = "WorkspaceId", output = "RepeatedWorkspace")]
|
||||
#[event(input = "WorkspaceIdPB", output = "RepeatedWorkspacePB")]
|
||||
ReadWorkspaces = 2,
|
||||
|
||||
#[event(input = "WorkspaceId")]
|
||||
#[event(input = "WorkspaceIdPB")]
|
||||
DeleteWorkspace = 3,
|
||||
|
||||
#[event(input = "WorkspaceId", output = "Workspace")]
|
||||
#[event(input = "WorkspaceIdPB", output = "WorkspacePB")]
|
||||
OpenWorkspace = 4,
|
||||
|
||||
#[event(input = "WorkspaceId", output = "RepeatedApp")]
|
||||
#[event(input = "WorkspaceIdPB", output = "RepeatedAppPB")]
|
||||
ReadWorkspaceApps = 5,
|
||||
|
||||
#[event(input = "CreateAppPayload", output = "App")]
|
||||
#[event(input = "CreateAppPayloadPB", output = "AppPB")]
|
||||
CreateApp = 101,
|
||||
|
||||
#[event(input = "AppId")]
|
||||
#[event(input = "AppIdPB")]
|
||||
DeleteApp = 102,
|
||||
|
||||
#[event(input = "AppId", output = "App")]
|
||||
#[event(input = "AppIdPB", output = "AppPB")]
|
||||
ReadApp = 103,
|
||||
|
||||
#[event(input = "UpdateAppPayload")]
|
||||
#[event(input = "UpdateAppPayloadPB")]
|
||||
UpdateApp = 104,
|
||||
|
||||
#[event(input = "CreateViewPayload", output = "View")]
|
||||
#[event(input = "CreateViewPayloadPB", output = "ViewPB")]
|
||||
CreateView = 201,
|
||||
|
||||
#[event(input = "ViewId", output = "View")]
|
||||
#[event(input = "ViewIdPB", output = "ViewPB")]
|
||||
ReadView = 202,
|
||||
|
||||
#[event(input = "UpdateViewPayload", output = "View")]
|
||||
#[event(input = "UpdateViewPayloadPB", output = "ViewPB")]
|
||||
UpdateView = 203,
|
||||
|
||||
#[event(input = "RepeatedViewId")]
|
||||
#[event(input = "RepeatedViewIdPB")]
|
||||
DeleteView = 204,
|
||||
|
||||
#[event(input = "ViewId")]
|
||||
#[event(input = "ViewIdPB")]
|
||||
DuplicateView = 205,
|
||||
|
||||
#[event(input = "ViewIdPB")]
|
||||
CloseView = 206,
|
||||
|
||||
#[event(input = "ViewIdPB", output = "ViewInfoPB")]
|
||||
ReadViewInfo = 207,
|
||||
|
||||
#[event()]
|
||||
CopyLink = 206,
|
||||
CopyLink = 220,
|
||||
|
||||
#[event(input = "ViewId")]
|
||||
SetLatestView = 207,
|
||||
#[event(input = "ViewIdPB")]
|
||||
SetLatestView = 221,
|
||||
|
||||
#[event(input = "ViewId")]
|
||||
CloseView = 208,
|
||||
#[event(input = "MoveFolderItemPayloadPB")]
|
||||
MoveFolderItem = 230,
|
||||
|
||||
#[event(input = "MoveFolderItemPayload")]
|
||||
MoveFolderItem = 209,
|
||||
|
||||
#[event(output = "RepeatedTrash")]
|
||||
#[event(output = "RepeatedTrashPB")]
|
||||
ReadTrash = 300,
|
||||
|
||||
#[event(input = "TrashId")]
|
||||
#[event(input = "TrashIdPB")]
|
||||
PutbackTrash = 301,
|
||||
|
||||
#[event(input = "RepeatedTrashId")]
|
||||
#[event(input = "RepeatedTrashIdPB")]
|
||||
DeleteTrash = 302,
|
||||
|
||||
#[event()]
|
||||
@ -155,36 +164,40 @@ pub trait FolderCouldServiceV1: Send + Sync {
|
||||
fn init(&self);
|
||||
|
||||
// Workspace
|
||||
fn create_workspace(&self, token: &str, params: CreateWorkspaceParams) -> FutureResult<Workspace, FlowyError>;
|
||||
fn create_workspace(
|
||||
&self,
|
||||
token: &str,
|
||||
params: CreateWorkspaceParams,
|
||||
) -> FutureResult<WorkspaceRevision, FlowyError>;
|
||||
|
||||
fn read_workspace(&self, token: &str, params: WorkspaceId) -> FutureResult<RepeatedWorkspace, FlowyError>;
|
||||
fn read_workspace(&self, token: &str, params: WorkspaceIdPB) -> FutureResult<Vec<WorkspaceRevision>, FlowyError>;
|
||||
|
||||
fn update_workspace(&self, token: &str, params: UpdateWorkspaceParams) -> FutureResult<(), FlowyError>;
|
||||
|
||||
fn delete_workspace(&self, token: &str, params: WorkspaceId) -> FutureResult<(), FlowyError>;
|
||||
fn delete_workspace(&self, token: &str, params: WorkspaceIdPB) -> FutureResult<(), FlowyError>;
|
||||
|
||||
// View
|
||||
fn create_view(&self, token: &str, params: CreateViewParams) -> FutureResult<View, FlowyError>;
|
||||
fn create_view(&self, token: &str, params: CreateViewParams) -> FutureResult<ViewRevision, FlowyError>;
|
||||
|
||||
fn read_view(&self, token: &str, params: ViewId) -> FutureResult<Option<View>, FlowyError>;
|
||||
fn read_view(&self, token: &str, params: ViewIdPB) -> FutureResult<Option<ViewRevision>, FlowyError>;
|
||||
|
||||
fn delete_view(&self, token: &str, params: RepeatedViewId) -> FutureResult<(), FlowyError>;
|
||||
fn delete_view(&self, token: &str, params: RepeatedViewIdPB) -> FutureResult<(), FlowyError>;
|
||||
|
||||
fn update_view(&self, token: &str, params: UpdateViewParams) -> FutureResult<(), FlowyError>;
|
||||
|
||||
// App
|
||||
fn create_app(&self, token: &str, params: CreateAppParams) -> FutureResult<App, FlowyError>;
|
||||
fn create_app(&self, token: &str, params: CreateAppParams) -> FutureResult<AppRevision, FlowyError>;
|
||||
|
||||
fn read_app(&self, token: &str, params: AppId) -> FutureResult<Option<App>, FlowyError>;
|
||||
fn read_app(&self, token: &str, params: AppIdPB) -> FutureResult<Option<AppRevision>, FlowyError>;
|
||||
|
||||
fn update_app(&self, token: &str, params: UpdateAppParams) -> FutureResult<(), FlowyError>;
|
||||
|
||||
fn delete_app(&self, token: &str, params: AppId) -> FutureResult<(), FlowyError>;
|
||||
fn delete_app(&self, token: &str, params: AppIdPB) -> FutureResult<(), FlowyError>;
|
||||
|
||||
// Trash
|
||||
fn create_trash(&self, token: &str, params: RepeatedTrashId) -> FutureResult<(), FlowyError>;
|
||||
fn create_trash(&self, token: &str, params: RepeatedTrashIdPB) -> FutureResult<(), FlowyError>;
|
||||
|
||||
fn delete_trash(&self, token: &str, params: RepeatedTrashId) -> FutureResult<(), FlowyError>;
|
||||
fn delete_trash(&self, token: &str, params: RepeatedTrashIdPB) -> FutureResult<(), FlowyError>;
|
||||
|
||||
fn read_trash(&self, token: &str) -> FutureResult<RepeatedTrash, FlowyError>;
|
||||
fn read_trash(&self, token: &str) -> FutureResult<Vec<TrashRevision>, FlowyError>;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
pub use flowy_folder_data_model::entities;
|
||||
pub mod entities;
|
||||
pub mod event_map;
|
||||
pub mod services;
|
||||
|
||||
@ -14,8 +14,6 @@ pub mod protobuf;
|
||||
mod util;
|
||||
|
||||
pub mod prelude {
|
||||
pub use flowy_folder_data_model::entities::{app::*, trash::*, view::*, workspace::*};
|
||||
|
||||
pub use crate::{errors::*, event_map::*};
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,7 @@ macro_rules! impl_def_and_def_mut {
|
||||
impl $target {
|
||||
#[allow(dead_code)]
|
||||
pub fn into_inner(&mut self) -> Vec<$item> {
|
||||
::std::mem::replace(&mut self.items, vec![])
|
||||
::std::mem::take(&mut self.items)
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
|
@ -1,6 +1,8 @@
|
||||
use crate::entities::view::ViewDataType;
|
||||
use crate::services::folder_editor::FolderRevisionCompactor;
|
||||
use crate::{
|
||||
dart_notification::{send_dart_notification, FolderNotification},
|
||||
entities::workspace::RepeatedWorkspace,
|
||||
entities::workspace::RepeatedWorkspacePB,
|
||||
errors::FlowyResult,
|
||||
event_map::{FolderCouldServiceV1, WorkspaceDatabase, WorkspaceUser},
|
||||
services::{
|
||||
@ -9,17 +11,11 @@ use crate::{
|
||||
},
|
||||
};
|
||||
use bytes::Bytes;
|
||||
use flowy_sync::client_document::default::{initial_quill_delta_string, initial_read_me};
|
||||
|
||||
use crate::services::folder_editor::FolderRevisionCompactor;
|
||||
use flowy_error::FlowyError;
|
||||
use flowy_folder_data_model::entities::view::ViewDataType;
|
||||
use flowy_folder_data_model::user_default;
|
||||
use flowy_revision::disk::SQLiteTextBlockRevisionPersistence;
|
||||
use flowy_revision::{
|
||||
RevisionManager, RevisionPersistence, RevisionWebSocket, SQLiteRevisionHistoryPersistence,
|
||||
SQLiteRevisionSnapshotPersistence,
|
||||
};
|
||||
use flowy_revision::{RevisionManager, RevisionPersistence, RevisionWebSocket, SQLiteRevisionSnapshotPersistence};
|
||||
use flowy_sync::client_document::default::{initial_quill_delta_string, initial_read_me};
|
||||
use flowy_sync::{client_folder::FolderPad, entities::ws_data::ServerRevisionWSData};
|
||||
use lazy_static::lazy_static;
|
||||
use lib_infra::future::FutureResult;
|
||||
@ -170,14 +166,14 @@ impl FolderManager {
|
||||
let disk_cache = SQLiteTextBlockRevisionPersistence::new(user_id, pool.clone());
|
||||
let rev_persistence = RevisionPersistence::new(user_id, object_id, disk_cache);
|
||||
let rev_compactor = FolderRevisionCompactor();
|
||||
let history_persistence = SQLiteRevisionHistoryPersistence::new(object_id, pool.clone());
|
||||
// let history_persistence = SQLiteRevisionHistoryPersistence::new(object_id, pool.clone());
|
||||
let snapshot_persistence = SQLiteRevisionSnapshotPersistence::new(object_id, pool);
|
||||
let rev_manager = RevisionManager::new(
|
||||
user_id,
|
||||
folder_id.as_ref(),
|
||||
rev_persistence,
|
||||
rev_compactor,
|
||||
history_persistence,
|
||||
// history_persistence,
|
||||
snapshot_persistence,
|
||||
);
|
||||
|
||||
@ -214,9 +210,9 @@ impl DefaultFolderBuilder {
|
||||
view_controller: Arc<ViewController>,
|
||||
) -> FlowyResult<()> {
|
||||
log::debug!("Create user default workspace");
|
||||
let workspace = user_default::create_default_workspace();
|
||||
set_current_workspace(&workspace.id);
|
||||
for app in workspace.apps.iter() {
|
||||
let workspace_rev = user_default::create_default_workspace();
|
||||
set_current_workspace(&workspace_rev.id);
|
||||
for app in workspace_rev.apps.iter() {
|
||||
for (index, view) in app.belongings.iter().enumerate() {
|
||||
let view_data = if index == 0 {
|
||||
initial_read_me().to_delta_str()
|
||||
@ -229,10 +225,12 @@ impl DefaultFolderBuilder {
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
let folder = FolderPad::new(vec![workspace.clone()], vec![])?;
|
||||
let folder = FolderPad::new(vec![workspace_rev.clone()], vec![])?;
|
||||
let folder_id = FolderId::new(user_id);
|
||||
let _ = persistence.save_folder(user_id, &folder_id, folder).await?;
|
||||
let repeated_workspace = RepeatedWorkspace { items: vec![workspace] };
|
||||
let repeated_workspace = RepeatedWorkspacePB {
|
||||
items: vec![workspace_rev.into()],
|
||||
};
|
||||
send_dart_notification(token, FolderNotification::UserCreateWorkspace)
|
||||
.payload(repeated_workspace)
|
||||
.send();
|
||||
@ -256,11 +254,16 @@ pub trait ViewDataProcessor {
|
||||
|
||||
fn close_container(&self, view_id: &str) -> FutureResult<(), FlowyError>;
|
||||
|
||||
fn view_delta_data(&self, view_id: &str) -> FutureResult<Bytes, FlowyError>;
|
||||
fn get_delta_data(&self, view_id: &str) -> FutureResult<Bytes, FlowyError>;
|
||||
|
||||
fn create_default_view(&self, user_id: &str, view_id: &str) -> FutureResult<Bytes, FlowyError>;
|
||||
|
||||
fn process_view_delta_data(&self, user_id: &str, view_id: &str, data: Vec<u8>) -> FutureResult<Bytes, FlowyError>;
|
||||
fn create_view_from_delta_data(
|
||||
&self,
|
||||
user_id: &str,
|
||||
view_id: &str,
|
||||
data: Vec<u8>,
|
||||
) -> FutureResult<Bytes, FlowyError>;
|
||||
|
||||
fn data_type(&self) -> ViewDataType;
|
||||
}
|
||||
|
@ -1,4 +0,0 @@
|
||||
#![cfg_attr(rustfmt, rustfmt::skip)]
|
||||
// Auto-generated, do not edit
|
||||
mod model;
|
||||
pub use model::*;
|
@ -1,134 +0,0 @@
|
||||
// This file is generated by rust-protobuf 2.25.2. Do not edit
|
||||
// @generated
|
||||
|
||||
// https://github.com/rust-lang/rust-clippy/issues/702
|
||||
#![allow(unknown_lints)]
|
||||
#![allow(clippy::all)]
|
||||
|
||||
#![allow(unused_attributes)]
|
||||
#![cfg_attr(rustfmt, rustfmt::skip)]
|
||||
|
||||
#![allow(box_pointers)]
|
||||
#![allow(dead_code)]
|
||||
#![allow(missing_docs)]
|
||||
#![allow(non_camel_case_types)]
|
||||
#![allow(non_snake_case)]
|
||||
#![allow(non_upper_case_globals)]
|
||||
#![allow(trivial_casts)]
|
||||
#![allow(unused_imports)]
|
||||
#![allow(unused_results)]
|
||||
//! Generated file from `dart_notification.proto`
|
||||
|
||||
/// Generated files are compatible only with the same version
|
||||
/// of protobuf runtime.
|
||||
// const _PROTOBUF_VERSION_CHECK: () = ::protobuf::VERSION_2_25_2;
|
||||
|
||||
#[derive(Clone,PartialEq,Eq,Debug,Hash)]
|
||||
pub enum FolderNotification {
|
||||
Unknown = 0,
|
||||
UserCreateWorkspace = 10,
|
||||
UserDeleteWorkspace = 11,
|
||||
WorkspaceUpdated = 12,
|
||||
WorkspaceListUpdated = 13,
|
||||
WorkspaceAppsChanged = 14,
|
||||
WorkspaceSetting = 15,
|
||||
AppUpdated = 21,
|
||||
AppViewsChanged = 24,
|
||||
ViewUpdated = 31,
|
||||
ViewDeleted = 32,
|
||||
ViewRestored = 33,
|
||||
UserUnauthorized = 100,
|
||||
TrashUpdated = 1000,
|
||||
}
|
||||
|
||||
impl ::protobuf::ProtobufEnum for FolderNotification {
|
||||
fn value(&self) -> i32 {
|
||||
*self as i32
|
||||
}
|
||||
|
||||
fn from_i32(value: i32) -> ::std::option::Option<FolderNotification> {
|
||||
match value {
|
||||
0 => ::std::option::Option::Some(FolderNotification::Unknown),
|
||||
10 => ::std::option::Option::Some(FolderNotification::UserCreateWorkspace),
|
||||
11 => ::std::option::Option::Some(FolderNotification::UserDeleteWorkspace),
|
||||
12 => ::std::option::Option::Some(FolderNotification::WorkspaceUpdated),
|
||||
13 => ::std::option::Option::Some(FolderNotification::WorkspaceListUpdated),
|
||||
14 => ::std::option::Option::Some(FolderNotification::WorkspaceAppsChanged),
|
||||
15 => ::std::option::Option::Some(FolderNotification::WorkspaceSetting),
|
||||
21 => ::std::option::Option::Some(FolderNotification::AppUpdated),
|
||||
24 => ::std::option::Option::Some(FolderNotification::AppViewsChanged),
|
||||
31 => ::std::option::Option::Some(FolderNotification::ViewUpdated),
|
||||
32 => ::std::option::Option::Some(FolderNotification::ViewDeleted),
|
||||
33 => ::std::option::Option::Some(FolderNotification::ViewRestored),
|
||||
100 => ::std::option::Option::Some(FolderNotification::UserUnauthorized),
|
||||
1000 => ::std::option::Option::Some(FolderNotification::TrashUpdated),
|
||||
_ => ::std::option::Option::None
|
||||
}
|
||||
}
|
||||
|
||||
fn values() -> &'static [Self] {
|
||||
static values: &'static [FolderNotification] = &[
|
||||
FolderNotification::Unknown,
|
||||
FolderNotification::UserCreateWorkspace,
|
||||
FolderNotification::UserDeleteWorkspace,
|
||||
FolderNotification::WorkspaceUpdated,
|
||||
FolderNotification::WorkspaceListUpdated,
|
||||
FolderNotification::WorkspaceAppsChanged,
|
||||
FolderNotification::WorkspaceSetting,
|
||||
FolderNotification::AppUpdated,
|
||||
FolderNotification::AppViewsChanged,
|
||||
FolderNotification::ViewUpdated,
|
||||
FolderNotification::ViewDeleted,
|
||||
FolderNotification::ViewRestored,
|
||||
FolderNotification::UserUnauthorized,
|
||||
FolderNotification::TrashUpdated,
|
||||
];
|
||||
values
|
||||
}
|
||||
|
||||
fn enum_descriptor_static() -> &'static ::protobuf::reflect::EnumDescriptor {
|
||||
static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::EnumDescriptor> = ::protobuf::rt::LazyV2::INIT;
|
||||
descriptor.get(|| {
|
||||
::protobuf::reflect::EnumDescriptor::new_pb_name::<FolderNotification>("FolderNotification", file_descriptor_proto())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl ::std::marker::Copy for FolderNotification {
|
||||
}
|
||||
|
||||
impl ::std::default::Default for FolderNotification {
|
||||
fn default() -> Self {
|
||||
FolderNotification::Unknown
|
||||
}
|
||||
}
|
||||
|
||||
impl ::protobuf::reflect::ProtobufValue for FolderNotification {
|
||||
fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
|
||||
::protobuf::reflect::ReflectValueRef::Enum(::protobuf::ProtobufEnum::descriptor(self))
|
||||
}
|
||||
}
|
||||
|
||||
static file_descriptor_proto_data: &'static [u8] = b"\
|
||||
\n\x17dart_notification.proto*\xb5\x02\n\x12FolderNotification\x12\x0b\n\
|
||||
\x07Unknown\x10\0\x12\x17\n\x13UserCreateWorkspace\x10\n\x12\x17\n\x13Us\
|
||||
erDeleteWorkspace\x10\x0b\x12\x14\n\x10WorkspaceUpdated\x10\x0c\x12\x18\
|
||||
\n\x14WorkspaceListUpdated\x10\r\x12\x18\n\x14WorkspaceAppsChanged\x10\
|
||||
\x0e\x12\x14\n\x10WorkspaceSetting\x10\x0f\x12\x0e\n\nAppUpdated\x10\x15\
|
||||
\x12\x13\n\x0fAppViewsChanged\x10\x18\x12\x0f\n\x0bViewUpdated\x10\x1f\
|
||||
\x12\x0f\n\x0bViewDeleted\x10\x20\x12\x10\n\x0cViewRestored\x10!\x12\x14\
|
||||
\n\x10UserUnauthorized\x10d\x12\x11\n\x0cTrashUpdated\x10\xe8\x07b\x06pr\
|
||||
oto3\
|
||||
";
|
||||
|
||||
static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;
|
||||
|
||||
fn parse_descriptor_proto() -> ::protobuf::descriptor::FileDescriptorProto {
|
||||
::protobuf::Message::parse_from_bytes(file_descriptor_proto_data).unwrap()
|
||||
}
|
||||
|
||||
pub fn file_descriptor_proto() -> &'static ::protobuf::descriptor::FileDescriptorProto {
|
||||
file_descriptor_proto_lazy.get(|| {
|
||||
parse_descriptor_proto()
|
||||
})
|
||||
}
|
@ -1,168 +0,0 @@
|
||||
// This file is generated by rust-protobuf 2.25.2. Do not edit
|
||||
// @generated
|
||||
|
||||
// https://github.com/rust-lang/rust-clippy/issues/702
|
||||
#![allow(unknown_lints)]
|
||||
#![allow(clippy::all)]
|
||||
|
||||
#![allow(unused_attributes)]
|
||||
#![cfg_attr(rustfmt, rustfmt::skip)]
|
||||
|
||||
#![allow(box_pointers)]
|
||||
#![allow(dead_code)]
|
||||
#![allow(missing_docs)]
|
||||
#![allow(non_camel_case_types)]
|
||||
#![allow(non_snake_case)]
|
||||
#![allow(non_upper_case_globals)]
|
||||
#![allow(trivial_casts)]
|
||||
#![allow(unused_imports)]
|
||||
#![allow(unused_results)]
|
||||
//! Generated file from `event_map.proto`
|
||||
|
||||
/// Generated files are compatible only with the same version
|
||||
/// of protobuf runtime.
|
||||
// const _PROTOBUF_VERSION_CHECK: () = ::protobuf::VERSION_2_25_2;
|
||||
|
||||
#[derive(Clone,PartialEq,Eq,Debug,Hash)]
|
||||
pub enum FolderEvent {
|
||||
CreateWorkspace = 0,
|
||||
ReadCurWorkspace = 1,
|
||||
ReadWorkspaces = 2,
|
||||
DeleteWorkspace = 3,
|
||||
OpenWorkspace = 4,
|
||||
ReadWorkspaceApps = 5,
|
||||
CreateApp = 101,
|
||||
DeleteApp = 102,
|
||||
ReadApp = 103,
|
||||
UpdateApp = 104,
|
||||
CreateView = 201,
|
||||
ReadView = 202,
|
||||
UpdateView = 203,
|
||||
DeleteView = 204,
|
||||
DuplicateView = 205,
|
||||
CopyLink = 206,
|
||||
SetLatestView = 207,
|
||||
CloseView = 208,
|
||||
MoveFolderItem = 209,
|
||||
ReadTrash = 300,
|
||||
PutbackTrash = 301,
|
||||
DeleteTrash = 302,
|
||||
RestoreAllTrash = 303,
|
||||
DeleteAllTrash = 304,
|
||||
}
|
||||
|
||||
impl ::protobuf::ProtobufEnum for FolderEvent {
|
||||
fn value(&self) -> i32 {
|
||||
*self as i32
|
||||
}
|
||||
|
||||
fn from_i32(value: i32) -> ::std::option::Option<FolderEvent> {
|
||||
match value {
|
||||
0 => ::std::option::Option::Some(FolderEvent::CreateWorkspace),
|
||||
1 => ::std::option::Option::Some(FolderEvent::ReadCurWorkspace),
|
||||
2 => ::std::option::Option::Some(FolderEvent::ReadWorkspaces),
|
||||
3 => ::std::option::Option::Some(FolderEvent::DeleteWorkspace),
|
||||
4 => ::std::option::Option::Some(FolderEvent::OpenWorkspace),
|
||||
5 => ::std::option::Option::Some(FolderEvent::ReadWorkspaceApps),
|
||||
101 => ::std::option::Option::Some(FolderEvent::CreateApp),
|
||||
102 => ::std::option::Option::Some(FolderEvent::DeleteApp),
|
||||
103 => ::std::option::Option::Some(FolderEvent::ReadApp),
|
||||
104 => ::std::option::Option::Some(FolderEvent::UpdateApp),
|
||||
201 => ::std::option::Option::Some(FolderEvent::CreateView),
|
||||
202 => ::std::option::Option::Some(FolderEvent::ReadView),
|
||||
203 => ::std::option::Option::Some(FolderEvent::UpdateView),
|
||||
204 => ::std::option::Option::Some(FolderEvent::DeleteView),
|
||||
205 => ::std::option::Option::Some(FolderEvent::DuplicateView),
|
||||
206 => ::std::option::Option::Some(FolderEvent::CopyLink),
|
||||
207 => ::std::option::Option::Some(FolderEvent::SetLatestView),
|
||||
208 => ::std::option::Option::Some(FolderEvent::CloseView),
|
||||
209 => ::std::option::Option::Some(FolderEvent::MoveFolderItem),
|
||||
300 => ::std::option::Option::Some(FolderEvent::ReadTrash),
|
||||
301 => ::std::option::Option::Some(FolderEvent::PutbackTrash),
|
||||
302 => ::std::option::Option::Some(FolderEvent::DeleteTrash),
|
||||
303 => ::std::option::Option::Some(FolderEvent::RestoreAllTrash),
|
||||
304 => ::std::option::Option::Some(FolderEvent::DeleteAllTrash),
|
||||
_ => ::std::option::Option::None
|
||||
}
|
||||
}
|
||||
|
||||
fn values() -> &'static [Self] {
|
||||
static values: &'static [FolderEvent] = &[
|
||||
FolderEvent::CreateWorkspace,
|
||||
FolderEvent::ReadCurWorkspace,
|
||||
FolderEvent::ReadWorkspaces,
|
||||
FolderEvent::DeleteWorkspace,
|
||||
FolderEvent::OpenWorkspace,
|
||||
FolderEvent::ReadWorkspaceApps,
|
||||
FolderEvent::CreateApp,
|
||||
FolderEvent::DeleteApp,
|
||||
FolderEvent::ReadApp,
|
||||
FolderEvent::UpdateApp,
|
||||
FolderEvent::CreateView,
|
||||
FolderEvent::ReadView,
|
||||
FolderEvent::UpdateView,
|
||||
FolderEvent::DeleteView,
|
||||
FolderEvent::DuplicateView,
|
||||
FolderEvent::CopyLink,
|
||||
FolderEvent::SetLatestView,
|
||||
FolderEvent::CloseView,
|
||||
FolderEvent::MoveFolderItem,
|
||||
FolderEvent::ReadTrash,
|
||||
FolderEvent::PutbackTrash,
|
||||
FolderEvent::DeleteTrash,
|
||||
FolderEvent::RestoreAllTrash,
|
||||
FolderEvent::DeleteAllTrash,
|
||||
];
|
||||
values
|
||||
}
|
||||
|
||||
fn enum_descriptor_static() -> &'static ::protobuf::reflect::EnumDescriptor {
|
||||
static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::EnumDescriptor> = ::protobuf::rt::LazyV2::INIT;
|
||||
descriptor.get(|| {
|
||||
::protobuf::reflect::EnumDescriptor::new_pb_name::<FolderEvent>("FolderEvent", file_descriptor_proto())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl ::std::marker::Copy for FolderEvent {
|
||||
}
|
||||
|
||||
impl ::std::default::Default for FolderEvent {
|
||||
fn default() -> Self {
|
||||
FolderEvent::CreateWorkspace
|
||||
}
|
||||
}
|
||||
|
||||
impl ::protobuf::reflect::ProtobufValue for FolderEvent {
|
||||
fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
|
||||
::protobuf::reflect::ReflectValueRef::Enum(::protobuf::ProtobufEnum::descriptor(self))
|
||||
}
|
||||
}
|
||||
|
||||
static file_descriptor_proto_data: &'static [u8] = b"\
|
||||
\n\x0fevent_map.proto*\xc3\x03\n\x0bFolderEvent\x12\x13\n\x0fCreateWorks\
|
||||
pace\x10\0\x12\x14\n\x10ReadCurWorkspace\x10\x01\x12\x12\n\x0eReadWorksp\
|
||||
aces\x10\x02\x12\x13\n\x0fDeleteWorkspace\x10\x03\x12\x11\n\rOpenWorkspa\
|
||||
ce\x10\x04\x12\x15\n\x11ReadWorkspaceApps\x10\x05\x12\r\n\tCreateApp\x10\
|
||||
e\x12\r\n\tDeleteApp\x10f\x12\x0b\n\x07ReadApp\x10g\x12\r\n\tUpdateApp\
|
||||
\x10h\x12\x0f\n\nCreateView\x10\xc9\x01\x12\r\n\x08ReadView\x10\xca\x01\
|
||||
\x12\x0f\n\nUpdateView\x10\xcb\x01\x12\x0f\n\nDeleteView\x10\xcc\x01\x12\
|
||||
\x12\n\rDuplicateView\x10\xcd\x01\x12\r\n\x08CopyLink\x10\xce\x01\x12\
|
||||
\x12\n\rSetLatestView\x10\xcf\x01\x12\x0e\n\tCloseView\x10\xd0\x01\x12\
|
||||
\x13\n\x0eMoveFolderItem\x10\xd1\x01\x12\x0e\n\tReadTrash\x10\xac\x02\
|
||||
\x12\x11\n\x0cPutbackTrash\x10\xad\x02\x12\x10\n\x0bDeleteTrash\x10\xae\
|
||||
\x02\x12\x14\n\x0fRestoreAllTrash\x10\xaf\x02\x12\x13\n\x0eDeleteAllTras\
|
||||
h\x10\xb0\x02b\x06proto3\
|
||||
";
|
||||
|
||||
static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;
|
||||
|
||||
fn parse_descriptor_proto() -> ::protobuf::descriptor::FileDescriptorProto {
|
||||
::protobuf::Message::parse_from_bytes(file_descriptor_proto_data).unwrap()
|
||||
}
|
||||
|
||||
pub fn file_descriptor_proto() -> &'static ::protobuf::descriptor::FileDescriptorProto {
|
||||
file_descriptor_proto_lazy.get(|| {
|
||||
parse_descriptor_proto()
|
||||
})
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
#![cfg_attr(rustfmt, rustfmt::skip)]
|
||||
// Auto-generated, do not edit
|
||||
|
||||
mod dart_notification;
|
||||
pub use dart_notification::*;
|
||||
|
||||
mod event_map;
|
||||
pub use event_map::*;
|
@ -1,18 +0,0 @@
|
||||
syntax = "proto3";
|
||||
|
||||
enum FolderNotification {
|
||||
Unknown = 0;
|
||||
UserCreateWorkspace = 10;
|
||||
UserDeleteWorkspace = 11;
|
||||
WorkspaceUpdated = 12;
|
||||
WorkspaceListUpdated = 13;
|
||||
WorkspaceAppsChanged = 14;
|
||||
WorkspaceSetting = 15;
|
||||
AppUpdated = 21;
|
||||
AppViewsChanged = 24;
|
||||
ViewUpdated = 31;
|
||||
ViewDeleted = 32;
|
||||
ViewRestored = 33;
|
||||
UserUnauthorized = 100;
|
||||
TrashUpdated = 1000;
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
syntax = "proto3";
|
||||
|
||||
enum FolderEvent {
|
||||
CreateWorkspace = 0;
|
||||
ReadCurWorkspace = 1;
|
||||
ReadWorkspaces = 2;
|
||||
DeleteWorkspace = 3;
|
||||
OpenWorkspace = 4;
|
||||
ReadWorkspaceApps = 5;
|
||||
CreateApp = 101;
|
||||
DeleteApp = 102;
|
||||
ReadApp = 103;
|
||||
UpdateApp = 104;
|
||||
CreateView = 201;
|
||||
ReadView = 202;
|
||||
UpdateView = 203;
|
||||
DeleteView = 204;
|
||||
DuplicateView = 205;
|
||||
CopyLink = 206;
|
||||
SetLatestView = 207;
|
||||
CloseView = 208;
|
||||
MoveFolderItem = 209;
|
||||
ReadTrash = 300;
|
||||
PutbackTrash = 301;
|
||||
DeleteTrash = 302;
|
||||
RestoreAllTrash = 303;
|
||||
DeleteAllTrash = 304;
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
use crate::{
|
||||
dart_notification::*,
|
||||
entities::{
|
||||
app::{App, CreateAppParams, *},
|
||||
app::{AppPB, CreateAppParams, *},
|
||||
trash::TrashType,
|
||||
},
|
||||
errors::*,
|
||||
@ -12,6 +12,7 @@ use crate::{
|
||||
},
|
||||
};
|
||||
|
||||
use flowy_folder_data_model::revision::AppRevision;
|
||||
use futures::{FutureExt, StreamExt};
|
||||
use std::{collections::HashSet, sync::Arc};
|
||||
|
||||
@ -43,12 +44,12 @@ impl AppController {
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip(self, params), fields(name = %params.name) err)]
|
||||
pub(crate) async fn create_app_from_params(&self, params: CreateAppParams) -> Result<App, FlowyError> {
|
||||
pub(crate) async fn create_app_from_params(&self, params: CreateAppParams) -> Result<AppPB, FlowyError> {
|
||||
let app = self.create_app_on_server(params).await?;
|
||||
self.create_app_on_local(app).await
|
||||
}
|
||||
|
||||
pub(crate) async fn create_app_on_local(&self, app: App) -> Result<App, FlowyError> {
|
||||
pub(crate) async fn create_app_on_local(&self, app: AppRevision) -> Result<AppPB, FlowyError> {
|
||||
let _ = self
|
||||
.persistence
|
||||
.begin_transaction(|transaction| {
|
||||
@ -57,10 +58,10 @@ impl AppController {
|
||||
Ok(())
|
||||
})
|
||||
.await?;
|
||||
Ok(app)
|
||||
Ok(app.into())
|
||||
}
|
||||
|
||||
pub(crate) async fn read_app(&self, params: AppId) -> Result<App, FlowyError> {
|
||||
pub(crate) async fn read_app(&self, params: AppIdPB) -> Result<AppRevision, FlowyError> {
|
||||
let app = self
|
||||
.persistence
|
||||
.begin_transaction(|transaction| {
|
||||
@ -80,14 +81,15 @@ impl AppController {
|
||||
let changeset = AppChangeset::new(params.clone());
|
||||
let app_id = changeset.id.clone();
|
||||
|
||||
let app = self
|
||||
let app: AppPB = self
|
||||
.persistence
|
||||
.begin_transaction(|transaction| {
|
||||
let _ = transaction.update_app(changeset)?;
|
||||
let app = transaction.read_app(&app_id)?;
|
||||
Ok(app)
|
||||
})
|
||||
.await?;
|
||||
.await?
|
||||
.into();
|
||||
send_dart_notification(&app_id, FolderNotification::AppUpdated)
|
||||
.payload(app)
|
||||
.send();
|
||||
@ -108,8 +110,8 @@ impl AppController {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) async fn read_local_apps(&self, ids: Vec<String>) -> Result<Vec<App>, FlowyError> {
|
||||
let apps = self
|
||||
pub(crate) async fn read_local_apps(&self, ids: Vec<String>) -> Result<Vec<AppRevision>, FlowyError> {
|
||||
let app_revs = self
|
||||
.persistence
|
||||
.begin_transaction(|transaction| {
|
||||
let mut apps = vec![];
|
||||
@ -119,13 +121,13 @@ impl AppController {
|
||||
Ok(apps)
|
||||
})
|
||||
.await?;
|
||||
Ok(apps)
|
||||
Ok(app_revs)
|
||||
}
|
||||
}
|
||||
|
||||
impl AppController {
|
||||
#[tracing::instrument(level = "trace", skip(self), err)]
|
||||
async fn create_app_on_server(&self, params: CreateAppParams) -> Result<App, FlowyError> {
|
||||
async fn create_app_on_server(&self, params: CreateAppParams) -> Result<AppRevision, FlowyError> {
|
||||
let token = self.user.token()?;
|
||||
let app = self.cloud_service.create_app(&token, params).await?;
|
||||
Ok(app)
|
||||
@ -148,18 +150,19 @@ impl AppController {
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "trace", skip(self), err)]
|
||||
fn read_app_on_server(&self, params: AppId) -> Result<(), FlowyError> {
|
||||
fn read_app_on_server(&self, params: AppIdPB) -> Result<(), FlowyError> {
|
||||
let token = self.user.token()?;
|
||||
let server = self.cloud_service.clone();
|
||||
let persistence = self.persistence.clone();
|
||||
tokio::spawn(async move {
|
||||
match server.read_app(&token, params).await {
|
||||
Ok(Some(app)) => {
|
||||
Ok(Some(app_rev)) => {
|
||||
match persistence
|
||||
.begin_transaction(|transaction| transaction.create_app(app.clone()))
|
||||
.begin_transaction(|transaction| transaction.create_app(app_rev.clone()))
|
||||
.await
|
||||
{
|
||||
Ok(_) => {
|
||||
let app: AppPB = app_rev.into();
|
||||
send_dart_notification(&app.id, FolderNotification::AppUpdated)
|
||||
.payload(app)
|
||||
.send();
|
||||
@ -240,7 +243,11 @@ fn notify_apps_changed<'a>(
|
||||
trash_controller: Arc<TrashController>,
|
||||
transaction: &'a (dyn FolderPersistenceTransaction + 'a),
|
||||
) -> FlowyResult<()> {
|
||||
let repeated_app = read_local_workspace_apps(workspace_id, trash_controller, transaction)?;
|
||||
let items = read_local_workspace_apps(workspace_id, trash_controller, transaction)?
|
||||
.into_iter()
|
||||
.map(|app_rev| app_rev.into())
|
||||
.collect();
|
||||
let repeated_app = RepeatedAppPB { items };
|
||||
send_dart_notification(workspace_id, FolderNotification::WorkspaceAppsChanged)
|
||||
.payload(repeated_app)
|
||||
.send();
|
||||
@ -251,9 +258,9 @@ pub fn read_local_workspace_apps<'a>(
|
||||
workspace_id: &str,
|
||||
trash_controller: Arc<TrashController>,
|
||||
transaction: &'a (dyn FolderPersistenceTransaction + 'a),
|
||||
) -> Result<RepeatedApp, FlowyError> {
|
||||
let mut apps = transaction.read_workspace_apps(workspace_id)?;
|
||||
) -> Result<Vec<AppRevision>, FlowyError> {
|
||||
let mut app_revs = transaction.read_workspace_apps(workspace_id)?;
|
||||
let trash_ids = trash_controller.read_trash_ids(transaction)?;
|
||||
apps.retain(|app| !trash_ids.contains(&app.id));
|
||||
Ok(RepeatedApp { items: apps })
|
||||
app_revs.retain(|app| !trash_ids.contains(&app.id));
|
||||
Ok(app_revs)
|
||||
}
|
||||
|
@ -1,18 +1,16 @@
|
||||
use crate::{
|
||||
entities::{
|
||||
app::{App, AppId, CreateAppParams, CreateAppPayload, UpdateAppParams, UpdateAppPayload},
|
||||
trash::Trash,
|
||||
},
|
||||
entities::app::{AppIdPB, AppPB, CreateAppParams, CreateAppPayloadPB, UpdateAppParams, UpdateAppPayloadPB},
|
||||
errors::FlowyError,
|
||||
services::{AppController, TrashController, ViewController},
|
||||
};
|
||||
use flowy_folder_data_model::revision::TrashRevision;
|
||||
use lib_dispatch::prelude::{data_result, AppData, Data, DataResult};
|
||||
use std::{convert::TryInto, sync::Arc};
|
||||
|
||||
pub(crate) async fn create_app_handler(
|
||||
data: Data<CreateAppPayload>,
|
||||
data: Data<CreateAppPayloadPB>,
|
||||
controller: AppData<Arc<AppController>>,
|
||||
) -> DataResult<App, FlowyError> {
|
||||
) -> DataResult<AppPB, FlowyError> {
|
||||
let params: CreateAppParams = data.into_inner().try_into()?;
|
||||
let detail = controller.create_app_from_params(params).await?;
|
||||
|
||||
@ -20,17 +18,17 @@ pub(crate) async fn create_app_handler(
|
||||
}
|
||||
|
||||
pub(crate) async fn delete_app_handler(
|
||||
data: Data<AppId>,
|
||||
data: Data<AppIdPB>,
|
||||
app_controller: AppData<Arc<AppController>>,
|
||||
trash_controller: AppData<Arc<TrashController>>,
|
||||
) -> Result<(), FlowyError> {
|
||||
let params: AppId = data.into_inner();
|
||||
let params: AppIdPB = data.into_inner();
|
||||
let trash = app_controller
|
||||
.read_local_apps(vec![params.value])
|
||||
.await?
|
||||
.into_iter()
|
||||
.map(|app| app.into())
|
||||
.collect::<Vec<Trash>>();
|
||||
.map(|app_rev| app_rev.into())
|
||||
.collect::<Vec<TrashRevision>>();
|
||||
|
||||
let _ = trash_controller.add(trash).await?;
|
||||
Ok(())
|
||||
@ -38,7 +36,7 @@ pub(crate) async fn delete_app_handler(
|
||||
|
||||
#[tracing::instrument(level = "debug", skip(data, controller))]
|
||||
pub(crate) async fn update_app_handler(
|
||||
data: Data<UpdateAppPayload>,
|
||||
data: Data<UpdateAppPayloadPB>,
|
||||
controller: AppData<Arc<AppController>>,
|
||||
) -> Result<(), FlowyError> {
|
||||
let params: UpdateAppParams = data.into_inner().try_into()?;
|
||||
@ -48,13 +46,13 @@ pub(crate) async fn update_app_handler(
|
||||
|
||||
#[tracing::instrument(level = "trace", skip(data, app_controller, view_controller))]
|
||||
pub(crate) async fn read_app_handler(
|
||||
data: Data<AppId>,
|
||||
data: Data<AppIdPB>,
|
||||
app_controller: AppData<Arc<AppController>>,
|
||||
view_controller: AppData<Arc<ViewController>>,
|
||||
) -> DataResult<App, FlowyError> {
|
||||
let params: AppId = data.into_inner();
|
||||
let mut app = app_controller.read_app(params.clone()).await?;
|
||||
app.belongings = view_controller.read_views_belong_to(¶ms.value).await?;
|
||||
) -> DataResult<AppPB, FlowyError> {
|
||||
let params: AppIdPB = data.into_inner();
|
||||
let mut app_rev = app_controller.read_app(params.clone()).await?;
|
||||
app_rev.belongings = view_controller.read_views_belong_to(¶ms.value).await?;
|
||||
|
||||
data_result(app)
|
||||
data_result(app_rev.into())
|
||||
}
|
||||
|
@ -1,16 +1,14 @@
|
||||
use flowy_sync::{
|
||||
client_folder::{FolderChange, FolderPad},
|
||||
entities::{revision::Revision, ws_data::ServerRevisionWSData},
|
||||
};
|
||||
|
||||
use crate::manager::FolderId;
|
||||
use bytes::Bytes;
|
||||
use flowy_error::{FlowyError, FlowyResult};
|
||||
use flowy_sync::util::make_delta_from_revisions;
|
||||
|
||||
use flowy_revision::{
|
||||
RevisionCloudService, RevisionCompactor, RevisionManager, RevisionObjectBuilder, RevisionWebSocket,
|
||||
};
|
||||
use flowy_sync::util::make_delta_from_revisions;
|
||||
use flowy_sync::{
|
||||
client_folder::{FolderChange, FolderPad},
|
||||
entities::{revision::Revision, ws_data::ServerRevisionWSData},
|
||||
};
|
||||
use lib_infra::future::FutureResult;
|
||||
use lib_ot::core::PlainTextAttributes;
|
||||
|
||||
|
@ -5,11 +5,8 @@ use crate::{
|
||||
};
|
||||
use flowy_database::kv::KV;
|
||||
use flowy_error::{FlowyError, FlowyResult};
|
||||
use flowy_folder_data_model::entities::{
|
||||
app::{App, RepeatedApp},
|
||||
view::{RepeatedView, View},
|
||||
workspace::Workspace,
|
||||
};
|
||||
|
||||
use flowy_folder_data_model::revision::{AppRevision, ViewRevision, WorkspaceRevision};
|
||||
use flowy_revision::disk::SQLiteTextBlockRevisionPersistence;
|
||||
use flowy_revision::{RevisionLoader, RevisionPersistence};
|
||||
use flowy_sync::{client_folder::FolderPad, entities::revision::md5};
|
||||
@ -42,25 +39,25 @@ impl FolderMigration {
|
||||
let workspaces = conn.immediate_transaction::<_, FlowyError, _>(|| {
|
||||
let mut workspaces = WorkspaceTableSql::read_workspaces(&self.user_id, None, conn)?
|
||||
.into_iter()
|
||||
.map(Workspace::from)
|
||||
.map(WorkspaceRevision::from)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
for workspace in workspaces.iter_mut() {
|
||||
let mut apps = AppTableSql::read_workspace_apps(&workspace.id, conn)?
|
||||
.into_iter()
|
||||
.map(App::from)
|
||||
.map(AppRevision::from)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
for app in apps.iter_mut() {
|
||||
let views = ViewTableSql::read_views(&app.id, conn)?
|
||||
.into_iter()
|
||||
.map(View::from)
|
||||
.map(ViewRevision::from)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
app.belongings = RepeatedView { items: views };
|
||||
app.belongings = views;
|
||||
}
|
||||
|
||||
workspace.apps = RepeatedApp { items: apps };
|
||||
workspace.apps = apps;
|
||||
}
|
||||
Ok(workspaces)
|
||||
})?;
|
||||
@ -72,7 +69,7 @@ impl FolderMigration {
|
||||
}
|
||||
|
||||
let trash = conn.immediate_transaction::<_, FlowyError, _>(|| {
|
||||
let trash = TrashTableSql::read_all(conn)?.take_items();
|
||||
let trash = TrashTableSql::read_all(conn)?;
|
||||
Ok(trash)
|
||||
})?;
|
||||
|
||||
|
@ -9,12 +9,7 @@ use crate::{
|
||||
};
|
||||
use flowy_database::ConnectionPool;
|
||||
use flowy_error::{FlowyError, FlowyResult};
|
||||
use flowy_folder_data_model::entities::{
|
||||
app::App,
|
||||
trash::{RepeatedTrash, Trash},
|
||||
view::View,
|
||||
workspace::Workspace,
|
||||
};
|
||||
use flowy_folder_data_model::revision::{AppRevision, TrashRevision, ViewRevision, WorkspaceRevision};
|
||||
use flowy_revision::disk::{RevisionRecord, RevisionState};
|
||||
use flowy_revision::mk_revision_disk_cache;
|
||||
use flowy_sync::client_folder::initial_folder_delta;
|
||||
@ -24,27 +19,27 @@ use tokio::sync::RwLock;
|
||||
pub use version_1::{app_sql::*, trash_sql::*, v1_impl::V1Transaction, view_sql::*, workspace_sql::*};
|
||||
|
||||
pub trait FolderPersistenceTransaction {
|
||||
fn create_workspace(&self, user_id: &str, workspace: Workspace) -> FlowyResult<()>;
|
||||
fn read_workspaces(&self, user_id: &str, workspace_id: Option<String>) -> FlowyResult<Vec<Workspace>>;
|
||||
fn create_workspace(&self, user_id: &str, workspace_rev: WorkspaceRevision) -> FlowyResult<()>;
|
||||
fn read_workspaces(&self, user_id: &str, workspace_id: Option<String>) -> FlowyResult<Vec<WorkspaceRevision>>;
|
||||
fn update_workspace(&self, changeset: WorkspaceChangeset) -> FlowyResult<()>;
|
||||
fn delete_workspace(&self, workspace_id: &str) -> FlowyResult<()>;
|
||||
|
||||
fn create_app(&self, app: App) -> FlowyResult<()>;
|
||||
fn create_app(&self, app_rev: AppRevision) -> FlowyResult<()>;
|
||||
fn update_app(&self, changeset: AppChangeset) -> FlowyResult<()>;
|
||||
fn read_app(&self, app_id: &str) -> FlowyResult<App>;
|
||||
fn read_workspace_apps(&self, workspace_id: &str) -> FlowyResult<Vec<App>>;
|
||||
fn delete_app(&self, app_id: &str) -> FlowyResult<App>;
|
||||
fn read_app(&self, app_id: &str) -> FlowyResult<AppRevision>;
|
||||
fn read_workspace_apps(&self, workspace_id: &str) -> FlowyResult<Vec<AppRevision>>;
|
||||
fn delete_app(&self, app_id: &str) -> FlowyResult<AppRevision>;
|
||||
fn move_app(&self, app_id: &str, from: usize, to: usize) -> FlowyResult<()>;
|
||||
|
||||
fn create_view(&self, view: View) -> FlowyResult<()>;
|
||||
fn read_view(&self, view_id: &str) -> FlowyResult<View>;
|
||||
fn read_views(&self, belong_to_id: &str) -> FlowyResult<Vec<View>>;
|
||||
fn create_view(&self, view_rev: ViewRevision) -> FlowyResult<()>;
|
||||
fn read_view(&self, view_id: &str) -> FlowyResult<ViewRevision>;
|
||||
fn read_views(&self, belong_to_id: &str) -> FlowyResult<Vec<ViewRevision>>;
|
||||
fn update_view(&self, changeset: ViewChangeset) -> FlowyResult<()>;
|
||||
fn delete_view(&self, view_id: &str) -> FlowyResult<()>;
|
||||
fn move_view(&self, view_id: &str, from: usize, to: usize) -> FlowyResult<()>;
|
||||
|
||||
fn create_trash(&self, trashes: Vec<Trash>) -> FlowyResult<()>;
|
||||
fn read_trash(&self, trash_id: Option<String>) -> FlowyResult<RepeatedTrash>;
|
||||
fn create_trash(&self, trashes: Vec<TrashRevision>) -> FlowyResult<()>;
|
||||
fn read_trash(&self, trash_id: Option<String>) -> FlowyResult<Vec<TrashRevision>>;
|
||||
fn delete_trash(&self, trash_ids: Option<Vec<String>>) -> FlowyResult<()>;
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
use crate::entities::{
|
||||
app::{App, UpdateAppParams},
|
||||
trash::{Trash, TrashType},
|
||||
view::RepeatedView,
|
||||
app::UpdateAppParams,
|
||||
trash::{TrashPB, TrashType},
|
||||
};
|
||||
use crate::{errors::FlowyError, services::persistence::version_1::workspace_sql::WorkspaceTable};
|
||||
use flowy_database::{
|
||||
@ -9,11 +8,12 @@ use flowy_database::{
|
||||
schema::{app_table, app_table::dsl},
|
||||
SqliteConnection,
|
||||
};
|
||||
use flowy_folder_data_model::revision::AppRevision;
|
||||
|
||||
pub struct AppTableSql();
|
||||
impl AppTableSql {
|
||||
pub(crate) fn create_app(app: App, conn: &SqliteConnection) -> Result<(), FlowyError> {
|
||||
let app_table = AppTable::new(app);
|
||||
pub(crate) fn create_app(app_rev: AppRevision, conn: &SqliteConnection) -> Result<(), FlowyError> {
|
||||
let app_table = AppTable::new(app_rev);
|
||||
match diesel_record_count!(app_table, &app_table.id, conn) {
|
||||
0 => diesel_insert_table!(app_table, &app_table, conn),
|
||||
_ => {
|
||||
@ -91,25 +91,25 @@ pub(crate) struct AppTable {
|
||||
}
|
||||
|
||||
impl AppTable {
|
||||
pub fn new(app: App) -> Self {
|
||||
pub fn new(app_rev: AppRevision) -> Self {
|
||||
Self {
|
||||
id: app.id,
|
||||
workspace_id: app.workspace_id,
|
||||
name: app.name,
|
||||
desc: app.desc,
|
||||
id: app_rev.id,
|
||||
workspace_id: app_rev.workspace_id,
|
||||
name: app_rev.name,
|
||||
desc: app_rev.desc,
|
||||
color_style: Default::default(),
|
||||
last_view_id: None,
|
||||
modified_time: app.modified_time,
|
||||
create_time: app.create_time,
|
||||
modified_time: app_rev.modified_time,
|
||||
create_time: app_rev.create_time,
|
||||
version: 0,
|
||||
is_trash: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::From<AppTable> for Trash {
|
||||
impl std::convert::From<AppTable> for TrashPB {
|
||||
fn from(table: AppTable) -> Self {
|
||||
Trash {
|
||||
TrashPB {
|
||||
id: table.id,
|
||||
name: table.name,
|
||||
modified_time: table.modified_time,
|
||||
@ -147,14 +147,14 @@ impl AppChangeset {
|
||||
}
|
||||
}
|
||||
}
|
||||
impl std::convert::From<AppTable> for App {
|
||||
impl std::convert::From<AppTable> for AppRevision {
|
||||
fn from(table: AppTable) -> Self {
|
||||
App {
|
||||
AppRevision {
|
||||
id: table.id,
|
||||
workspace_id: table.workspace_id,
|
||||
name: table.name,
|
||||
desc: table.desc,
|
||||
belongings: RepeatedView::default(),
|
||||
belongings: vec![],
|
||||
version: table.version,
|
||||
modified_time: table.modified_time,
|
||||
create_time: table.create_time,
|
||||
|
@ -1,19 +1,17 @@
|
||||
use crate::{
|
||||
entities::trash::{RepeatedTrash, Trash, TrashType},
|
||||
errors::FlowyError,
|
||||
};
|
||||
use crate::errors::FlowyError;
|
||||
use diesel::sql_types::Integer;
|
||||
use flowy_database::{
|
||||
prelude::*,
|
||||
schema::{trash_table, trash_table::dsl},
|
||||
SqliteConnection,
|
||||
};
|
||||
use flowy_folder_data_model::revision::{TrashRevision, TrashTypeRevision};
|
||||
|
||||
pub struct TrashTableSql();
|
||||
impl TrashTableSql {
|
||||
pub(crate) fn create_trash(trashes: Vec<Trash>, conn: &SqliteConnection) -> Result<(), FlowyError> {
|
||||
for trash in trashes {
|
||||
let trash_table: TrashTable = trash.into();
|
||||
pub(crate) fn create_trash(trashes: Vec<TrashRevision>, conn: &SqliteConnection) -> Result<(), FlowyError> {
|
||||
for trash_rev in trashes {
|
||||
let trash_table: TrashTable = trash_rev.into();
|
||||
match diesel_record_count!(trash_table, &trash_table.id, conn) {
|
||||
0 => diesel_insert_table!(trash_table, &trash_table, conn),
|
||||
_ => {
|
||||
@ -26,10 +24,13 @@ impl TrashTableSql {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn read_all(conn: &SqliteConnection) -> Result<RepeatedTrash, FlowyError> {
|
||||
pub(crate) fn read_all(conn: &SqliteConnection) -> Result<Vec<TrashRevision>, FlowyError> {
|
||||
let trash_tables = dsl::trash_table.load::<TrashTable>(conn)?;
|
||||
let items = trash_tables.into_iter().map(|t| t.into()).collect::<Vec<Trash>>();
|
||||
Ok(RepeatedTrash { items })
|
||||
let items = trash_tables
|
||||
.into_iter()
|
||||
.map(TrashRevision::from)
|
||||
.collect::<Vec<TrashRevision>>();
|
||||
Ok(items)
|
||||
}
|
||||
|
||||
pub(crate) fn delete_all(conn: &SqliteConnection) -> Result<(), FlowyError> {
|
||||
@ -60,27 +61,39 @@ pub(crate) struct TrashTable {
|
||||
pub create_time: i64,
|
||||
pub ty: SqlTrashType,
|
||||
}
|
||||
impl std::convert::From<TrashTable> for Trash {
|
||||
fn from(table: TrashTable) -> Self {
|
||||
Trash {
|
||||
id: table.id,
|
||||
name: table.name,
|
||||
modified_time: table.modified_time,
|
||||
create_time: table.create_time,
|
||||
ty: table.ty.into(),
|
||||
// impl std::convert::From<TrashTable> for Trash {
|
||||
// fn from(table: TrashTable) -> Self {
|
||||
// Trash {
|
||||
// id: table.id,
|
||||
// name: table.name,
|
||||
// modified_time: table.modified_time,
|
||||
// create_time: table.create_time,
|
||||
// ty: table.ty.into(),
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
impl std::convert::From<TrashTable> for TrashRevision {
|
||||
fn from(trash: TrashTable) -> Self {
|
||||
TrashRevision {
|
||||
id: trash.id,
|
||||
name: trash.name,
|
||||
modified_time: trash.modified_time,
|
||||
create_time: trash.create_time,
|
||||
ty: trash.ty.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::From<Trash> for TrashTable {
|
||||
fn from(trash: Trash) -> Self {
|
||||
impl std::convert::From<TrashRevision> for TrashTable {
|
||||
fn from(trash_rev: TrashRevision) -> Self {
|
||||
TrashTable {
|
||||
id: trash.id,
|
||||
name: trash.name,
|
||||
desc: "".to_owned(),
|
||||
modified_time: trash.modified_time,
|
||||
create_time: trash.create_time,
|
||||
ty: trash.ty.into(),
|
||||
id: trash_rev.id,
|
||||
name: trash_rev.name,
|
||||
desc: "".to_string(),
|
||||
modified_time: trash_rev.modified_time,
|
||||
create_time: trash_rev.create_time,
|
||||
ty: trash_rev.ty.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -125,22 +138,22 @@ impl std::convert::From<i32> for SqlTrashType {
|
||||
|
||||
impl_sql_integer_expression!(SqlTrashType);
|
||||
|
||||
impl std::convert::From<SqlTrashType> for TrashType {
|
||||
impl std::convert::From<SqlTrashType> for TrashTypeRevision {
|
||||
fn from(ty: SqlTrashType) -> Self {
|
||||
match ty {
|
||||
SqlTrashType::Unknown => TrashType::Unknown,
|
||||
SqlTrashType::View => TrashType::TrashView,
|
||||
SqlTrashType::App => TrashType::TrashApp,
|
||||
SqlTrashType::Unknown => TrashTypeRevision::Unknown,
|
||||
SqlTrashType::View => TrashTypeRevision::TrashView,
|
||||
SqlTrashType::App => TrashTypeRevision::TrashApp,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::From<TrashType> for SqlTrashType {
|
||||
fn from(ty: TrashType) -> Self {
|
||||
impl std::convert::From<TrashTypeRevision> for SqlTrashType {
|
||||
fn from(ty: TrashTypeRevision) -> Self {
|
||||
match ty {
|
||||
TrashType::Unknown => SqlTrashType::Unknown,
|
||||
TrashType::TrashView => SqlTrashType::View,
|
||||
TrashType::TrashApp => SqlTrashType::App,
|
||||
TrashTypeRevision::Unknown => SqlTrashType::Unknown,
|
||||
TrashTypeRevision::TrashView => SqlTrashType::View,
|
||||
TrashTypeRevision::TrashApp => SqlTrashType::App,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,24 +8,20 @@ use crate::services::persistence::{
|
||||
};
|
||||
use flowy_database::DBConnection;
|
||||
use flowy_error::FlowyResult;
|
||||
use flowy_folder_data_model::entities::{
|
||||
app::App,
|
||||
trash::{RepeatedTrash, Trash},
|
||||
view::View,
|
||||
workspace::Workspace,
|
||||
};
|
||||
use flowy_folder_data_model::revision::{AppRevision, TrashRevision, ViewRevision, WorkspaceRevision};
|
||||
|
||||
/// V1Transaction is deprecated since version 0.0.2 version
|
||||
pub struct V1Transaction<'a>(pub &'a DBConnection);
|
||||
|
||||
impl<'a> FolderPersistenceTransaction for V1Transaction<'a> {
|
||||
fn create_workspace(&self, user_id: &str, workspace: Workspace) -> FlowyResult<()> {
|
||||
let _ = WorkspaceTableSql::create_workspace(user_id, workspace, &*self.0)?;
|
||||
fn create_workspace(&self, user_id: &str, workspace_rev: WorkspaceRevision) -> FlowyResult<()> {
|
||||
let _ = WorkspaceTableSql::create_workspace(user_id, workspace_rev, &*self.0)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn read_workspaces(&self, user_id: &str, workspace_id: Option<String>) -> FlowyResult<Vec<Workspace>> {
|
||||
fn read_workspaces(&self, user_id: &str, workspace_id: Option<String>) -> FlowyResult<Vec<WorkspaceRevision>> {
|
||||
let tables = WorkspaceTableSql::read_workspaces(user_id, workspace_id, &*self.0)?;
|
||||
let workspaces = tables.into_iter().map(Workspace::from).collect::<Vec<_>>();
|
||||
let workspaces = tables.into_iter().map(WorkspaceRevision::from).collect::<Vec<_>>();
|
||||
Ok(workspaces)
|
||||
}
|
||||
|
||||
@ -37,8 +33,8 @@ impl<'a> FolderPersistenceTransaction for V1Transaction<'a> {
|
||||
WorkspaceTableSql::delete_workspace(workspace_id, &*self.0)
|
||||
}
|
||||
|
||||
fn create_app(&self, app: App) -> FlowyResult<()> {
|
||||
let _ = AppTableSql::create_app(app, &*self.0)?;
|
||||
fn create_app(&self, app_rev: AppRevision) -> FlowyResult<()> {
|
||||
let _ = AppTableSql::create_app(app_rev, &*self.0)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -47,39 +43,39 @@ impl<'a> FolderPersistenceTransaction for V1Transaction<'a> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn read_app(&self, app_id: &str) -> FlowyResult<App> {
|
||||
let table = AppTableSql::read_app(app_id, &*self.0)?;
|
||||
Ok(App::from(table))
|
||||
fn read_app(&self, app_id: &str) -> FlowyResult<AppRevision> {
|
||||
let app_revision: AppRevision = AppTableSql::read_app(app_id, &*self.0)?.into();
|
||||
Ok(app_revision)
|
||||
}
|
||||
|
||||
fn read_workspace_apps(&self, workspace_id: &str) -> FlowyResult<Vec<App>> {
|
||||
fn read_workspace_apps(&self, workspace_id: &str) -> FlowyResult<Vec<AppRevision>> {
|
||||
let tables = AppTableSql::read_workspace_apps(workspace_id, &*self.0)?;
|
||||
let apps = tables.into_iter().map(App::from).collect::<Vec<_>>();
|
||||
let apps = tables.into_iter().map(AppRevision::from).collect::<Vec<_>>();
|
||||
Ok(apps)
|
||||
}
|
||||
|
||||
fn delete_app(&self, app_id: &str) -> FlowyResult<App> {
|
||||
let table = AppTableSql::delete_app(app_id, &*self.0)?;
|
||||
Ok(App::from(table))
|
||||
fn delete_app(&self, app_id: &str) -> FlowyResult<AppRevision> {
|
||||
let app_revision: AppRevision = AppTableSql::delete_app(app_id, &*self.0)?.into();
|
||||
Ok(app_revision)
|
||||
}
|
||||
|
||||
fn move_app(&self, _app_id: &str, _from: usize, _to: usize) -> FlowyResult<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn create_view(&self, view: View) -> FlowyResult<()> {
|
||||
let _ = ViewTableSql::create_view(view, &*self.0)?;
|
||||
fn create_view(&self, view_rev: ViewRevision) -> FlowyResult<()> {
|
||||
let _ = ViewTableSql::create_view(view_rev, &*self.0)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn read_view(&self, view_id: &str) -> FlowyResult<View> {
|
||||
let table = ViewTableSql::read_view(view_id, &*self.0)?;
|
||||
Ok(View::from(table))
|
||||
fn read_view(&self, view_id: &str) -> FlowyResult<ViewRevision> {
|
||||
let view_revision: ViewRevision = ViewTableSql::read_view(view_id, &*self.0)?.into();
|
||||
Ok(view_revision)
|
||||
}
|
||||
|
||||
fn read_views(&self, belong_to_id: &str) -> FlowyResult<Vec<View>> {
|
||||
fn read_views(&self, belong_to_id: &str) -> FlowyResult<Vec<ViewRevision>> {
|
||||
let tables = ViewTableSql::read_views(belong_to_id, &*self.0)?;
|
||||
let views = tables.into_iter().map(View::from).collect::<Vec<_>>();
|
||||
let views = tables.into_iter().map(ViewRevision::from).collect::<Vec<_>>();
|
||||
Ok(views)
|
||||
}
|
||||
|
||||
@ -97,19 +93,17 @@ impl<'a> FolderPersistenceTransaction for V1Transaction<'a> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn create_trash(&self, trashes: Vec<Trash>) -> FlowyResult<()> {
|
||||
fn create_trash(&self, trashes: Vec<TrashRevision>) -> FlowyResult<()> {
|
||||
let _ = TrashTableSql::create_trash(trashes, &*self.0)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn read_trash(&self, trash_id: Option<String>) -> FlowyResult<RepeatedTrash> {
|
||||
fn read_trash(&self, trash_id: Option<String>) -> FlowyResult<Vec<TrashRevision>> {
|
||||
match trash_id {
|
||||
None => TrashTableSql::read_all(&*self.0),
|
||||
Some(trash_id) => {
|
||||
let table = TrashTableSql::read(&trash_id, &*self.0)?;
|
||||
Ok(RepeatedTrash {
|
||||
items: vec![Trash::from(table)],
|
||||
})
|
||||
let trash_revision: TrashRevision = TrashTableSql::read(&trash_id, &*self.0)?.into();
|
||||
Ok(vec![trash_revision])
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -132,11 +126,11 @@ impl<T> FolderPersistenceTransaction for Box<T>
|
||||
where
|
||||
T: FolderPersistenceTransaction + ?Sized,
|
||||
{
|
||||
fn create_workspace(&self, user_id: &str, workspace: Workspace) -> FlowyResult<()> {
|
||||
(**self).create_workspace(user_id, workspace)
|
||||
fn create_workspace(&self, user_id: &str, workspace_rev: WorkspaceRevision) -> FlowyResult<()> {
|
||||
(**self).create_workspace(user_id, workspace_rev)
|
||||
}
|
||||
|
||||
fn read_workspaces(&self, user_id: &str, workspace_id: Option<String>) -> FlowyResult<Vec<Workspace>> {
|
||||
fn read_workspaces(&self, user_id: &str, workspace_id: Option<String>) -> FlowyResult<Vec<WorkspaceRevision>> {
|
||||
(**self).read_workspaces(user_id, workspace_id)
|
||||
}
|
||||
|
||||
@ -148,23 +142,23 @@ where
|
||||
(**self).delete_workspace(workspace_id)
|
||||
}
|
||||
|
||||
fn create_app(&self, app: App) -> FlowyResult<()> {
|
||||
(**self).create_app(app)
|
||||
fn create_app(&self, app_rev: AppRevision) -> FlowyResult<()> {
|
||||
(**self).create_app(app_rev)
|
||||
}
|
||||
|
||||
fn update_app(&self, changeset: AppChangeset) -> FlowyResult<()> {
|
||||
(**self).update_app(changeset)
|
||||
}
|
||||
|
||||
fn read_app(&self, app_id: &str) -> FlowyResult<App> {
|
||||
fn read_app(&self, app_id: &str) -> FlowyResult<AppRevision> {
|
||||
(**self).read_app(app_id)
|
||||
}
|
||||
|
||||
fn read_workspace_apps(&self, workspace_id: &str) -> FlowyResult<Vec<App>> {
|
||||
fn read_workspace_apps(&self, workspace_id: &str) -> FlowyResult<Vec<AppRevision>> {
|
||||
(**self).read_workspace_apps(workspace_id)
|
||||
}
|
||||
|
||||
fn delete_app(&self, app_id: &str) -> FlowyResult<App> {
|
||||
fn delete_app(&self, app_id: &str) -> FlowyResult<AppRevision> {
|
||||
(**self).delete_app(app_id)
|
||||
}
|
||||
|
||||
@ -172,15 +166,15 @@ where
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn create_view(&self, view: View) -> FlowyResult<()> {
|
||||
(**self).create_view(view)
|
||||
fn create_view(&self, view_rev: ViewRevision) -> FlowyResult<()> {
|
||||
(**self).create_view(view_rev)
|
||||
}
|
||||
|
||||
fn read_view(&self, view_id: &str) -> FlowyResult<View> {
|
||||
fn read_view(&self, view_id: &str) -> FlowyResult<ViewRevision> {
|
||||
(**self).read_view(view_id)
|
||||
}
|
||||
|
||||
fn read_views(&self, belong_to_id: &str) -> FlowyResult<Vec<View>> {
|
||||
fn read_views(&self, belong_to_id: &str) -> FlowyResult<Vec<ViewRevision>> {
|
||||
(**self).read_views(belong_to_id)
|
||||
}
|
||||
|
||||
@ -196,11 +190,11 @@ where
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn create_trash(&self, trashes: Vec<Trash>) -> FlowyResult<()> {
|
||||
fn create_trash(&self, trashes: Vec<TrashRevision>) -> FlowyResult<()> {
|
||||
(**self).create_trash(trashes)
|
||||
}
|
||||
|
||||
fn read_trash(&self, trash_id: Option<String>) -> FlowyResult<RepeatedTrash> {
|
||||
fn read_trash(&self, trash_id: Option<String>) -> FlowyResult<Vec<TrashRevision>> {
|
||||
(**self).read_trash(trash_id)
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::{
|
||||
entities::{
|
||||
trash::{Trash, TrashType},
|
||||
view::{RepeatedView, UpdateViewParams, View, ViewDataType},
|
||||
trash::{TrashPB, TrashType},
|
||||
view::UpdateViewParams,
|
||||
},
|
||||
errors::FlowyError,
|
||||
services::persistence::version_1::app_sql::AppTable,
|
||||
@ -12,12 +12,14 @@ use flowy_database::{
|
||||
schema::{view_table, view_table::dsl},
|
||||
SqliteConnection,
|
||||
};
|
||||
|
||||
use flowy_folder_data_model::revision::{ViewDataTypeRevision, ViewRevision};
|
||||
use lib_infra::util::timestamp;
|
||||
|
||||
pub struct ViewTableSql();
|
||||
impl ViewTableSql {
|
||||
pub(crate) fn create_view(view: View, conn: &SqliteConnection) -> Result<(), FlowyError> {
|
||||
let view_table = ViewTable::new(view);
|
||||
pub(crate) fn create_view(view_rev: ViewRevision, conn: &SqliteConnection) -> Result<(), FlowyError> {
|
||||
let view_table = ViewTable::new(view_rev);
|
||||
match diesel_record_count!(view_table, &view_table.id, conn) {
|
||||
0 => diesel_insert_table!(view_table, &view_table, conn),
|
||||
_ => {
|
||||
@ -79,59 +81,61 @@ pub(crate) struct ViewTable {
|
||||
pub view_type: SqlViewDataType,
|
||||
pub version: i64,
|
||||
pub is_trash: bool,
|
||||
pub ext_data: String,
|
||||
}
|
||||
|
||||
impl ViewTable {
|
||||
pub fn new(view: View) -> Self {
|
||||
let data_type = match view.data_type {
|
||||
ViewDataType::TextBlock => SqlViewDataType::Block,
|
||||
ViewDataType::Grid => SqlViewDataType::Grid,
|
||||
pub fn new(view_rev: ViewRevision) -> Self {
|
||||
let data_type = match view_rev.data_type {
|
||||
ViewDataTypeRevision::TextBlock => SqlViewDataType::Block,
|
||||
ViewDataTypeRevision::Grid => SqlViewDataType::Grid,
|
||||
};
|
||||
|
||||
ViewTable {
|
||||
id: view.id,
|
||||
belong_to_id: view.belong_to_id,
|
||||
name: view.name,
|
||||
desc: view.desc,
|
||||
modified_time: view.modified_time,
|
||||
create_time: view.create_time,
|
||||
thumbnail: view.thumbnail,
|
||||
id: view_rev.id,
|
||||
belong_to_id: view_rev.belong_to_id,
|
||||
name: view_rev.name,
|
||||
desc: view_rev.desc,
|
||||
modified_time: view_rev.modified_time,
|
||||
create_time: view_rev.create_time,
|
||||
thumbnail: view_rev.thumbnail,
|
||||
view_type: data_type,
|
||||
version: 0,
|
||||
ext_data: view_rev.ext_data,
|
||||
version: view_rev.version,
|
||||
is_trash: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::From<ViewTable> for View {
|
||||
impl std::convert::From<ViewTable> for ViewRevision {
|
||||
fn from(table: ViewTable) -> Self {
|
||||
let data_type = match table.view_type {
|
||||
SqlViewDataType::Block => ViewDataType::TextBlock,
|
||||
SqlViewDataType::Grid => ViewDataType::Grid,
|
||||
SqlViewDataType::Block => ViewDataTypeRevision::TextBlock,
|
||||
SqlViewDataType::Grid => ViewDataTypeRevision::Grid,
|
||||
};
|
||||
|
||||
View {
|
||||
ViewRevision {
|
||||
id: table.id,
|
||||
belong_to_id: table.belong_to_id,
|
||||
name: table.name,
|
||||
desc: table.desc,
|
||||
data_type,
|
||||
belongings: RepeatedView::default(),
|
||||
belongings: vec![],
|
||||
modified_time: table.modified_time,
|
||||
version: table.version,
|
||||
create_time: table.create_time,
|
||||
ext_data: "".to_string(),
|
||||
thumbnail: table.thumbnail,
|
||||
// Store the view in ViewTable was deprecated since v0.0.2.
|
||||
// No need worry about plugin_type.
|
||||
// No need to worry about plugin_type.
|
||||
plugin_type: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::From<ViewTable> for Trash {
|
||||
impl std::convert::From<ViewTable> for TrashPB {
|
||||
fn from(table: ViewTable) -> Self {
|
||||
Trash {
|
||||
TrashPB {
|
||||
id: table.id,
|
||||
name: table.name,
|
||||
modified_time: table.modified_time,
|
||||
|
@ -1,23 +1,19 @@
|
||||
use crate::{
|
||||
entities::{
|
||||
app::RepeatedApp,
|
||||
workspace::{UpdateWorkspaceParams, Workspace},
|
||||
},
|
||||
errors::FlowyError,
|
||||
};
|
||||
use crate::{entities::workspace::UpdateWorkspaceParams, errors::FlowyError};
|
||||
use diesel::SqliteConnection;
|
||||
use flowy_database::{
|
||||
prelude::*,
|
||||
schema::{workspace_table, workspace_table::dsl},
|
||||
};
|
||||
use flowy_folder_data_model::revision::WorkspaceRevision;
|
||||
|
||||
pub(crate) struct WorkspaceTableSql();
|
||||
impl WorkspaceTableSql {
|
||||
pub(crate) fn create_workspace(
|
||||
user_id: &str,
|
||||
workspace: Workspace,
|
||||
workspace_rev: WorkspaceRevision,
|
||||
conn: &SqliteConnection,
|
||||
) -> Result<(), FlowyError> {
|
||||
let table = WorkspaceTable::new(workspace, user_id);
|
||||
let table = WorkspaceTable::new(workspace_rev, user_id);
|
||||
match diesel_record_count!(workspace_table, &table.id, conn) {
|
||||
0 => diesel_insert_table!(workspace_table, &table, conn),
|
||||
_ => {
|
||||
@ -74,26 +70,26 @@ pub struct WorkspaceTable {
|
||||
|
||||
impl WorkspaceTable {
|
||||
#[allow(dead_code)]
|
||||
pub fn new(workspace: Workspace, user_id: &str) -> Self {
|
||||
pub fn new(workspace_rev: WorkspaceRevision, user_id: &str) -> Self {
|
||||
WorkspaceTable {
|
||||
id: workspace.id,
|
||||
name: workspace.name,
|
||||
desc: workspace.desc,
|
||||
modified_time: workspace.modified_time,
|
||||
create_time: workspace.create_time,
|
||||
id: workspace_rev.id,
|
||||
name: workspace_rev.name,
|
||||
desc: workspace_rev.desc,
|
||||
modified_time: workspace_rev.modified_time,
|
||||
create_time: workspace_rev.create_time,
|
||||
user_id: user_id.to_owned(),
|
||||
version: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::From<WorkspaceTable> for Workspace {
|
||||
impl std::convert::From<WorkspaceTable> for WorkspaceRevision {
|
||||
fn from(table: WorkspaceTable) -> Self {
|
||||
Workspace {
|
||||
WorkspaceRevision {
|
||||
id: table.id,
|
||||
name: table.name,
|
||||
desc: table.desc,
|
||||
apps: RepeatedApp::default(),
|
||||
apps: vec![],
|
||||
modified_time: table.modified_time,
|
||||
create_time: table.create_time,
|
||||
}
|
||||
|
@ -3,23 +3,18 @@ use crate::services::{
|
||||
persistence::{AppChangeset, FolderPersistenceTransaction, ViewChangeset, WorkspaceChangeset},
|
||||
};
|
||||
use flowy_error::{FlowyError, FlowyResult};
|
||||
use flowy_folder_data_model::entities::{
|
||||
app::App,
|
||||
trash::{RepeatedTrash, Trash},
|
||||
view::View,
|
||||
workspace::Workspace,
|
||||
};
|
||||
use flowy_folder_data_model::revision::{AppRevision, TrashRevision, ViewRevision, WorkspaceRevision};
|
||||
use std::sync::Arc;
|
||||
|
||||
impl FolderPersistenceTransaction for FolderEditor {
|
||||
fn create_workspace(&self, _user_id: &str, workspace: Workspace) -> FlowyResult<()> {
|
||||
if let Some(change) = self.folder.write().create_workspace(workspace)? {
|
||||
fn create_workspace(&self, _user_id: &str, workspace_rev: WorkspaceRevision) -> FlowyResult<()> {
|
||||
if let Some(change) = self.folder.write().create_workspace(workspace_rev)? {
|
||||
let _ = self.apply_change(change)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn read_workspaces(&self, _user_id: &str, workspace_id: Option<String>) -> FlowyResult<Vec<Workspace>> {
|
||||
fn read_workspaces(&self, _user_id: &str, workspace_id: Option<String>) -> FlowyResult<Vec<WorkspaceRevision>> {
|
||||
let workspaces = self.folder.read().read_workspaces(workspace_id)?;
|
||||
Ok(workspaces)
|
||||
}
|
||||
@ -42,8 +37,8 @@ impl FolderPersistenceTransaction for FolderEditor {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn create_app(&self, app: App) -> FlowyResult<()> {
|
||||
if let Some(change) = self.folder.write().create_app(app)? {
|
||||
fn create_app(&self, app_rev: AppRevision) -> FlowyResult<()> {
|
||||
if let Some(change) = self.folder.write().create_app(app_rev)? {
|
||||
let _ = self.apply_change(change)?;
|
||||
}
|
||||
Ok(())
|
||||
@ -60,22 +55,22 @@ impl FolderPersistenceTransaction for FolderEditor {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn read_app(&self, app_id: &str) -> FlowyResult<App> {
|
||||
fn read_app(&self, app_id: &str) -> FlowyResult<AppRevision> {
|
||||
let app = self.folder.read().read_app(app_id)?;
|
||||
Ok(app)
|
||||
}
|
||||
|
||||
fn read_workspace_apps(&self, workspace_id: &str) -> FlowyResult<Vec<App>> {
|
||||
fn read_workspace_apps(&self, workspace_id: &str) -> FlowyResult<Vec<AppRevision>> {
|
||||
let workspaces = self.folder.read().read_workspaces(Some(workspace_id.to_owned()))?;
|
||||
match workspaces.first() {
|
||||
None => {
|
||||
Err(FlowyError::record_not_found().context(format!("can't find workspace with id {}", workspace_id)))
|
||||
}
|
||||
Some(workspace) => Ok(workspace.apps.clone().take_items()),
|
||||
Some(workspace) => Ok(workspace.apps.clone()),
|
||||
}
|
||||
}
|
||||
|
||||
fn delete_app(&self, app_id: &str) -> FlowyResult<App> {
|
||||
fn delete_app(&self, app_id: &str) -> FlowyResult<AppRevision> {
|
||||
let app = self.folder.read().read_app(app_id)?;
|
||||
if let Some(change) = self.folder.write().delete_app(app_id)? {
|
||||
let _ = self.apply_change(change)?;
|
||||
@ -90,19 +85,19 @@ impl FolderPersistenceTransaction for FolderEditor {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn create_view(&self, view: View) -> FlowyResult<()> {
|
||||
if let Some(change) = self.folder.write().create_view(view)? {
|
||||
fn create_view(&self, view_rev: ViewRevision) -> FlowyResult<()> {
|
||||
if let Some(change) = self.folder.write().create_view(view_rev)? {
|
||||
let _ = self.apply_change(change)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn read_view(&self, view_id: &str) -> FlowyResult<View> {
|
||||
fn read_view(&self, view_id: &str) -> FlowyResult<ViewRevision> {
|
||||
let view = self.folder.read().read_view(view_id)?;
|
||||
Ok(view)
|
||||
}
|
||||
|
||||
fn read_views(&self, belong_to_id: &str) -> FlowyResult<Vec<View>> {
|
||||
fn read_views(&self, belong_to_id: &str) -> FlowyResult<Vec<ViewRevision>> {
|
||||
let views = self.folder.read().read_views(belong_to_id)?;
|
||||
Ok(views)
|
||||
}
|
||||
@ -132,16 +127,16 @@ impl FolderPersistenceTransaction for FolderEditor {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn create_trash(&self, trashes: Vec<Trash>) -> FlowyResult<()> {
|
||||
fn create_trash(&self, trashes: Vec<TrashRevision>) -> FlowyResult<()> {
|
||||
if let Some(change) = self.folder.write().create_trash(trashes)? {
|
||||
let _ = self.apply_change(change)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn read_trash(&self, trash_id: Option<String>) -> FlowyResult<RepeatedTrash> {
|
||||
fn read_trash(&self, trash_id: Option<String>) -> FlowyResult<Vec<TrashRevision>> {
|
||||
let trash = self.folder.read().read_trash(trash_id)?;
|
||||
Ok(RepeatedTrash { items: trash })
|
||||
Ok(trash)
|
||||
}
|
||||
|
||||
fn delete_trash(&self, trash_ids: Option<Vec<String>>) -> FlowyResult<()> {
|
||||
@ -156,11 +151,11 @@ impl<T> FolderPersistenceTransaction for Arc<T>
|
||||
where
|
||||
T: FolderPersistenceTransaction + ?Sized,
|
||||
{
|
||||
fn create_workspace(&self, user_id: &str, workspace: Workspace) -> FlowyResult<()> {
|
||||
(**self).create_workspace(user_id, workspace)
|
||||
fn create_workspace(&self, user_id: &str, workspace_rev: WorkspaceRevision) -> FlowyResult<()> {
|
||||
(**self).create_workspace(user_id, workspace_rev)
|
||||
}
|
||||
|
||||
fn read_workspaces(&self, user_id: &str, workspace_id: Option<String>) -> FlowyResult<Vec<Workspace>> {
|
||||
fn read_workspaces(&self, user_id: &str, workspace_id: Option<String>) -> FlowyResult<Vec<WorkspaceRevision>> {
|
||||
(**self).read_workspaces(user_id, workspace_id)
|
||||
}
|
||||
|
||||
@ -172,23 +167,23 @@ where
|
||||
(**self).delete_workspace(workspace_id)
|
||||
}
|
||||
|
||||
fn create_app(&self, app: App) -> FlowyResult<()> {
|
||||
(**self).create_app(app)
|
||||
fn create_app(&self, app_rev: AppRevision) -> FlowyResult<()> {
|
||||
(**self).create_app(app_rev)
|
||||
}
|
||||
|
||||
fn update_app(&self, changeset: AppChangeset) -> FlowyResult<()> {
|
||||
(**self).update_app(changeset)
|
||||
}
|
||||
|
||||
fn read_app(&self, app_id: &str) -> FlowyResult<App> {
|
||||
fn read_app(&self, app_id: &str) -> FlowyResult<AppRevision> {
|
||||
(**self).read_app(app_id)
|
||||
}
|
||||
|
||||
fn read_workspace_apps(&self, workspace_id: &str) -> FlowyResult<Vec<App>> {
|
||||
fn read_workspace_apps(&self, workspace_id: &str) -> FlowyResult<Vec<AppRevision>> {
|
||||
(**self).read_workspace_apps(workspace_id)
|
||||
}
|
||||
|
||||
fn delete_app(&self, app_id: &str) -> FlowyResult<App> {
|
||||
fn delete_app(&self, app_id: &str) -> FlowyResult<AppRevision> {
|
||||
(**self).delete_app(app_id)
|
||||
}
|
||||
|
||||
@ -196,15 +191,15 @@ where
|
||||
(**self).move_app(app_id, from, to)
|
||||
}
|
||||
|
||||
fn create_view(&self, view: View) -> FlowyResult<()> {
|
||||
(**self).create_view(view)
|
||||
fn create_view(&self, view_rev: ViewRevision) -> FlowyResult<()> {
|
||||
(**self).create_view(view_rev)
|
||||
}
|
||||
|
||||
fn read_view(&self, view_id: &str) -> FlowyResult<View> {
|
||||
fn read_view(&self, view_id: &str) -> FlowyResult<ViewRevision> {
|
||||
(**self).read_view(view_id)
|
||||
}
|
||||
|
||||
fn read_views(&self, belong_to_id: &str) -> FlowyResult<Vec<View>> {
|
||||
fn read_views(&self, belong_to_id: &str) -> FlowyResult<Vec<ViewRevision>> {
|
||||
(**self).read_views(belong_to_id)
|
||||
}
|
||||
|
||||
@ -220,11 +215,11 @@ where
|
||||
(**self).move_view(view_id, from, to)
|
||||
}
|
||||
|
||||
fn create_trash(&self, trashes: Vec<Trash>) -> FlowyResult<()> {
|
||||
fn create_trash(&self, trashes: Vec<TrashRevision>) -> FlowyResult<()> {
|
||||
(**self).create_trash(trashes)
|
||||
}
|
||||
|
||||
fn read_trash(&self, trash_id: Option<String>) -> FlowyResult<RepeatedTrash> {
|
||||
fn read_trash(&self, trash_id: Option<String>) -> FlowyResult<Vec<TrashRevision>> {
|
||||
(**self).read_trash(trash_id)
|
||||
}
|
||||
|
||||
|
@ -1,11 +1,12 @@
|
||||
use crate::{
|
||||
dart_notification::{send_anonymous_dart_notification, FolderNotification},
|
||||
entities::trash::{RepeatedTrash, RepeatedTrashId, Trash, TrashId, TrashType},
|
||||
entities::trash::{RepeatedTrashIdPB, RepeatedTrashPB, TrashIdPB, TrashPB, TrashType},
|
||||
errors::{FlowyError, FlowyResult},
|
||||
event_map::{FolderCouldServiceV1, WorkspaceUser},
|
||||
services::persistence::{FolderPersistence, FolderPersistenceTransaction},
|
||||
};
|
||||
|
||||
use flowy_folder_data_model::revision::TrashRevision;
|
||||
use std::{fmt::Formatter, sync::Arc};
|
||||
use tokio::sync::{broadcast, mpsc};
|
||||
|
||||
@ -48,12 +49,12 @@ impl TrashController {
|
||||
})
|
||||
.await?;
|
||||
|
||||
let identifier = TrashId {
|
||||
let identifier = TrashIdPB {
|
||||
id: trash.id,
|
||||
ty: trash.ty,
|
||||
ty: trash.ty.into(),
|
||||
};
|
||||
|
||||
let _ = self.delete_trash_on_server(RepeatedTrashId {
|
||||
let _ = self.delete_trash_on_server(RepeatedTrashIdPB {
|
||||
items: vec![identifier.clone()],
|
||||
delete_all: false,
|
||||
})?;
|
||||
@ -66,54 +67,56 @@ impl TrashController {
|
||||
|
||||
#[tracing::instrument(level = "debug", skip(self) err)]
|
||||
pub async fn restore_all_trash(&self) -> FlowyResult<()> {
|
||||
let repeated_trash = self
|
||||
let trash_identifier: RepeatedTrashIdPB = self
|
||||
.persistence
|
||||
.begin_transaction(|transaction| {
|
||||
let trash = transaction.read_trash(None);
|
||||
let _ = transaction.delete_trash(None);
|
||||
trash
|
||||
})
|
||||
.await?;
|
||||
.await?
|
||||
.into();
|
||||
|
||||
let identifiers: RepeatedTrashId = repeated_trash.items.clone().into();
|
||||
let (tx, mut rx) = mpsc::channel::<FlowyResult<()>>(1);
|
||||
let _ = self.notify.send(TrashEvent::Putback(identifiers, tx));
|
||||
let _ = self.notify.send(TrashEvent::Putback(trash_identifier, tx));
|
||||
let _ = rx.recv().await;
|
||||
|
||||
notify_trash_changed(RepeatedTrash { items: vec![] });
|
||||
notify_trash_changed(RepeatedTrashPB { items: vec![] });
|
||||
let _ = self.delete_all_trash_on_server().await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip(self), err)]
|
||||
pub async fn delete_all_trash(&self) -> FlowyResult<()> {
|
||||
let repeated_trash = self
|
||||
let all_trash_identifiers: RepeatedTrashIdPB = self
|
||||
.persistence
|
||||
.begin_transaction(|transaction| transaction.read_trash(None))
|
||||
.await?;
|
||||
let trash_identifiers: RepeatedTrashId = repeated_trash.items.clone().into();
|
||||
let _ = self.delete_with_identifiers(trash_identifiers.clone()).await?;
|
||||
.await?
|
||||
.into();
|
||||
|
||||
notify_trash_changed(RepeatedTrash { items: vec![] });
|
||||
let _ = self.delete_with_identifiers(all_trash_identifiers).await?;
|
||||
|
||||
notify_trash_changed(RepeatedTrashPB { items: vec![] });
|
||||
let _ = self.delete_all_trash_on_server().await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip(self), err)]
|
||||
pub async fn delete(&self, trash_identifiers: RepeatedTrashId) -> FlowyResult<()> {
|
||||
pub async fn delete(&self, trash_identifiers: RepeatedTrashIdPB) -> FlowyResult<()> {
|
||||
let _ = self.delete_with_identifiers(trash_identifiers.clone()).await?;
|
||||
let repeated_trash = self
|
||||
let trash_revs = self
|
||||
.persistence
|
||||
.begin_transaction(|transaction| transaction.read_trash(None))
|
||||
.await?;
|
||||
notify_trash_changed(repeated_trash);
|
||||
|
||||
notify_trash_changed(trash_revs);
|
||||
let _ = self.delete_trash_on_server(trash_identifiers)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip(self), fields(delete_trash_ids), err)]
|
||||
pub async fn delete_with_identifiers(&self, trash_identifiers: RepeatedTrashId) -> FlowyResult<()> {
|
||||
pub async fn delete_with_identifiers(&self, trash_identifiers: RepeatedTrashIdPB) -> FlowyResult<()> {
|
||||
let (tx, mut rx) = mpsc::channel::<FlowyResult<()>>(1);
|
||||
tracing::Span::current().record("delete_trash_ids", &format!("{}", trash_identifiers).as_str());
|
||||
let _ = self.notify.send(TrashEvent::Delete(trash_identifiers.clone(), tx));
|
||||
@ -147,10 +150,10 @@ impl TrashController {
|
||||
// CREATE and DROP tables operations because those are auto-commit in the
|
||||
// database.
|
||||
#[tracing::instrument(name = "add_trash", level = "debug", skip(self, trash), fields(trash_ids), err)]
|
||||
pub async fn add<T: Into<Trash>>(&self, trash: Vec<T>) -> Result<(), FlowyError> {
|
||||
pub async fn add<T: Into<TrashRevision>>(&self, trash: Vec<T>) -> Result<(), FlowyError> {
|
||||
let (tx, mut rx) = mpsc::channel::<FlowyResult<()>>(1);
|
||||
let repeated_trash = trash.into_iter().map(|t| t.into()).collect::<Vec<Trash>>();
|
||||
let identifiers = repeated_trash.iter().map(|t| t.into()).collect::<Vec<TrashId>>();
|
||||
let trash_revs: Vec<TrashRevision> = trash.into_iter().map(|t| t.into()).collect();
|
||||
let identifiers = trash_revs.iter().map(|t| t.into()).collect::<Vec<TrashIdPB>>();
|
||||
|
||||
tracing::Span::current().record(
|
||||
"trash_ids",
|
||||
@ -167,8 +170,9 @@ impl TrashController {
|
||||
let _ = self
|
||||
.persistence
|
||||
.begin_transaction(|transaction| {
|
||||
let _ = transaction.create_trash(repeated_trash.clone())?;
|
||||
let _ = self.create_trash_on_server(repeated_trash);
|
||||
let _ = transaction.create_trash(trash_revs.clone())?;
|
||||
let _ = self.create_trash_on_server(trash_revs);
|
||||
|
||||
notify_trash_changed(transaction.read_trash(None)?);
|
||||
Ok(())
|
||||
})
|
||||
@ -183,13 +187,17 @@ impl TrashController {
|
||||
self.notify.subscribe()
|
||||
}
|
||||
|
||||
pub async fn read_trash(&self) -> Result<RepeatedTrash, FlowyError> {
|
||||
let repeated_trash = self
|
||||
pub async fn read_trash(&self) -> Result<RepeatedTrashPB, FlowyError> {
|
||||
let items: Vec<TrashPB> = self
|
||||
.persistence
|
||||
.begin_transaction(|transaction| transaction.read_trash(None))
|
||||
.await?;
|
||||
.await?
|
||||
.into_iter()
|
||||
.map(|trash_rev| trash_rev.into())
|
||||
.collect();
|
||||
|
||||
let _ = self.read_trash_on_server()?;
|
||||
Ok(repeated_trash)
|
||||
Ok(RepeatedTrashPB { items })
|
||||
}
|
||||
|
||||
pub fn read_trash_ids<'a>(
|
||||
@ -198,7 +206,6 @@ impl TrashController {
|
||||
) -> Result<Vec<String>, FlowyError> {
|
||||
let ids = transaction
|
||||
.read_trash(None)?
|
||||
.into_inner()
|
||||
.into_iter()
|
||||
.map(|item| item.id)
|
||||
.collect::<Vec<String>>();
|
||||
@ -208,7 +215,7 @@ impl TrashController {
|
||||
|
||||
impl TrashController {
|
||||
#[tracing::instrument(level = "trace", skip(self, trash), err)]
|
||||
fn create_trash_on_server<T: Into<RepeatedTrashId>>(&self, trash: T) -> FlowyResult<()> {
|
||||
fn create_trash_on_server<T: Into<RepeatedTrashIdPB>>(&self, trash: T) -> FlowyResult<()> {
|
||||
let token = self.user.token()?;
|
||||
let trash_identifiers = trash.into();
|
||||
let server = self.cloud_service.clone();
|
||||
@ -223,7 +230,7 @@ impl TrashController {
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "trace", skip(self, trash), err)]
|
||||
fn delete_trash_on_server<T: Into<RepeatedTrashId>>(&self, trash: T) -> FlowyResult<()> {
|
||||
fn delete_trash_on_server<T: Into<RepeatedTrashIdPB>>(&self, trash: T) -> FlowyResult<()> {
|
||||
let token = self.user.token()?;
|
||||
let trash_identifiers = trash.into();
|
||||
let server = self.cloud_service.clone();
|
||||
@ -244,18 +251,18 @@ impl TrashController {
|
||||
|
||||
tokio::spawn(async move {
|
||||
match server.read_trash(&token).await {
|
||||
Ok(repeated_trash) => {
|
||||
tracing::debug!("Remote trash count: {}", repeated_trash.items.len());
|
||||
Ok(trash_rev) => {
|
||||
tracing::debug!("Remote trash count: {}", trash_rev.len());
|
||||
let result = persistence
|
||||
.begin_transaction(|transaction| {
|
||||
let _ = transaction.create_trash(repeated_trash.items.clone())?;
|
||||
let _ = transaction.create_trash(trash_rev.clone())?;
|
||||
transaction.read_trash(None)
|
||||
})
|
||||
.await;
|
||||
|
||||
match result {
|
||||
Ok(repeated_trash) => {
|
||||
notify_trash_changed(repeated_trash);
|
||||
Ok(trash_revs) => {
|
||||
notify_trash_changed(trash_revs);
|
||||
}
|
||||
Err(e) => log::error!("Save trash failed: {:?}", e),
|
||||
}
|
||||
@ -270,12 +277,13 @@ impl TrashController {
|
||||
async fn delete_all_trash_on_server(&self) -> FlowyResult<()> {
|
||||
let token = self.user.token()?;
|
||||
let server = self.cloud_service.clone();
|
||||
server.delete_trash(&token, RepeatedTrashId::all()).await
|
||||
server.delete_trash(&token, RepeatedTrashIdPB::all()).await
|
||||
}
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip(repeated_trash), fields(n_trash))]
|
||||
fn notify_trash_changed(repeated_trash: RepeatedTrash) {
|
||||
fn notify_trash_changed<T: Into<RepeatedTrashPB>>(repeated_trash: T) {
|
||||
let repeated_trash = repeated_trash.into();
|
||||
tracing::Span::current().record("n_trash", &repeated_trash.len());
|
||||
send_anonymous_dart_notification(FolderNotification::TrashUpdated)
|
||||
.payload(repeated_trash)
|
||||
@ -284,9 +292,9 @@ fn notify_trash_changed(repeated_trash: RepeatedTrash) {
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum TrashEvent {
|
||||
NewTrash(RepeatedTrashId, mpsc::Sender<FlowyResult<()>>),
|
||||
Putback(RepeatedTrashId, mpsc::Sender<FlowyResult<()>>),
|
||||
Delete(RepeatedTrashId, mpsc::Sender<FlowyResult<()>>),
|
||||
NewTrash(RepeatedTrashIdPB, mpsc::Sender<FlowyResult<()>>),
|
||||
Putback(RepeatedTrashIdPB, mpsc::Sender<FlowyResult<()>>),
|
||||
Delete(RepeatedTrashIdPB, mpsc::Sender<FlowyResult<()>>),
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for TrashEvent {
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::{
|
||||
entities::trash::{RepeatedTrash, RepeatedTrashId, TrashId},
|
||||
entities::trash::{RepeatedTrashIdPB, RepeatedTrashPB, TrashIdPB},
|
||||
errors::FlowyError,
|
||||
services::TrashController,
|
||||
};
|
||||
@ -9,14 +9,14 @@ use std::sync::Arc;
|
||||
#[tracing::instrument(level = "debug", skip(controller), err)]
|
||||
pub(crate) async fn read_trash_handler(
|
||||
controller: AppData<Arc<TrashController>>,
|
||||
) -> DataResult<RepeatedTrash, FlowyError> {
|
||||
) -> DataResult<RepeatedTrashPB, FlowyError> {
|
||||
let repeated_trash = controller.read_trash().await?;
|
||||
data_result(repeated_trash)
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip(identifier, controller), err)]
|
||||
pub(crate) async fn putback_trash_handler(
|
||||
identifier: Data<TrashId>,
|
||||
identifier: Data<TrashIdPB>,
|
||||
controller: AppData<Arc<TrashController>>,
|
||||
) -> Result<(), FlowyError> {
|
||||
let _ = controller.putback(&identifier.id).await?;
|
||||
@ -25,7 +25,7 @@ pub(crate) async fn putback_trash_handler(
|
||||
|
||||
#[tracing::instrument(level = "debug", skip(identifiers, controller), err)]
|
||||
pub(crate) async fn delete_trash_handler(
|
||||
identifiers: Data<RepeatedTrashId>,
|
||||
identifiers: Data<RepeatedTrashIdPB>,
|
||||
controller: AppData<Arc<TrashController>>,
|
||||
) -> Result<(), FlowyError> {
|
||||
let _ = controller.delete(identifiers.into_inner()).await?;
|
||||
|
@ -1,9 +1,11 @@
|
||||
pub use crate::entities::view::ViewDataType;
|
||||
use crate::entities::ViewInfoPB;
|
||||
use crate::manager::{ViewDataProcessor, ViewDataProcessorMap};
|
||||
use crate::{
|
||||
dart_notification::{send_dart_notification, FolderNotification},
|
||||
entities::{
|
||||
trash::{RepeatedTrashId, TrashType},
|
||||
view::{CreateViewParams, RepeatedView, UpdateViewParams, View, ViewId},
|
||||
trash::{RepeatedTrashIdPB, TrashType},
|
||||
view::{CreateViewParams, RepeatedViewPB, UpdateViewParams, ViewIdPB, ViewPB},
|
||||
},
|
||||
errors::{FlowyError, FlowyResult},
|
||||
event_map::{FolderCouldServiceV1, WorkspaceUser},
|
||||
@ -14,8 +16,8 @@ use crate::{
|
||||
};
|
||||
use bytes::Bytes;
|
||||
use flowy_database::kv::KV;
|
||||
use flowy_folder_data_model::entities::view::{gen_view_id, ViewDataType};
|
||||
use flowy_sync::entities::text_block_info::TextBlockId;
|
||||
use flowy_folder_data_model::revision::{gen_view_id, ViewRevision};
|
||||
use flowy_sync::entities::text_block::TextBlockIdPB;
|
||||
use futures::{FutureExt, StreamExt};
|
||||
use std::{collections::HashSet, sync::Arc};
|
||||
|
||||
@ -52,24 +54,27 @@ impl ViewController {
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "trace", skip(self, params), fields(name = %params.name), err)]
|
||||
pub(crate) async fn create_view_from_params(&self, mut params: CreateViewParams) -> Result<View, FlowyError> {
|
||||
let processor = self.get_data_processor(¶ms.data_type)?;
|
||||
pub(crate) async fn create_view_from_params(
|
||||
&self,
|
||||
mut params: CreateViewParams,
|
||||
) -> Result<ViewRevision, FlowyError> {
|
||||
let processor = self.get_data_processor(params.data_type.clone())?;
|
||||
let user_id = self.user.user_id()?;
|
||||
if params.data.is_empty() {
|
||||
let view_data = processor.create_default_view(&user_id, ¶ms.view_id).await?;
|
||||
params.data = view_data.to_vec();
|
||||
} else {
|
||||
let delta_data = processor
|
||||
.process_view_delta_data(&user_id, ¶ms.view_id, params.data.clone())
|
||||
.create_view_from_delta_data(&user_id, ¶ms.view_id, params.data.clone())
|
||||
.await?;
|
||||
let _ = self
|
||||
.create_view(¶ms.view_id, params.data_type.clone(), delta_data)
|
||||
.await?;
|
||||
};
|
||||
|
||||
let view = self.create_view_on_server(params).await?;
|
||||
let _ = self.create_view_on_local(view.clone()).await?;
|
||||
Ok(view)
|
||||
let view_rev = self.create_view_on_server(params).await?;
|
||||
let _ = self.create_view_on_local(view_rev.clone()).await?;
|
||||
Ok(view_rev)
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip(self, view_id, delta_data), err)]
|
||||
@ -83,17 +88,17 @@ impl ViewController {
|
||||
return Err(FlowyError::internal().context("The content of the view should not be empty"));
|
||||
}
|
||||
let user_id = self.user.user_id()?;
|
||||
let processor = self.get_data_processor(&data_type)?;
|
||||
let processor = self.get_data_processor(data_type)?;
|
||||
let _ = processor.create_container(&user_id, view_id, delta_data).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) async fn create_view_on_local(&self, view: View) -> Result<(), FlowyError> {
|
||||
pub(crate) async fn create_view_on_local(&self, view_rev: ViewRevision) -> Result<(), FlowyError> {
|
||||
let trash_controller = self.trash_controller.clone();
|
||||
self.persistence
|
||||
.begin_transaction(|transaction| {
|
||||
let belong_to_id = view.belong_to_id.clone();
|
||||
let _ = transaction.create_view(view)?;
|
||||
let belong_to_id = view_rev.belong_to_id.clone();
|
||||
let _ = transaction.create_view(view_rev)?;
|
||||
let _ = notify_views_changed(&belong_to_id, trash_controller, &transaction)?;
|
||||
Ok(())
|
||||
})
|
||||
@ -101,8 +106,8 @@ impl ViewController {
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip(self, view_id), fields(view_id = %view_id.value), err)]
|
||||
pub(crate) async fn read_view(&self, view_id: ViewId) -> Result<View, FlowyError> {
|
||||
let view = self
|
||||
pub(crate) async fn read_view(&self, view_id: ViewIdPB) -> Result<ViewRevision, FlowyError> {
|
||||
let view_rev = self
|
||||
.persistence
|
||||
.begin_transaction(|transaction| {
|
||||
let view = transaction.read_view(&view_id.value)?;
|
||||
@ -114,10 +119,39 @@ impl ViewController {
|
||||
})
|
||||
.await?;
|
||||
let _ = self.read_view_on_server(view_id);
|
||||
Ok(view)
|
||||
Ok(view_rev)
|
||||
}
|
||||
|
||||
pub(crate) async fn read_local_views(&self, ids: Vec<String>) -> Result<Vec<View>, FlowyError> {
|
||||
#[tracing::instrument(level = "debug", skip(self, view_id), fields(view_id = %view_id.value), err)]
|
||||
pub(crate) async fn read_view_info(&self, view_id: ViewIdPB) -> Result<ViewInfoPB, FlowyError> {
|
||||
let view_info = self
|
||||
.persistence
|
||||
.begin_transaction(|transaction| {
|
||||
let view_rev = transaction.read_view(&view_id.value)?;
|
||||
|
||||
let items: Vec<ViewPB> = view_rev
|
||||
.belongings
|
||||
.into_iter()
|
||||
.map(|view_rev| view_rev.into())
|
||||
.collect();
|
||||
|
||||
let view_info = ViewInfoPB {
|
||||
id: view_rev.id,
|
||||
belong_to_id: view_rev.belong_to_id,
|
||||
name: view_rev.name,
|
||||
desc: view_rev.desc,
|
||||
data_type: view_rev.data_type.into(),
|
||||
belongings: RepeatedViewPB { items },
|
||||
ext_data: view_rev.ext_data,
|
||||
};
|
||||
Ok(view_info)
|
||||
})
|
||||
.await?;
|
||||
|
||||
Ok(view_info)
|
||||
}
|
||||
|
||||
pub(crate) async fn read_local_views(&self, ids: Vec<String>) -> Result<Vec<ViewRevision>, FlowyError> {
|
||||
self.persistence
|
||||
.begin_transaction(|transaction| {
|
||||
let mut views = vec![];
|
||||
@ -143,7 +177,7 @@ impl ViewController {
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip(self,params), fields(doc_id = %params.value), err)]
|
||||
pub(crate) async fn delete_view(&self, params: TextBlockId) -> Result<(), FlowyError> {
|
||||
pub(crate) async fn delete_view(&self, params: TextBlockIdPB) -> Result<(), FlowyError> {
|
||||
if let Some(view_id) = KV::get_str(LATEST_VIEW_ID) {
|
||||
if view_id == params.value {
|
||||
let _ = KV::remove(LATEST_VIEW_ID);
|
||||
@ -170,22 +204,22 @@ impl ViewController {
|
||||
|
||||
#[tracing::instrument(level = "debug", skip(self), err)]
|
||||
pub(crate) async fn duplicate_view(&self, view_id: &str) -> Result<(), FlowyError> {
|
||||
let view = self
|
||||
let view_rev = self
|
||||
.persistence
|
||||
.begin_transaction(|transaction| transaction.read_view(view_id))
|
||||
.await?;
|
||||
|
||||
let processor = self.get_data_processor(&view.data_type)?;
|
||||
let delta_bytes = processor.view_delta_data(view_id).await?;
|
||||
let processor = self.get_data_processor(view_rev.data_type.clone())?;
|
||||
let delta_bytes = processor.get_delta_data(view_id).await?;
|
||||
let duplicate_params = CreateViewParams {
|
||||
belong_to_id: view.belong_to_id.clone(),
|
||||
name: format!("{} (copy)", &view.name),
|
||||
desc: view.desc,
|
||||
thumbnail: view.thumbnail,
|
||||
data_type: view.data_type,
|
||||
belong_to_id: view_rev.belong_to_id.clone(),
|
||||
name: format!("{} (copy)", &view_rev.name),
|
||||
desc: view_rev.desc,
|
||||
thumbnail: view_rev.thumbnail,
|
||||
data_type: view_rev.data_type.into(),
|
||||
data: delta_bytes.to_vec(),
|
||||
view_id: gen_view_id(),
|
||||
plugin_type: view.plugin_type,
|
||||
plugin_type: view_rev.plugin_type,
|
||||
};
|
||||
|
||||
let _ = self.create_view_from_params(duplicate_params).await?;
|
||||
@ -194,7 +228,7 @@ impl ViewController {
|
||||
|
||||
// belong_to_id will be the app_id or view_id.
|
||||
#[tracing::instrument(level = "trace", skip(self), err)]
|
||||
pub(crate) async fn read_views_belong_to(&self, belong_to_id: &str) -> Result<RepeatedView, FlowyError> {
|
||||
pub(crate) async fn read_views_belong_to(&self, belong_to_id: &str) -> Result<Vec<ViewRevision>, FlowyError> {
|
||||
self.persistence
|
||||
.begin_transaction(|transaction| {
|
||||
read_belonging_views_on_local(belong_to_id, self.trash_controller.clone(), &transaction)
|
||||
@ -203,35 +237,36 @@ impl ViewController {
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip(self, params), err)]
|
||||
pub(crate) async fn update_view(&self, params: UpdateViewParams) -> Result<View, FlowyError> {
|
||||
pub(crate) async fn update_view(&self, params: UpdateViewParams) -> Result<ViewRevision, FlowyError> {
|
||||
let changeset = ViewChangeset::new(params.clone());
|
||||
let view_id = changeset.id.clone();
|
||||
let view = self
|
||||
let view_rev = self
|
||||
.persistence
|
||||
.begin_transaction(|transaction| {
|
||||
let _ = transaction.update_view(changeset)?;
|
||||
let view = transaction.read_view(&view_id)?;
|
||||
let view_rev = transaction.read_view(&view_id)?;
|
||||
let view: ViewPB = view_rev.clone().into();
|
||||
send_dart_notification(&view_id, FolderNotification::ViewUpdated)
|
||||
.payload(view.clone())
|
||||
.payload(view)
|
||||
.send();
|
||||
let _ = notify_views_changed(&view.belong_to_id, self.trash_controller.clone(), &transaction)?;
|
||||
Ok(view)
|
||||
let _ = notify_views_changed(&view_rev.belong_to_id, self.trash_controller.clone(), &transaction)?;
|
||||
Ok(view_rev)
|
||||
})
|
||||
.await?;
|
||||
|
||||
let _ = self.update_view_on_server(params);
|
||||
Ok(view)
|
||||
Ok(view_rev)
|
||||
}
|
||||
|
||||
pub(crate) async fn latest_visit_view(&self) -> FlowyResult<Option<View>> {
|
||||
pub(crate) async fn latest_visit_view(&self) -> FlowyResult<Option<ViewRevision>> {
|
||||
match KV::get_str(LATEST_VIEW_ID) {
|
||||
None => Ok(None),
|
||||
Some(view_id) => {
|
||||
let view = self
|
||||
let view_rev = self
|
||||
.persistence
|
||||
.begin_transaction(|transaction| transaction.read_view(&view_id))
|
||||
.await?;
|
||||
Ok(Some(view))
|
||||
Ok(Some(view_rev))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -239,10 +274,10 @@ impl ViewController {
|
||||
|
||||
impl ViewController {
|
||||
#[tracing::instrument(level = "debug", skip(self, params), err)]
|
||||
async fn create_view_on_server(&self, params: CreateViewParams) -> Result<View, FlowyError> {
|
||||
async fn create_view_on_server(&self, params: CreateViewParams) -> Result<ViewRevision, FlowyError> {
|
||||
let token = self.user.token()?;
|
||||
let view = self.cloud_service.create_view(&token, params).await?;
|
||||
Ok(view)
|
||||
let view_rev = self.cloud_service.create_view(&token, params).await?;
|
||||
Ok(view_rev)
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip(self), err)]
|
||||
@ -262,21 +297,22 @@ impl ViewController {
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip(self), err)]
|
||||
fn read_view_on_server(&self, params: ViewId) -> Result<(), FlowyError> {
|
||||
fn read_view_on_server(&self, params: ViewIdPB) -> Result<(), FlowyError> {
|
||||
let token = self.user.token()?;
|
||||
let server = self.cloud_service.clone();
|
||||
let persistence = self.persistence.clone();
|
||||
// TODO: Retry with RetryAction?
|
||||
tokio::spawn(async move {
|
||||
match server.read_view(&token, params).await {
|
||||
Ok(Some(view)) => {
|
||||
Ok(Some(view_rev)) => {
|
||||
match persistence
|
||||
.begin_transaction(|transaction| transaction.create_view(view.clone()))
|
||||
.begin_transaction(|transaction| transaction.create_view(view_rev.clone()))
|
||||
.await
|
||||
{
|
||||
Ok(_) => {
|
||||
let view: ViewPB = view_rev.into();
|
||||
send_dart_notification(&view.id, FolderNotification::ViewUpdated)
|
||||
.payload(view.clone())
|
||||
.payload(view)
|
||||
.send();
|
||||
}
|
||||
Err(e) => log::error!("Save view failed: {:?}", e),
|
||||
@ -324,12 +360,16 @@ impl ViewController {
|
||||
.persistence
|
||||
.begin_transaction(|transaction| transaction.read_view(view_id))
|
||||
.await?;
|
||||
self.get_data_processor(&view.data_type)
|
||||
self.get_data_processor(view.data_type)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn get_data_processor(&self, data_type: &ViewDataType) -> FlowyResult<Arc<dyn ViewDataProcessor + Send + Sync>> {
|
||||
match self.data_processors.get(data_type) {
|
||||
fn get_data_processor<T: Into<ViewDataType>>(
|
||||
&self,
|
||||
data_type: T,
|
||||
) -> FlowyResult<Arc<dyn ViewDataProcessor + Send + Sync>> {
|
||||
let data_type = data_type.into();
|
||||
match self.data_processors.get(&data_type) {
|
||||
None => Err(FlowyError::internal().context(format!(
|
||||
"Get data processor failed. Unknown view data type: {:?}",
|
||||
data_type
|
||||
@ -350,10 +390,10 @@ async fn handle_trash_event(
|
||||
TrashEvent::NewTrash(identifiers, ret) => {
|
||||
let result = persistence
|
||||
.begin_transaction(|transaction| {
|
||||
let views = read_local_views_with_transaction(identifiers, &transaction)?;
|
||||
for view in views {
|
||||
let _ = notify_views_changed(&view.belong_to_id, trash_can.clone(), &transaction)?;
|
||||
notify_dart(view, FolderNotification::ViewDeleted);
|
||||
let view_revs = read_local_views_with_transaction(identifiers, &transaction)?;
|
||||
for view_rev in view_revs {
|
||||
let _ = notify_views_changed(&view_rev.belong_to_id, trash_can.clone(), &transaction)?;
|
||||
notify_dart(view_rev.into(), FolderNotification::ViewDeleted);
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
@ -363,10 +403,10 @@ async fn handle_trash_event(
|
||||
TrashEvent::Putback(identifiers, ret) => {
|
||||
let result = persistence
|
||||
.begin_transaction(|transaction| {
|
||||
let views = read_local_views_with_transaction(identifiers, &transaction)?;
|
||||
for view in views {
|
||||
let _ = notify_views_changed(&view.belong_to_id, trash_can.clone(), &transaction)?;
|
||||
notify_dart(view, FolderNotification::ViewRestored);
|
||||
let view_revs = read_local_views_with_transaction(identifiers, &transaction)?;
|
||||
for view_rev in view_revs {
|
||||
let _ = notify_views_changed(&view_rev.belong_to_id, trash_can.clone(), &transaction)?;
|
||||
notify_dart(view_rev.into(), FolderNotification::ViewRestored);
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
@ -393,7 +433,8 @@ async fn handle_trash_event(
|
||||
.await?;
|
||||
|
||||
for view in views {
|
||||
match get_data_processor(data_processors.clone(), &view.data_type) {
|
||||
let data_type = view.data_type.clone().into();
|
||||
match get_data_processor(data_processors.clone(), &data_type) {
|
||||
Ok(processor) => {
|
||||
let _ = processor.close_container(&view.id).await?;
|
||||
}
|
||||
@ -423,18 +464,17 @@ fn get_data_processor(
|
||||
}
|
||||
|
||||
fn read_local_views_with_transaction<'a>(
|
||||
identifiers: RepeatedTrashId,
|
||||
identifiers: RepeatedTrashIdPB,
|
||||
transaction: &'a (dyn FolderPersistenceTransaction + 'a),
|
||||
) -> Result<Vec<View>, FlowyError> {
|
||||
let mut views = vec![];
|
||||
) -> Result<Vec<ViewRevision>, FlowyError> {
|
||||
let mut view_revs = vec![];
|
||||
for identifier in identifiers.items {
|
||||
let view = transaction.read_view(&identifier.id)?;
|
||||
views.push(view);
|
||||
view_revs.push(transaction.read_view(&identifier.id)?);
|
||||
}
|
||||
Ok(views)
|
||||
Ok(view_revs)
|
||||
}
|
||||
|
||||
fn notify_dart(view: View, notification: FolderNotification) {
|
||||
fn notify_dart(view: ViewPB, notification: FolderNotification) {
|
||||
send_dart_notification(&view.id, notification).payload(view).send();
|
||||
}
|
||||
|
||||
@ -449,8 +489,13 @@ fn notify_views_changed<'a>(
|
||||
trash_controller: Arc<TrashController>,
|
||||
transaction: &'a (dyn FolderPersistenceTransaction + 'a),
|
||||
) -> FlowyResult<()> {
|
||||
let repeated_view = read_belonging_views_on_local(belong_to_id, trash_controller.clone(), transaction)?;
|
||||
tracing::Span::current().record("view_count", &format!("{}", repeated_view.len()).as_str());
|
||||
let items: Vec<ViewPB> = read_belonging_views_on_local(belong_to_id, trash_controller.clone(), transaction)?
|
||||
.into_iter()
|
||||
.map(|view_rev| view_rev.into())
|
||||
.collect();
|
||||
tracing::Span::current().record("view_count", &format!("{}", items.len()).as_str());
|
||||
|
||||
let repeated_view = RepeatedViewPB { items };
|
||||
send_dart_notification(belong_to_id, FolderNotification::AppViewsChanged)
|
||||
.payload(repeated_view)
|
||||
.send();
|
||||
@ -461,10 +506,10 @@ fn read_belonging_views_on_local<'a>(
|
||||
belong_to_id: &str,
|
||||
trash_controller: Arc<TrashController>,
|
||||
transaction: &'a (dyn FolderPersistenceTransaction + 'a),
|
||||
) -> FlowyResult<RepeatedView> {
|
||||
let mut views = transaction.read_views(belong_to_id)?;
|
||||
) -> FlowyResult<Vec<ViewRevision>> {
|
||||
let mut view_revs = transaction.read_views(belong_to_id)?;
|
||||
let trash_ids = trash_controller.read_trash_ids(transaction)?;
|
||||
views.retain(|view_table| !trash_ids.contains(&view_table.id));
|
||||
view_revs.retain(|view_table| !trash_ids.contains(&view_table.id));
|
||||
|
||||
Ok(RepeatedView { items: views })
|
||||
Ok(view_revs)
|
||||
}
|
||||
|
@ -1,44 +1,52 @@
|
||||
use crate::entities::view::{MoveFolderItemParams, MoveFolderItemPayloadPB, MoveFolderItemType};
|
||||
use crate::entities::ViewInfoPB;
|
||||
use crate::manager::FolderManager;
|
||||
use crate::services::{notify_workspace_setting_did_change, AppController};
|
||||
use crate::{
|
||||
entities::{
|
||||
trash::Trash,
|
||||
trash::TrashPB,
|
||||
view::{
|
||||
CreateViewParams, CreateViewPayload, RepeatedViewId, UpdateViewParams, UpdateViewPayload, View, ViewId,
|
||||
CreateViewParams, CreateViewPayloadPB, RepeatedViewIdPB, UpdateViewParams, UpdateViewPayloadPB, ViewIdPB,
|
||||
ViewPB,
|
||||
},
|
||||
},
|
||||
errors::FlowyError,
|
||||
services::{TrashController, ViewController},
|
||||
};
|
||||
use flowy_folder_data_model::entities::view::{MoveFolderItemParams, MoveFolderItemPayload, MoveFolderItemType};
|
||||
use flowy_folder_data_model::revision::TrashRevision;
|
||||
use lib_dispatch::prelude::{data_result, AppData, Data, DataResult};
|
||||
use std::{convert::TryInto, sync::Arc};
|
||||
|
||||
pub(crate) async fn create_view_handler(
|
||||
data: Data<CreateViewPayload>,
|
||||
data: Data<CreateViewPayloadPB>,
|
||||
controller: AppData<Arc<ViewController>>,
|
||||
) -> DataResult<View, FlowyError> {
|
||||
) -> DataResult<ViewPB, FlowyError> {
|
||||
let params: CreateViewParams = data.into_inner().try_into()?;
|
||||
let view = controller.create_view_from_params(params).await?;
|
||||
data_result(view)
|
||||
let view_rev = controller.create_view_from_params(params).await?;
|
||||
data_result(view_rev.into())
|
||||
}
|
||||
|
||||
pub(crate) async fn read_view_handler(
|
||||
data: Data<ViewId>,
|
||||
data: Data<ViewIdPB>,
|
||||
controller: AppData<Arc<ViewController>>,
|
||||
) -> DataResult<View, FlowyError> {
|
||||
let view_id: ViewId = data.into_inner();
|
||||
let mut view = controller.read_view(view_id.clone()).await?;
|
||||
// For the moment, app and view can contains lots of views. Reading the view
|
||||
// belongings using the view_id.
|
||||
view.belongings = controller.read_views_belong_to(&view_id.value).await?;
|
||||
) -> DataResult<ViewPB, FlowyError> {
|
||||
let view_id: ViewIdPB = data.into_inner();
|
||||
let view_rev = controller.read_view(view_id.clone()).await?;
|
||||
data_result(view_rev.into())
|
||||
}
|
||||
|
||||
data_result(view)
|
||||
pub(crate) async fn read_view_info_handler(
|
||||
data: Data<ViewIdPB>,
|
||||
controller: AppData<Arc<ViewController>>,
|
||||
) -> DataResult<ViewInfoPB, FlowyError> {
|
||||
let view_id: ViewIdPB = data.into_inner();
|
||||
let view_info = controller.read_view_info(view_id.clone()).await?;
|
||||
data_result(view_info)
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip(data, controller), err)]
|
||||
pub(crate) async fn update_view_handler(
|
||||
data: Data<UpdateViewPayload>,
|
||||
data: Data<UpdateViewPayloadPB>,
|
||||
controller: AppData<Arc<ViewController>>,
|
||||
) -> Result<(), FlowyError> {
|
||||
let params: UpdateViewParams = data.into_inner().try_into()?;
|
||||
@ -48,11 +56,11 @@ pub(crate) async fn update_view_handler(
|
||||
}
|
||||
|
||||
pub(crate) async fn delete_view_handler(
|
||||
data: Data<RepeatedViewId>,
|
||||
data: Data<RepeatedViewIdPB>,
|
||||
view_controller: AppData<Arc<ViewController>>,
|
||||
trash_controller: AppData<Arc<TrashController>>,
|
||||
) -> Result<(), FlowyError> {
|
||||
let params: RepeatedViewId = data.into_inner();
|
||||
let params: RepeatedViewIdPB = data.into_inner();
|
||||
for view_id in ¶ms.items {
|
||||
let _ = view_controller.delete_view(view_id.into()).await;
|
||||
}
|
||||
@ -61,36 +69,39 @@ pub(crate) async fn delete_view_handler(
|
||||
.read_local_views(params.items)
|
||||
.await?
|
||||
.into_iter()
|
||||
.map(|view| view.into())
|
||||
.collect::<Vec<Trash>>();
|
||||
.map(|view| {
|
||||
let trash_rev: TrashRevision = view.into();
|
||||
trash_rev.into()
|
||||
})
|
||||
.collect::<Vec<TrashPB>>();
|
||||
|
||||
let _ = trash_controller.add(trash).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) async fn set_latest_view_handler(
|
||||
data: Data<ViewId>,
|
||||
data: Data<ViewIdPB>,
|
||||
folder: AppData<Arc<FolderManager>>,
|
||||
controller: AppData<Arc<ViewController>>,
|
||||
) -> Result<(), FlowyError> {
|
||||
let view_id: ViewId = data.into_inner();
|
||||
let view_id: ViewIdPB = data.into_inner();
|
||||
let _ = controller.set_latest_view(&view_id.value)?;
|
||||
let _ = notify_workspace_setting_did_change(&folder, &view_id).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) async fn close_view_handler(
|
||||
data: Data<ViewId>,
|
||||
data: Data<ViewIdPB>,
|
||||
controller: AppData<Arc<ViewController>>,
|
||||
) -> Result<(), FlowyError> {
|
||||
let view_id: ViewId = data.into_inner();
|
||||
let view_id: ViewIdPB = data.into_inner();
|
||||
let _ = controller.close_view(&view_id.value).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip_all, err)]
|
||||
pub(crate) async fn move_item_handler(
|
||||
data: Data<MoveFolderItemPayload>,
|
||||
data: Data<MoveFolderItemPayloadPB>,
|
||||
view_controller: AppData<Arc<ViewController>>,
|
||||
app_controller: AppData<Arc<AppController>>,
|
||||
) -> Result<(), FlowyError> {
|
||||
@ -110,10 +121,10 @@ pub(crate) async fn move_item_handler(
|
||||
|
||||
#[tracing::instrument(level = "debug", skip(data, controller), err)]
|
||||
pub(crate) async fn duplicate_view_handler(
|
||||
data: Data<ViewId>,
|
||||
data: Data<ViewIdPB>,
|
||||
controller: AppData<Arc<ViewController>>,
|
||||
) -> Result<(), FlowyError> {
|
||||
let view_id: ViewId = data.into_inner();
|
||||
let view_id: ViewIdPB = data.into_inner();
|
||||
let _ = controller.duplicate_view(&view_id.value).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
use crate::entities::workspace::*;
|
||||
use crate::manager::FolderManager;
|
||||
use crate::{
|
||||
dart_notification::*,
|
||||
@ -9,7 +10,7 @@ use crate::{
|
||||
},
|
||||
};
|
||||
use flowy_database::kv::KV;
|
||||
use flowy_folder_data_model::entities::{app::RepeatedApp, workspace::*};
|
||||
use flowy_folder_data_model::revision::{AppRevision, WorkspaceRevision};
|
||||
use std::sync::Arc;
|
||||
|
||||
pub struct WorkspaceController {
|
||||
@ -37,7 +38,7 @@ impl WorkspaceController {
|
||||
pub(crate) async fn create_workspace_from_params(
|
||||
&self,
|
||||
params: CreateWorkspaceParams,
|
||||
) -> Result<Workspace, FlowyError> {
|
||||
) -> Result<WorkspaceRevision, FlowyError> {
|
||||
let workspace = self.create_workspace_on_server(params.clone()).await?;
|
||||
let user_id = self.user.user_id()?;
|
||||
let token = self.user.token()?;
|
||||
@ -47,8 +48,11 @@ impl WorkspaceController {
|
||||
let _ = transaction.create_workspace(&user_id, workspace.clone())?;
|
||||
transaction.read_workspaces(&user_id, None)
|
||||
})
|
||||
.await?;
|
||||
let repeated_workspace = RepeatedWorkspace { items: workspaces };
|
||||
.await?
|
||||
.into_iter()
|
||||
.map(|workspace_rev| workspace_rev.into())
|
||||
.collect();
|
||||
let repeated_workspace = RepeatedWorkspacePB { items: workspaces };
|
||||
send_dart_notification(&token, FolderNotification::UserCreateWorkspace)
|
||||
.payload(repeated_workspace)
|
||||
.send();
|
||||
@ -95,7 +99,7 @@ impl WorkspaceController {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) async fn open_workspace(&self, params: WorkspaceId) -> Result<Workspace, FlowyError> {
|
||||
pub(crate) async fn open_workspace(&self, params: WorkspaceIdPB) -> Result<WorkspacePB, FlowyError> {
|
||||
let user_id = self.user.user_id()?;
|
||||
if let Some(workspace_id) = params.value {
|
||||
let workspace = self
|
||||
@ -109,16 +113,16 @@ impl WorkspaceController {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn read_current_workspace_apps(&self) -> Result<RepeatedApp, FlowyError> {
|
||||
pub(crate) async fn read_current_workspace_apps(&self) -> Result<Vec<AppRevision>, FlowyError> {
|
||||
let workspace_id = get_current_workspace()?;
|
||||
let repeated_app = self
|
||||
let app_revs = self
|
||||
.persistence
|
||||
.begin_transaction(|transaction| {
|
||||
read_local_workspace_apps(&workspace_id, self.trash_controller.clone(), &transaction)
|
||||
})
|
||||
.await?;
|
||||
// TODO: read from server
|
||||
Ok(repeated_app)
|
||||
Ok(app_revs)
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip(self, transaction), err)]
|
||||
@ -127,10 +131,14 @@ impl WorkspaceController {
|
||||
workspace_id: Option<String>,
|
||||
user_id: &str,
|
||||
transaction: &'a (dyn FolderPersistenceTransaction + 'a),
|
||||
) -> Result<RepeatedWorkspace, FlowyError> {
|
||||
) -> Result<RepeatedWorkspacePB, FlowyError> {
|
||||
let workspace_id = workspace_id.to_owned();
|
||||
let workspaces = transaction.read_workspaces(user_id, workspace_id)?;
|
||||
Ok(RepeatedWorkspace { items: workspaces })
|
||||
let workspaces = transaction
|
||||
.read_workspaces(user_id, workspace_id)?
|
||||
.into_iter()
|
||||
.map(|workspace_rev| workspace_rev.into())
|
||||
.collect();
|
||||
Ok(RepeatedWorkspacePB { items: workspaces })
|
||||
}
|
||||
|
||||
pub(crate) fn read_local_workspace<'a>(
|
||||
@ -138,23 +146,27 @@ impl WorkspaceController {
|
||||
workspace_id: String,
|
||||
user_id: &str,
|
||||
transaction: &'a (dyn FolderPersistenceTransaction + 'a),
|
||||
) -> Result<Workspace, FlowyError> {
|
||||
let mut workspaces = transaction.read_workspaces(user_id, Some(workspace_id.clone()))?;
|
||||
if workspaces.is_empty() {
|
||||
) -> Result<WorkspacePB, FlowyError> {
|
||||
let mut workspace_revs = transaction.read_workspaces(user_id, Some(workspace_id.clone()))?;
|
||||
if workspace_revs.is_empty() {
|
||||
return Err(FlowyError::record_not_found().context(format!("{} workspace not found", workspace_id)));
|
||||
}
|
||||
debug_assert_eq!(workspaces.len(), 1);
|
||||
let workspace = workspaces.drain(..1).collect::<Vec<Workspace>>().pop().unwrap();
|
||||
debug_assert_eq!(workspace_revs.len(), 1);
|
||||
let workspace = workspace_revs
|
||||
.drain(..1)
|
||||
.map(|workspace_rev| workspace_rev.into())
|
||||
.collect::<Vec<WorkspacePB>>()
|
||||
.pop()
|
||||
.unwrap();
|
||||
Ok(workspace)
|
||||
}
|
||||
}
|
||||
|
||||
impl WorkspaceController {
|
||||
#[tracing::instrument(level = "trace", skip(self), err)]
|
||||
async fn create_workspace_on_server(&self, params: CreateWorkspaceParams) -> Result<Workspace, FlowyError> {
|
||||
async fn create_workspace_on_server(&self, params: CreateWorkspaceParams) -> Result<WorkspaceRevision, FlowyError> {
|
||||
let token = self.user.token()?;
|
||||
let workspace = self.cloud_service.create_workspace(&token, params).await?;
|
||||
Ok(workspace)
|
||||
self.cloud_service.create_workspace(&token, params).await
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "trace", skip(self), err)]
|
||||
@ -174,7 +186,7 @@ impl WorkspaceController {
|
||||
|
||||
#[tracing::instrument(level = "trace", skip(self), err)]
|
||||
fn delete_workspace_on_server(&self, workspace_id: &str) -> Result<(), FlowyError> {
|
||||
let params = WorkspaceId {
|
||||
let params = WorkspaceIdPB {
|
||||
value: Some(workspace_id.to_string()),
|
||||
};
|
||||
let (token, server) = (self.user.token()?, self.cloud_service.clone());
|
||||
@ -209,11 +221,11 @@ pub async fn notify_workspace_setting_did_change(
|
||||
)?;
|
||||
|
||||
let setting = match transaction.read_view(view_id) {
|
||||
Ok(latest_view) => CurrentWorkspaceSetting {
|
||||
Ok(latest_view) => CurrentWorkspaceSettingPB {
|
||||
workspace,
|
||||
latest_view: Some(latest_view),
|
||||
latest_view: Some(latest_view.into()),
|
||||
},
|
||||
Err(_) => CurrentWorkspaceSetting {
|
||||
Err(_) => CurrentWorkspaceSettingPB {
|
||||
workspace,
|
||||
latest_view: None,
|
||||
},
|
||||
|
@ -1,53 +1,58 @@
|
||||
use crate::entities::{
|
||||
app::RepeatedAppPB,
|
||||
view::ViewPB,
|
||||
workspace::{CurrentWorkspaceSettingPB, RepeatedWorkspacePB, WorkspaceIdPB, *},
|
||||
};
|
||||
use crate::{
|
||||
dart_notification::{send_dart_notification, FolderNotification},
|
||||
errors::FlowyError,
|
||||
manager::FolderManager,
|
||||
services::{get_current_workspace, read_local_workspace_apps, WorkspaceController},
|
||||
};
|
||||
use flowy_folder_data_model::entities::{
|
||||
app::RepeatedApp,
|
||||
view::View,
|
||||
workspace::{CurrentWorkspaceSetting, RepeatedWorkspace, WorkspaceId, *},
|
||||
};
|
||||
|
||||
use lib_dispatch::prelude::{data_result, AppData, Data, DataResult};
|
||||
use std::{convert::TryInto, sync::Arc};
|
||||
|
||||
#[tracing::instrument(level = "debug", skip(data, controller), err)]
|
||||
pub(crate) async fn create_workspace_handler(
|
||||
data: Data<CreateWorkspacePayload>,
|
||||
data: Data<CreateWorkspacePayloadPB>,
|
||||
controller: AppData<Arc<WorkspaceController>>,
|
||||
) -> DataResult<Workspace, FlowyError> {
|
||||
) -> DataResult<WorkspacePB, FlowyError> {
|
||||
let controller = controller.get_ref().clone();
|
||||
let params: CreateWorkspaceParams = data.into_inner().try_into()?;
|
||||
let detail = controller.create_workspace_from_params(params).await?;
|
||||
data_result(detail)
|
||||
let workspace_rev = controller.create_workspace_from_params(params).await?;
|
||||
data_result(workspace_rev.into())
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip(controller), err)]
|
||||
pub(crate) async fn read_workspace_apps_handler(
|
||||
controller: AppData<Arc<WorkspaceController>>,
|
||||
) -> DataResult<RepeatedApp, FlowyError> {
|
||||
let repeated_app = controller.read_current_workspace_apps().await?;
|
||||
) -> DataResult<RepeatedAppPB, FlowyError> {
|
||||
let items = controller
|
||||
.read_current_workspace_apps()
|
||||
.await?
|
||||
.into_iter()
|
||||
.map(|app_rev| app_rev.into())
|
||||
.collect();
|
||||
let repeated_app = RepeatedAppPB { items };
|
||||
data_result(repeated_app)
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip(data, controller), err)]
|
||||
pub(crate) async fn open_workspace_handler(
|
||||
data: Data<WorkspaceId>,
|
||||
data: Data<WorkspaceIdPB>,
|
||||
controller: AppData<Arc<WorkspaceController>>,
|
||||
) -> DataResult<Workspace, FlowyError> {
|
||||
let params: WorkspaceId = data.into_inner();
|
||||
) -> DataResult<WorkspacePB, FlowyError> {
|
||||
let params: WorkspaceIdPB = data.into_inner();
|
||||
let workspaces = controller.open_workspace(params).await?;
|
||||
data_result(workspaces)
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip(data, folder), err)]
|
||||
pub(crate) async fn read_workspaces_handler(
|
||||
data: Data<WorkspaceId>,
|
||||
data: Data<WorkspaceIdPB>,
|
||||
folder: AppData<Arc<FolderManager>>,
|
||||
) -> DataResult<RepeatedWorkspace, FlowyError> {
|
||||
let params: WorkspaceId = data.into_inner();
|
||||
) -> DataResult<RepeatedWorkspacePB, FlowyError> {
|
||||
let params: WorkspaceIdPB = data.into_inner();
|
||||
let user_id = folder.user.user_id()?;
|
||||
let workspace_controller = folder.workspace_controller.clone();
|
||||
|
||||
@ -58,8 +63,10 @@ pub(crate) async fn read_workspaces_handler(
|
||||
let mut workspaces =
|
||||
workspace_controller.read_local_workspaces(params.value.clone(), &user_id, &transaction)?;
|
||||
for workspace in workspaces.iter_mut() {
|
||||
let apps =
|
||||
read_local_workspace_apps(&workspace.id, trash_controller.clone(), &transaction)?.into_inner();
|
||||
let apps = read_local_workspace_apps(&workspace.id, trash_controller.clone(), &transaction)?
|
||||
.into_iter()
|
||||
.map(|app_rev| app_rev.into())
|
||||
.collect();
|
||||
workspace.apps.items = apps;
|
||||
}
|
||||
Ok(workspaces)
|
||||
@ -72,10 +79,10 @@ pub(crate) async fn read_workspaces_handler(
|
||||
#[tracing::instrument(level = "debug", skip(folder), err)]
|
||||
pub async fn read_cur_workspace_handler(
|
||||
folder: AppData<Arc<FolderManager>>,
|
||||
) -> DataResult<CurrentWorkspaceSetting, FlowyError> {
|
||||
) -> DataResult<CurrentWorkspaceSettingPB, FlowyError> {
|
||||
let workspace_id = get_current_workspace()?;
|
||||
let user_id = folder.user.user_id()?;
|
||||
let params = WorkspaceId {
|
||||
let params = WorkspaceIdPB {
|
||||
value: Some(workspace_id.clone()),
|
||||
};
|
||||
|
||||
@ -88,8 +95,13 @@ pub async fn read_cur_workspace_handler(
|
||||
})
|
||||
.await?;
|
||||
|
||||
let latest_view: Option<View> = folder.view_controller.latest_visit_view().await.unwrap_or(None);
|
||||
let setting = CurrentWorkspaceSetting { workspace, latest_view };
|
||||
let latest_view: Option<ViewPB> = folder
|
||||
.view_controller
|
||||
.latest_visit_view()
|
||||
.await
|
||||
.unwrap_or(None)
|
||||
.map(|view_rev| view_rev.into());
|
||||
let setting = CurrentWorkspaceSettingPB { workspace, latest_view };
|
||||
let _ = read_workspaces_on_server(folder, user_id, params);
|
||||
data_result(setting)
|
||||
}
|
||||
@ -98,31 +110,31 @@ pub async fn read_cur_workspace_handler(
|
||||
fn read_workspaces_on_server(
|
||||
folder_manager: AppData<Arc<FolderManager>>,
|
||||
user_id: String,
|
||||
params: WorkspaceId,
|
||||
params: WorkspaceIdPB,
|
||||
) -> Result<(), FlowyError> {
|
||||
let (token, server) = (folder_manager.user.token()?, folder_manager.cloud_service.clone());
|
||||
let persistence = folder_manager.persistence.clone();
|
||||
|
||||
tokio::spawn(async move {
|
||||
let workspaces = server.read_workspace(&token, params).await?;
|
||||
let workspace_revs = server.read_workspace(&token, params).await?;
|
||||
let _ = persistence
|
||||
.begin_transaction(|transaction| {
|
||||
tracing::trace!("Save {} workspace", workspaces.len());
|
||||
for workspace in &workspaces.items {
|
||||
let m_workspace = workspace.clone();
|
||||
let apps = m_workspace.apps.clone().into_inner();
|
||||
tracing::trace!("Save {} workspace", workspace_revs.len());
|
||||
for workspace_rev in &workspace_revs {
|
||||
let m_workspace = workspace_rev.clone();
|
||||
let app_revs = m_workspace.apps.clone();
|
||||
let _ = transaction.create_workspace(&user_id, m_workspace)?;
|
||||
tracing::trace!("Save {} apps", apps.len());
|
||||
for app in apps {
|
||||
let views = app.belongings.clone().into_inner();
|
||||
match transaction.create_app(app) {
|
||||
tracing::trace!("Save {} apps", app_revs.len());
|
||||
for app_rev in app_revs {
|
||||
let view_revs = app_rev.belongings.clone();
|
||||
match transaction.create_app(app_rev) {
|
||||
Ok(_) => {}
|
||||
Err(e) => log::error!("create app failed: {:?}", e),
|
||||
}
|
||||
|
||||
tracing::trace!("Save {} views", views.len());
|
||||
for view in views {
|
||||
match transaction.create_view(view) {
|
||||
tracing::trace!("Save {} views", view_revs.len());
|
||||
for view_rev in view_revs {
|
||||
match transaction.create_view(view_rev) {
|
||||
Ok(_) => {}
|
||||
Err(e) => log::error!("create view failed: {:?}", e),
|
||||
}
|
||||
@ -133,8 +145,15 @@ fn read_workspaces_on_server(
|
||||
})
|
||||
.await?;
|
||||
|
||||
let repeated_workspace = RepeatedWorkspacePB {
|
||||
items: workspace_revs
|
||||
.into_iter()
|
||||
.map(|workspace_rev| workspace_rev.into())
|
||||
.collect(),
|
||||
};
|
||||
|
||||
send_dart_notification(&token, FolderNotification::WorkspaceListUpdated)
|
||||
.payload(workspaces)
|
||||
.payload(repeated_workspace)
|
||||
.send();
|
||||
Result::<(), FlowyError>::Ok(())
|
||||
});
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::script::{invalid_workspace_name_test_case, FolderScript::*, FolderTest};
|
||||
use flowy_folder::entities::view::ViewDataType;
|
||||
use flowy_folder::entities::workspace::CreateWorkspacePayloadPB;
|
||||
|
||||
use flowy_folder::entities::workspace::CreateWorkspacePayload;
|
||||
use flowy_folder_data_model::entities::view::ViewDataType;
|
||||
use flowy_revision::disk::RevisionState;
|
||||
use flowy_test::{event_builder::*, FlowySDKTest};
|
||||
|
||||
@ -38,11 +38,9 @@ async fn workspace_create() {
|
||||
async fn workspace_read() {
|
||||
let mut test = FolderTest::new().await;
|
||||
let workspace = test.workspace.clone();
|
||||
let json = serde_json::to_string(&workspace).unwrap();
|
||||
|
||||
test.run_scripts(vec![
|
||||
ReadWorkspace(Some(workspace.id.clone())),
|
||||
AssertWorkspaceJson(json),
|
||||
AssertWorkspace(workspace),
|
||||
])
|
||||
.await;
|
||||
@ -58,15 +56,14 @@ async fn workspace_create_with_apps() {
|
||||
.await;
|
||||
|
||||
let app = test.app.clone();
|
||||
let json = serde_json::to_string(&app).unwrap();
|
||||
test.run_scripts(vec![ReadApp(app.id), AssertAppJson(json)]).await;
|
||||
test.run_scripts(vec![ReadApp(app.id)]).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn workspace_create_with_invalid_name() {
|
||||
for (name, code) in invalid_workspace_name_test_case() {
|
||||
let sdk = FlowySDKTest::default();
|
||||
let request = CreateWorkspacePayload {
|
||||
let request = CreateWorkspacePayloadPB {
|
||||
name,
|
||||
desc: "".to_owned(),
|
||||
};
|
||||
@ -343,7 +340,6 @@ async fn folder_sync_revision_with_new_view() {
|
||||
|
||||
let view = test.view.clone();
|
||||
assert_eq!(view.name, view_name);
|
||||
assert_eq!(view.desc, view_desc);
|
||||
test.run_scripts(vec![ReadView(view.id.clone()), AssertView(view)])
|
||||
.await;
|
||||
}
|
||||
|
@ -1,22 +1,23 @@
|
||||
use flowy_folder::entities::view::{RepeatedViewIdPB, ViewIdPB};
|
||||
use flowy_folder::entities::workspace::WorkspaceIdPB;
|
||||
use flowy_folder::entities::{
|
||||
app::{AppIdPB, CreateAppPayloadPB, UpdateAppPayloadPB},
|
||||
trash::{RepeatedTrashPB, TrashIdPB, TrashType},
|
||||
view::{CreateViewPayloadPB, UpdateViewPayloadPB},
|
||||
workspace::{CreateWorkspacePayloadPB, RepeatedWorkspacePB},
|
||||
};
|
||||
use flowy_folder::entities::{
|
||||
app::{AppPB, RepeatedAppPB},
|
||||
trash::TrashPB,
|
||||
view::{RepeatedViewPB, ViewDataType, ViewPB},
|
||||
workspace::WorkspacePB,
|
||||
};
|
||||
use flowy_folder::event_map::FolderEvent::*;
|
||||
use flowy_folder::{errors::ErrorCode, services::folder_editor::FolderEditor};
|
||||
use flowy_folder_data_model::entities::view::{RepeatedViewId, ViewId};
|
||||
use flowy_folder_data_model::entities::workspace::WorkspaceId;
|
||||
use flowy_folder_data_model::entities::{
|
||||
app::{App, RepeatedApp},
|
||||
trash::Trash,
|
||||
view::{RepeatedView, View, ViewDataType},
|
||||
workspace::Workspace,
|
||||
};
|
||||
use flowy_folder_data_model::entities::{
|
||||
app::{AppId, CreateAppPayload, UpdateAppPayload},
|
||||
trash::{RepeatedTrash, TrashId, TrashType},
|
||||
view::{CreateViewPayload, UpdateViewPayload},
|
||||
workspace::{CreateWorkspacePayload, RepeatedWorkspace},
|
||||
};
|
||||
|
||||
use flowy_revision::disk::RevisionState;
|
||||
use flowy_revision::REVISION_WRITE_INTERVAL_IN_MILLIS;
|
||||
use flowy_sync::entities::text_block_info::TextBlockInfo;
|
||||
use flowy_sync::entities::text_block::DocumentPB;
|
||||
use flowy_test::{event_builder::*, FlowySDKTest};
|
||||
use std::{sync::Arc, time::Duration};
|
||||
use tokio::time::sleep;
|
||||
@ -28,8 +29,8 @@ pub enum FolderScript {
|
||||
name: String,
|
||||
desc: String,
|
||||
},
|
||||
AssertWorkspaceJson(String),
|
||||
AssertWorkspace(Workspace),
|
||||
// AssertWorkspaceRevisionJson(String),
|
||||
AssertWorkspace(WorkspacePB),
|
||||
ReadWorkspace(Option<String>),
|
||||
|
||||
// App
|
||||
@ -37,8 +38,8 @@ pub enum FolderScript {
|
||||
name: String,
|
||||
desc: String,
|
||||
},
|
||||
AssertAppJson(String),
|
||||
AssertApp(App),
|
||||
// AssertAppRevisionJson(String),
|
||||
AssertApp(AppPB),
|
||||
ReadApp(String),
|
||||
UpdateApp {
|
||||
name: Option<String>,
|
||||
@ -52,7 +53,7 @@ pub enum FolderScript {
|
||||
desc: String,
|
||||
data_type: ViewDataType,
|
||||
},
|
||||
AssertView(View),
|
||||
AssertView(ViewPB),
|
||||
ReadView(String),
|
||||
UpdateView {
|
||||
name: Option<String>,
|
||||
@ -78,11 +79,11 @@ pub enum FolderScript {
|
||||
|
||||
pub struct FolderTest {
|
||||
pub sdk: FlowySDKTest,
|
||||
pub all_workspace: Vec<Workspace>,
|
||||
pub workspace: Workspace,
|
||||
pub app: App,
|
||||
pub view: View,
|
||||
pub trash: Vec<Trash>,
|
||||
pub all_workspace: Vec<WorkspacePB>,
|
||||
pub workspace: WorkspacePB,
|
||||
pub app: AppPB,
|
||||
pub view: ViewPB,
|
||||
pub trash: Vec<TrashPB>,
|
||||
// pub folder_editor:
|
||||
}
|
||||
|
||||
@ -100,11 +101,11 @@ impl FolderTest {
|
||||
ViewDataType::TextBlock,
|
||||
)
|
||||
.await;
|
||||
app.belongings = RepeatedView {
|
||||
app.belongings = RepeatedViewPB {
|
||||
items: vec![view.clone()],
|
||||
};
|
||||
|
||||
workspace.apps = RepeatedApp {
|
||||
workspace.apps = RepeatedAppPB {
|
||||
items: vec![app.clone()],
|
||||
};
|
||||
Self {
|
||||
@ -138,14 +139,15 @@ impl FolderTest {
|
||||
let workspace = create_workspace(sdk, &name, &desc).await;
|
||||
self.workspace = workspace;
|
||||
}
|
||||
FolderScript::AssertWorkspaceJson(expected_json) => {
|
||||
let workspace = read_workspace(sdk, Some(self.workspace.id.clone()))
|
||||
.await
|
||||
.pop()
|
||||
.unwrap();
|
||||
let json = serde_json::to_string(&workspace).unwrap();
|
||||
assert_eq!(json, expected_json);
|
||||
}
|
||||
// FolderScript::AssertWorkspaceRevisionJson(expected_json) => {
|
||||
// let workspace = read_workspace(sdk, Some(self.workspace.id.clone()))
|
||||
// .await
|
||||
// .pop()
|
||||
// .unwrap();
|
||||
// let workspace_revision: WorkspaceRevision = workspace.into();
|
||||
// let json = serde_json::to_string(&workspace_revision).unwrap();
|
||||
// assert_eq!(json, expected_json);
|
||||
// }
|
||||
FolderScript::AssertWorkspace(workspace) => {
|
||||
assert_eq!(self.workspace, workspace);
|
||||
}
|
||||
@ -157,10 +159,11 @@ impl FolderTest {
|
||||
let app = create_app(sdk, &self.workspace.id, &name, &desc).await;
|
||||
self.app = app;
|
||||
}
|
||||
FolderScript::AssertAppJson(expected_json) => {
|
||||
let json = serde_json::to_string(&self.app).unwrap();
|
||||
assert_eq!(json, expected_json);
|
||||
}
|
||||
// FolderScript::AssertAppRevisionJson(expected_json) => {
|
||||
// let app_revision: AppRevision = self.app.clone().into();
|
||||
// let json = serde_json::to_string(&app_revision).unwrap();
|
||||
// assert_eq!(json, expected_json);
|
||||
// }
|
||||
FolderScript::AssertApp(app) => {
|
||||
assert_eq!(self.app, app);
|
||||
}
|
||||
@ -202,7 +205,7 @@ impl FolderTest {
|
||||
restore_view_from_trash(sdk, &self.view.id).await;
|
||||
}
|
||||
FolderScript::ReadTrash => {
|
||||
let trash = read_trash(sdk).await;
|
||||
let mut trash = read_trash(sdk).await;
|
||||
self.trash = trash.into_inner();
|
||||
}
|
||||
FolderScript::DeleteAllTrash => {
|
||||
@ -244,8 +247,8 @@ pub fn invalid_workspace_name_test_case() -> Vec<(String, ErrorCode)> {
|
||||
]
|
||||
}
|
||||
|
||||
pub async fn create_workspace(sdk: &FlowySDKTest, name: &str, desc: &str) -> Workspace {
|
||||
let request = CreateWorkspacePayload {
|
||||
pub async fn create_workspace(sdk: &FlowySDKTest, name: &str, desc: &str) -> WorkspacePB {
|
||||
let request = CreateWorkspacePayloadPB {
|
||||
name: name.to_owned(),
|
||||
desc: desc.to_owned(),
|
||||
};
|
||||
@ -255,18 +258,18 @@ pub async fn create_workspace(sdk: &FlowySDKTest, name: &str, desc: &str) -> Wor
|
||||
.payload(request)
|
||||
.async_send()
|
||||
.await
|
||||
.parse::<Workspace>();
|
||||
.parse::<WorkspacePB>();
|
||||
workspace
|
||||
}
|
||||
|
||||
pub async fn read_workspace(sdk: &FlowySDKTest, workspace_id: Option<String>) -> Vec<Workspace> {
|
||||
let request = WorkspaceId { value: workspace_id };
|
||||
let repeated_workspace = FolderEventBuilder::new(sdk.clone())
|
||||
pub async fn read_workspace(sdk: &FlowySDKTest, workspace_id: Option<String>) -> Vec<WorkspacePB> {
|
||||
let request = WorkspaceIdPB { value: workspace_id };
|
||||
let mut repeated_workspace = FolderEventBuilder::new(sdk.clone())
|
||||
.event(ReadWorkspaces)
|
||||
.payload(request.clone())
|
||||
.async_send()
|
||||
.await
|
||||
.parse::<RepeatedWorkspace>();
|
||||
.parse::<RepeatedWorkspacePB>();
|
||||
|
||||
let workspaces;
|
||||
if let Some(workspace_id) = &request.value {
|
||||
@ -274,7 +277,7 @@ pub async fn read_workspace(sdk: &FlowySDKTest, workspace_id: Option<String>) ->
|
||||
.into_inner()
|
||||
.into_iter()
|
||||
.filter(|workspace| &workspace.id == workspace_id)
|
||||
.collect::<Vec<Workspace>>();
|
||||
.collect::<Vec<WorkspacePB>>();
|
||||
debug_assert_eq!(workspaces.len(), 1);
|
||||
} else {
|
||||
workspaces = repeated_workspace.items;
|
||||
@ -283,8 +286,8 @@ pub async fn read_workspace(sdk: &FlowySDKTest, workspace_id: Option<String>) ->
|
||||
workspaces
|
||||
}
|
||||
|
||||
pub async fn create_app(sdk: &FlowySDKTest, workspace_id: &str, name: &str, desc: &str) -> App {
|
||||
let create_app_request = CreateAppPayload {
|
||||
pub async fn create_app(sdk: &FlowySDKTest, workspace_id: &str, name: &str, desc: &str) -> AppPB {
|
||||
let create_app_request = CreateAppPayloadPB {
|
||||
workspace_id: workspace_id.to_owned(),
|
||||
name: name.to_string(),
|
||||
desc: desc.to_string(),
|
||||
@ -296,12 +299,12 @@ pub async fn create_app(sdk: &FlowySDKTest, workspace_id: &str, name: &str, desc
|
||||
.payload(create_app_request)
|
||||
.async_send()
|
||||
.await
|
||||
.parse::<App>();
|
||||
.parse::<AppPB>();
|
||||
app
|
||||
}
|
||||
|
||||
pub async fn read_app(sdk: &FlowySDKTest, app_id: &str) -> App {
|
||||
let request = AppId {
|
||||
pub async fn read_app(sdk: &FlowySDKTest, app_id: &str) -> AppPB {
|
||||
let request = AppIdPB {
|
||||
value: app_id.to_owned(),
|
||||
};
|
||||
|
||||
@ -310,13 +313,13 @@ pub async fn read_app(sdk: &FlowySDKTest, app_id: &str) -> App {
|
||||
.payload(request)
|
||||
.async_send()
|
||||
.await
|
||||
.parse::<App>();
|
||||
.parse::<AppPB>();
|
||||
|
||||
app
|
||||
}
|
||||
|
||||
pub async fn update_app(sdk: &FlowySDKTest, app_id: &str, name: Option<String>, desc: Option<String>) {
|
||||
let request = UpdateAppPayload {
|
||||
let request = UpdateAppPayloadPB {
|
||||
app_id: app_id.to_string(),
|
||||
name,
|
||||
desc,
|
||||
@ -332,7 +335,7 @@ pub async fn update_app(sdk: &FlowySDKTest, app_id: &str, name: Option<String>,
|
||||
}
|
||||
|
||||
pub async fn delete_app(sdk: &FlowySDKTest, app_id: &str) {
|
||||
let request = AppId {
|
||||
let request = AppIdPB {
|
||||
value: app_id.to_string(),
|
||||
};
|
||||
|
||||
@ -343,8 +346,8 @@ pub async fn delete_app(sdk: &FlowySDKTest, app_id: &str) {
|
||||
.await;
|
||||
}
|
||||
|
||||
pub async fn create_view(sdk: &FlowySDKTest, app_id: &str, name: &str, desc: &str, data_type: ViewDataType) -> View {
|
||||
let request = CreateViewPayload {
|
||||
pub async fn create_view(sdk: &FlowySDKTest, app_id: &str, name: &str, desc: &str, data_type: ViewDataType) -> ViewPB {
|
||||
let request = CreateViewPayloadPB {
|
||||
belong_to_id: app_id.to_string(),
|
||||
name: name.to_string(),
|
||||
desc: desc.to_string(),
|
||||
@ -358,22 +361,22 @@ pub async fn create_view(sdk: &FlowySDKTest, app_id: &str, name: &str, desc: &st
|
||||
.payload(request)
|
||||
.async_send()
|
||||
.await
|
||||
.parse::<View>();
|
||||
.parse::<ViewPB>();
|
||||
view
|
||||
}
|
||||
|
||||
pub async fn read_view(sdk: &FlowySDKTest, view_id: &str) -> View {
|
||||
let view_id: ViewId = view_id.into();
|
||||
pub async fn read_view(sdk: &FlowySDKTest, view_id: &str) -> ViewPB {
|
||||
let view_id: ViewIdPB = view_id.into();
|
||||
FolderEventBuilder::new(sdk.clone())
|
||||
.event(ReadView)
|
||||
.payload(view_id)
|
||||
.async_send()
|
||||
.await
|
||||
.parse::<View>()
|
||||
.parse::<ViewPB>()
|
||||
}
|
||||
|
||||
pub async fn update_view(sdk: &FlowySDKTest, view_id: &str, name: Option<String>, desc: Option<String>) {
|
||||
let request = UpdateViewPayload {
|
||||
let request = UpdateViewPayloadPB {
|
||||
view_id: view_id.to_string(),
|
||||
name,
|
||||
desc,
|
||||
@ -387,7 +390,7 @@ pub async fn update_view(sdk: &FlowySDKTest, view_id: &str, name: Option<String>
|
||||
}
|
||||
|
||||
pub async fn delete_view(sdk: &FlowySDKTest, view_ids: Vec<String>) {
|
||||
let request = RepeatedViewId { items: view_ids };
|
||||
let request = RepeatedViewIdPB { items: view_ids };
|
||||
FolderEventBuilder::new(sdk.clone())
|
||||
.event(DeleteView)
|
||||
.payload(request)
|
||||
@ -396,26 +399,26 @@ pub async fn delete_view(sdk: &FlowySDKTest, view_ids: Vec<String>) {
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub async fn set_latest_view(sdk: &FlowySDKTest, view_id: &str) -> TextBlockInfo {
|
||||
let view_id: ViewId = view_id.into();
|
||||
pub async fn set_latest_view(sdk: &FlowySDKTest, view_id: &str) -> DocumentPB {
|
||||
let view_id: ViewIdPB = view_id.into();
|
||||
FolderEventBuilder::new(sdk.clone())
|
||||
.event(SetLatestView)
|
||||
.payload(view_id)
|
||||
.async_send()
|
||||
.await
|
||||
.parse::<TextBlockInfo>()
|
||||
.parse::<DocumentPB>()
|
||||
}
|
||||
|
||||
pub async fn read_trash(sdk: &FlowySDKTest) -> RepeatedTrash {
|
||||
pub async fn read_trash(sdk: &FlowySDKTest) -> RepeatedTrashPB {
|
||||
FolderEventBuilder::new(sdk.clone())
|
||||
.event(ReadTrash)
|
||||
.async_send()
|
||||
.await
|
||||
.parse::<RepeatedTrash>()
|
||||
.parse::<RepeatedTrashPB>()
|
||||
}
|
||||
|
||||
pub async fn restore_app_from_trash(sdk: &FlowySDKTest, app_id: &str) {
|
||||
let id = TrashId {
|
||||
let id = TrashIdPB {
|
||||
id: app_id.to_owned(),
|
||||
ty: TrashType::TrashApp,
|
||||
};
|
||||
@ -427,7 +430,7 @@ pub async fn restore_app_from_trash(sdk: &FlowySDKTest, app_id: &str) {
|
||||
}
|
||||
|
||||
pub async fn restore_view_from_trash(sdk: &FlowySDKTest, view_id: &str) {
|
||||
let id = TrashId {
|
||||
let id = TrashIdPB {
|
||||
id: view_id.to_owned(),
|
||||
ty: TrashType::TrashView,
|
||||
};
|
||||
|
Reference in New Issue
Block a user