mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2025-07-10 10:36:23 +00:00

* feat: implement folder indexer * feat: sqlite search views using fts5 * feat: add view indexing to user manager * feat: implement folder indexer * feat: add sqlite search documents * feat: add document indexing to user manager * feat: add document indexing to folder indexer * chore: update collab rev * feat: search frontend integration * refactor: search index * test: add event test * chore: fix ci * feat: initial command palette overlay impl (#4619) * chore: test search engine * chore: initial structure * chore: replace old search request * chore: enable log for lib-dispatch * chore: move search manager to core * feat: move traits and responsibility to search crate * feat: move search to search crate * feat: replace sqlite with tantivy * feat: deserialize tantivy documents * chore: fixes after rebase * chore: clean code * feat: fetch and sort results * fix: code review + cleaning * feat: support custom icons * feat: support view layout icons * feat: rename bloc and fix indexing * fix: prettify dialog * feat: score results * chore: update collab rev * feat: add recent view history to command palette * test: add integration_tests * fix: clippy changes * fix: focus traversal in cmd palette * fix: remove file after merging main * chore: code review and panic-safe * feat: index all views if index does not exist * chore: improve logic with conditional * chore: add is_empty check * chore: abstract logic from folder manager init * chore: update collab rev * chore: code review * chore: fixes after merge + update lock file * chore: revert cargo lock * fix: set icon type when removing icon * fix: code review + dependency inversion * fix: remove icon fix for not persisting icon type * test: simple tests manipulating views * test: create 100 views * fix: tauri build * chore: create 1000 views * chore: create util methods * chore: test * chore: test * chore: remove logs * chore: fix build.rs * chore: export models * chore: enable clear cache on Rust-CI * fix: navigate to newly created views * fix: force disable setting workspace listener on rebuilds * fix: remove late final * fix: missing returns * fix: localization and minor fixes * test: add index assert to large test * fix: missing section param after merging main * chore: try fix unzip file error * chore: lower the test * feat: show hint when result is in trash * feat: one index_writer per index * fix: minor changes after merge * fix: make create_log_filter public after merge * chore: fix test * chore: fix test * chore: flutter analyze * chore: flutter analyze * chore: fix tauri build --------- Co-authored-by: nathan <nathan@appflowy.io> Co-authored-by: Lucas.Xu <lucas.xu@appflowy.io> Co-authored-by: Nathan.fooo <86001920+appflowy@users.noreply.github.com>
385 lines
9.6 KiB
Rust
385 lines
9.6 KiB
Rust
use collab_folder::ViewLayout;
|
|
|
|
use event_integration::event_builder::EventBuilder;
|
|
use event_integration::EventIntegrationTest;
|
|
use flowy_folder::entities::icon::{UpdateViewIconPayloadPB, ViewIconPB};
|
|
use flowy_folder::entities::*;
|
|
use flowy_folder::event_map::FolderEvent::*;
|
|
|
|
pub enum FolderScript {
|
|
#[allow(dead_code)]
|
|
CreateWorkspace {
|
|
name: String,
|
|
desc: String,
|
|
},
|
|
#[allow(dead_code)]
|
|
AssertWorkspace(WorkspacePB),
|
|
#[allow(dead_code)]
|
|
ReadWorkspace(String),
|
|
CreateParentView {
|
|
name: String,
|
|
desc: String,
|
|
},
|
|
AssertParentView(ViewPB),
|
|
ReloadParentView(String),
|
|
UpdateParentView {
|
|
name: Option<String>,
|
|
desc: Option<String>,
|
|
is_favorite: Option<bool>,
|
|
},
|
|
DeleteParentView,
|
|
|
|
// View
|
|
CreateView {
|
|
name: String,
|
|
desc: String,
|
|
layout: ViewLayout,
|
|
},
|
|
AssertView(ViewPB),
|
|
ReadView(String),
|
|
UpdateView {
|
|
name: Option<String>,
|
|
desc: Option<String>,
|
|
is_favorite: Option<bool>,
|
|
},
|
|
UpdateViewIcon {
|
|
icon: Option<ViewIconPB>,
|
|
},
|
|
DeleteView,
|
|
DeleteViews(Vec<String>),
|
|
MoveView {
|
|
view_id: String,
|
|
new_parent_id: String,
|
|
prev_view_id: Option<String>,
|
|
},
|
|
|
|
// Trash
|
|
RestoreAppFromTrash,
|
|
RestoreViewFromTrash,
|
|
ReadTrash,
|
|
DeleteAllTrash,
|
|
ToggleFavorite,
|
|
ReadFavorites,
|
|
}
|
|
|
|
pub struct FolderTest {
|
|
pub sdk: EventIntegrationTest,
|
|
pub workspace: WorkspacePB,
|
|
pub parent_view: ViewPB,
|
|
pub child_view: ViewPB,
|
|
pub trash: Vec<TrashPB>,
|
|
pub favorites: Vec<ViewPB>,
|
|
}
|
|
|
|
impl FolderTest {
|
|
pub async fn new() -> Self {
|
|
let sdk = EventIntegrationTest::new().await;
|
|
let _ = sdk.init_anon_user().await;
|
|
let workspace = sdk.folder_manager.get_current_workspace().await.unwrap();
|
|
let parent_view = create_view(
|
|
&sdk,
|
|
&workspace.id,
|
|
"first level view",
|
|
"",
|
|
ViewLayout::Document,
|
|
)
|
|
.await;
|
|
let view = create_view(
|
|
&sdk,
|
|
&parent_view.id,
|
|
"second level view",
|
|
"",
|
|
ViewLayout::Document,
|
|
)
|
|
.await;
|
|
Self {
|
|
sdk,
|
|
workspace,
|
|
parent_view,
|
|
child_view: view,
|
|
trash: vec![],
|
|
favorites: vec![],
|
|
}
|
|
}
|
|
|
|
pub async fn run_scripts(&mut self, scripts: Vec<FolderScript>) {
|
|
for script in scripts {
|
|
self.run_script(script).await;
|
|
}
|
|
}
|
|
|
|
pub async fn run_script(&mut self, script: FolderScript) {
|
|
let sdk = &self.sdk;
|
|
match script {
|
|
FolderScript::CreateWorkspace { name, desc } => {
|
|
let workspace = create_workspace(sdk, &name, &desc).await;
|
|
self.workspace = workspace;
|
|
},
|
|
FolderScript::AssertWorkspace(workspace) => {
|
|
assert_eq!(self.workspace, workspace, "Workspace not equal");
|
|
},
|
|
FolderScript::ReadWorkspace(workspace_id) => {
|
|
let workspace = read_workspace(sdk, workspace_id).await;
|
|
self.workspace = workspace;
|
|
},
|
|
FolderScript::CreateParentView { name, desc } => {
|
|
let app = create_view(sdk, &self.workspace.id, &name, &desc, ViewLayout::Document).await;
|
|
self.parent_view = app;
|
|
},
|
|
FolderScript::AssertParentView(app) => {
|
|
assert_eq!(self.parent_view, app, "App not equal");
|
|
},
|
|
FolderScript::ReloadParentView(parent_view_id) => {
|
|
let parent_view = read_view(sdk, &parent_view_id).await;
|
|
self.parent_view = parent_view;
|
|
},
|
|
FolderScript::UpdateParentView {
|
|
name,
|
|
desc,
|
|
is_favorite,
|
|
} => {
|
|
update_view(sdk, &self.parent_view.id, name, desc, is_favorite).await;
|
|
},
|
|
FolderScript::DeleteParentView => {
|
|
delete_view(sdk, vec![self.parent_view.id.clone()]).await;
|
|
},
|
|
FolderScript::CreateView { name, desc, layout } => {
|
|
let view = create_view(sdk, &self.parent_view.id, &name, &desc, layout).await;
|
|
self.child_view = view;
|
|
},
|
|
FolderScript::MoveView {
|
|
view_id,
|
|
new_parent_id,
|
|
prev_view_id,
|
|
} => {
|
|
move_view(sdk, view_id, new_parent_id, prev_view_id).await;
|
|
},
|
|
FolderScript::AssertView(view) => {
|
|
assert_eq!(self.child_view, view, "View not equal");
|
|
},
|
|
FolderScript::ReadView(view_id) => {
|
|
let view = read_view(sdk, &view_id).await;
|
|
self.child_view = view;
|
|
},
|
|
FolderScript::UpdateView {
|
|
name,
|
|
desc,
|
|
is_favorite,
|
|
} => {
|
|
update_view(sdk, &self.child_view.id, name, desc, is_favorite).await;
|
|
},
|
|
FolderScript::UpdateViewIcon { icon } => {
|
|
update_view_icon(sdk, &self.child_view.id, icon).await;
|
|
},
|
|
FolderScript::DeleteView => {
|
|
delete_view(sdk, vec![self.child_view.id.clone()]).await;
|
|
},
|
|
FolderScript::DeleteViews(view_ids) => {
|
|
delete_view(sdk, view_ids).await;
|
|
},
|
|
FolderScript::RestoreAppFromTrash => {
|
|
restore_app_from_trash(sdk, &self.parent_view.id).await;
|
|
},
|
|
FolderScript::RestoreViewFromTrash => {
|
|
restore_view_from_trash(sdk, &self.child_view.id).await;
|
|
},
|
|
FolderScript::ReadTrash => {
|
|
let trash = read_trash(sdk).await;
|
|
self.trash = trash.items;
|
|
},
|
|
FolderScript::DeleteAllTrash => {
|
|
delete_all_trash(sdk).await;
|
|
self.trash = vec![];
|
|
},
|
|
FolderScript::ToggleFavorite => {
|
|
toggle_favorites(sdk, vec![self.child_view.id.clone()]).await;
|
|
},
|
|
FolderScript::ReadFavorites => {
|
|
let favorites = read_favorites(sdk).await;
|
|
self.favorites = favorites.to_vec();
|
|
},
|
|
}
|
|
}
|
|
}
|
|
pub async fn create_workspace(sdk: &EventIntegrationTest, name: &str, desc: &str) -> WorkspacePB {
|
|
let request = CreateWorkspacePayloadPB {
|
|
name: name.to_owned(),
|
|
desc: desc.to_owned(),
|
|
};
|
|
|
|
EventBuilder::new(sdk.clone())
|
|
.event(CreateFolderWorkspace)
|
|
.payload(request)
|
|
.async_send()
|
|
.await
|
|
.parse::<WorkspacePB>()
|
|
}
|
|
|
|
pub async fn read_workspace(sdk: &EventIntegrationTest, workspace_id: String) -> WorkspacePB {
|
|
let request = WorkspaceIdPB {
|
|
value: workspace_id,
|
|
};
|
|
EventBuilder::new(sdk.clone())
|
|
.event(ReadCurrentWorkspace)
|
|
.payload(request.clone())
|
|
.async_send()
|
|
.await
|
|
.parse::<WorkspacePB>()
|
|
}
|
|
|
|
pub async fn create_view(
|
|
sdk: &EventIntegrationTest,
|
|
parent_view_id: &str,
|
|
name: &str,
|
|
desc: &str,
|
|
layout: ViewLayout,
|
|
) -> ViewPB {
|
|
let request = CreateViewPayloadPB {
|
|
parent_view_id: parent_view_id.to_string(),
|
|
name: name.to_string(),
|
|
desc: desc.to_string(),
|
|
thumbnail: None,
|
|
layout: layout.into(),
|
|
initial_data: vec![],
|
|
meta: Default::default(),
|
|
set_as_current: true,
|
|
index: None,
|
|
section: None,
|
|
};
|
|
EventBuilder::new(sdk.clone())
|
|
.event(CreateView)
|
|
.payload(request)
|
|
.async_send()
|
|
.await
|
|
.parse::<ViewPB>()
|
|
}
|
|
|
|
pub async fn read_view(sdk: &EventIntegrationTest, view_id: &str) -> ViewPB {
|
|
let view_id = ViewIdPB::from(view_id);
|
|
EventBuilder::new(sdk.clone())
|
|
.event(GetView)
|
|
.payload(view_id)
|
|
.async_send()
|
|
.await
|
|
.parse::<ViewPB>()
|
|
}
|
|
|
|
pub async fn move_view(
|
|
sdk: &EventIntegrationTest,
|
|
view_id: String,
|
|
parent_id: String,
|
|
prev_view_id: Option<String>,
|
|
) {
|
|
let payload = MoveNestedViewPayloadPB {
|
|
view_id,
|
|
new_parent_id: parent_id,
|
|
prev_view_id,
|
|
from_section: None,
|
|
to_section: None,
|
|
};
|
|
let error = EventBuilder::new(sdk.clone())
|
|
.event(MoveNestedView)
|
|
.payload(payload)
|
|
.async_send()
|
|
.await
|
|
.error();
|
|
|
|
assert!(error.is_none());
|
|
}
|
|
pub async fn update_view(
|
|
sdk: &EventIntegrationTest,
|
|
view_id: &str,
|
|
name: Option<String>,
|
|
desc: Option<String>,
|
|
is_favorite: Option<bool>,
|
|
) {
|
|
println!("Toggling update view {:?}", is_favorite);
|
|
let request = UpdateViewPayloadPB {
|
|
view_id: view_id.to_string(),
|
|
name,
|
|
desc,
|
|
is_favorite,
|
|
..Default::default()
|
|
};
|
|
EventBuilder::new(sdk.clone())
|
|
.event(UpdateView)
|
|
.payload(request)
|
|
.async_send()
|
|
.await;
|
|
}
|
|
|
|
pub async fn update_view_icon(sdk: &EventIntegrationTest, view_id: &str, icon: Option<ViewIconPB>) {
|
|
let request = UpdateViewIconPayloadPB {
|
|
view_id: view_id.to_string(),
|
|
icon,
|
|
};
|
|
EventBuilder::new(sdk.clone())
|
|
.event(UpdateViewIcon)
|
|
.payload(request)
|
|
.async_send()
|
|
.await;
|
|
}
|
|
|
|
pub async fn delete_view(sdk: &EventIntegrationTest, view_ids: Vec<String>) {
|
|
let request = RepeatedViewIdPB { items: view_ids };
|
|
EventBuilder::new(sdk.clone())
|
|
.event(DeleteView)
|
|
.payload(request)
|
|
.async_send()
|
|
.await;
|
|
}
|
|
|
|
pub async fn read_trash(sdk: &EventIntegrationTest) -> RepeatedTrashPB {
|
|
EventBuilder::new(sdk.clone())
|
|
.event(ListTrashItems)
|
|
.async_send()
|
|
.await
|
|
.parse::<RepeatedTrashPB>()
|
|
}
|
|
|
|
pub async fn restore_app_from_trash(sdk: &EventIntegrationTest, app_id: &str) {
|
|
let id = TrashIdPB {
|
|
id: app_id.to_owned(),
|
|
};
|
|
EventBuilder::new(sdk.clone())
|
|
.event(RestoreTrashItem)
|
|
.payload(id)
|
|
.async_send()
|
|
.await;
|
|
}
|
|
|
|
pub async fn restore_view_from_trash(sdk: &EventIntegrationTest, view_id: &str) {
|
|
let id = TrashIdPB {
|
|
id: view_id.to_owned(),
|
|
};
|
|
EventBuilder::new(sdk.clone())
|
|
.event(RestoreTrashItem)
|
|
.payload(id)
|
|
.async_send()
|
|
.await;
|
|
}
|
|
|
|
pub async fn delete_all_trash(sdk: &EventIntegrationTest) {
|
|
EventBuilder::new(sdk.clone())
|
|
.event(PermanentlyDeleteAllTrashItem)
|
|
.async_send()
|
|
.await;
|
|
}
|
|
|
|
pub async fn toggle_favorites(sdk: &EventIntegrationTest, view_id: Vec<String>) {
|
|
let request = RepeatedViewIdPB { items: view_id };
|
|
EventBuilder::new(sdk.clone())
|
|
.event(ToggleFavorite)
|
|
.payload(request)
|
|
.async_send()
|
|
.await;
|
|
}
|
|
|
|
pub async fn read_favorites(sdk: &EventIntegrationTest) -> RepeatedViewPB {
|
|
EventBuilder::new(sdk.clone())
|
|
.event(ReadFavorites)
|
|
.async_send()
|
|
.await
|
|
.parse::<RepeatedViewPB>()
|
|
}
|