Add Rig native model providers

This commit is contained in:
2026-08-06 15:03:00 -05:00
parent 634ce7ba00
commit 3fda5d414b
34 changed files with 2134 additions and 452 deletions
+1 -21
View File
@@ -1,32 +1,12 @@
use std::env::current_dir;
use galaxy_core::ui::appearance::Appearance;
use galaxyui::App;
use super::expand_dirs;
use crate::cloud_object::model::persistence::CloudModel;
use crate::network::NetworkStatus;
use crate::server::cloud_objects::update_manager::UpdateManager;
use crate::server::sync_queue::SyncQueue;
use crate::workspaces::team_tester::TeamTesterStatus;
use crate::workspaces::user_workspaces::UserWorkspaces;
use crate::{GlobalResourceHandles, GlobalResourceHandlesProvider};
#[test]
fn test_expand_directories() {
App::test((), |mut app| async move {
app.update(crate::settings::init_and_register_user_preferences);
let global_resource_handles = GlobalResourceHandles::mock(&mut app);
app.add_singleton_model(|_| GlobalResourceHandlesProvider::new(global_resource_handles));
app.add_singleton_model(CloudModel::mock);
app.add_singleton_model(UserWorkspaces::default_mock);
app.add_singleton_model(|_| Appearance::mock());
app.add_singleton_model(|_| NetworkStatus::new());
app.add_singleton_model(SyncQueue::mock);
app.add_singleton_model(TeamTesterStatus::mock);
app.add_singleton_model(UpdateManager::mock);
App::test((), |_| async move {
let directory = current_dir()
.expect("current directory should exist")
.parent()
+11 -5
View File
@@ -18,6 +18,7 @@ use super::modal_body::{ImportModalBody, ImportModalBodyAction, ImportModalBodyE
use crate::appearance::Appearance;
use crate::cloud_object::model::persistence::CloudModel;
use crate::cloud_object::{CloudObject, Owner};
use crate::local_object_repository::local_owner;
use crate::server::ids::SyncId;
use crate::server::sync_queue::SyncQueue;
use crate::themes::theme::GalaxyTheme;
@@ -88,7 +89,8 @@ impl ImportModal {
let window_id = ctx.window_id();
let import_body_id = self.import_modal.id();
let sync_queue_is_dequeueing = SyncQueue::as_ref(ctx).is_dequeueing();
let sync_queue_is_dequeueing =
self.owner != Some(local_owner()) && SyncQueue::as_ref(ctx).is_dequeueing();
let allowed_file_types = vec![FileType::Yaml, FileType::Markdown];
@@ -98,7 +100,7 @@ impl ImportModal {
// Files under a folder could only be uploaded when the folder is created on the server.
// When sync queue is not dequeueing, disable folder upload in the import modal.
if sync_queue_is_dequeueing {
if sync_queue_is_dequeueing || self.owner == Some(local_owner()) {
file_picker_config = file_picker_config.allow_folder();
}
@@ -165,9 +167,13 @@ impl ImportModal {
// Convert to a Space for display, in case we're importing into a shared folder.
self.owner
.map(|owner| {
UserWorkspaces::as_ref(app)
.owner_to_space(owner, app)
.name(app)
if owner == local_owner() {
"Personal".to_string()
} else {
UserWorkspaces::as_ref(app)
.owner_to_space(owner, app)
.name(app)
}
})
.unwrap_or_default(),
0,
+8 -4
View File
@@ -21,6 +21,7 @@ use super::nodes::{
use super::queue::{ImportQueue, ImportQueueArgs, ImportQueueEvent, ParentId, RequestContent};
use crate::appearance::Appearance;
use crate::cloud_object::Owner;
use crate::local_object_repository::local_owner;
use crate::server::ids::{ClientId, SyncId};
use crate::server::sync_queue::SyncQueue;
use crate::ui_components::icons::Icon;
@@ -96,7 +97,7 @@ pub struct ImportModalBody {
impl ImportModalBody {
pub fn new(ctx: &mut ViewContext<Self>) -> Self {
let import_queue = ctx.add_model(ImportQueue::new);
let import_queue = ctx.add_model(|_| ImportQueue::new());
ctx.subscribe_to_model(&import_queue, |me, _, event, ctx| {
me.handle_import_queue_event(event, ctx)
});
@@ -152,7 +153,8 @@ impl ImportModalBody {
}
}
let sync_queue_dequeueing = SyncQueue::as_ref(ctx).is_dequeueing();
let sync_queue_dequeueing =
self.owner != Some(local_owner()) && SyncQueue::as_ref(ctx).is_dequeueing();
if !sync_queue_dequeueing && state.all_files_saved_locally() {
ctx.emit(ImportModalBodyEvent::AllFileSavedLocally);
@@ -177,7 +179,8 @@ impl ImportModalBody {
// Whether there is an active upload in progress (If all uploads are completed,
// we don't consider the import modal upload to be in progress).
pub fn upload_in_progress(&self, app: &AppContext) -> bool {
let sync_queue_dequeueing = SyncQueue::as_ref(app).is_dequeueing();
let sync_queue_dequeueing =
self.owner != Some(local_owner()) && SyncQueue::as_ref(app).is_dequeueing();
match &self.state {
ImportState::Upload => false,
@@ -498,7 +501,8 @@ impl View for ImportModalBody {
}
fn render(&self, app: &AppContext) -> Box<dyn Element> {
let sync_queue_dequeueing = SyncQueue::as_ref(app).is_dequeueing();
let sync_queue_dequeueing =
self.owner != Some(local_owner()) && SyncQueue::as_ref(app).is_dequeueing();
let appearance = Appearance::as_ref(app);
match &self.state {
+165 -77
View File
@@ -5,7 +5,7 @@ use galaxyui::{Entity, ModelContext, SingletonEntity};
use super::nodes::{self, FileId};
use crate::cloud_object::model::persistence::CloudModel;
use crate::cloud_object::{CloudObjectEventEntrypoint, Owner};
use crate::drive::folders::FolderId;
use crate::local_object_repository::{local_owner, LocalObjectRepository};
use crate::notebooks::CloudNotebookModel;
use crate::server::cloud_objects::update_manager::{
InitiatedBy, ObjectOperation, OperationSuccessType, UpdateManager, UpdateManagerEvent,
@@ -94,31 +94,40 @@ impl FileCompletionCounter {
pub(super) struct ImportQueue {
queue: Vec<ImportQueueArgs>,
client_to_server_id: HashMap<ClientId, Option<FolderId>>,
client_to_folder_id: HashMap<ClientId, Option<SyncId>>,
client_to_node_folder_id: HashMap<ClientId, nodes::FolderId>,
file_completion: FileCompletionCounter,
remote_subscription_initialized: bool,
}
impl ImportQueue {
pub fn new(ctx: &mut ModelContext<Self>) -> Self {
pub fn new() -> Self {
Self {
queue: Vec::new(),
client_to_folder_id: HashMap::default(),
file_completion: Default::default(),
client_to_node_folder_id: HashMap::default(),
remote_subscription_initialized: false,
}
}
fn ensure_remote_subscription(&mut self, ctx: &mut ModelContext<Self>) {
if self.remote_subscription_initialized {
return;
}
let update_manager = UpdateManager::handle(ctx);
ctx.subscribe_to_model(&update_manager, |me, _, event, ctx| {
me.handle_update_manager_event(event, ctx);
});
Self {
queue: Vec::new(),
client_to_server_id: HashMap::default(),
file_completion: Default::default(),
client_to_node_folder_id: HashMap::default(),
}
self.remote_subscription_initialized = true;
}
// Whether all dependencies of an item has been sync-ed.
fn dependency_synced(&self, item: &ImportQueueArgs) -> bool {
match &item.parent_id {
ParentId::FolderToUpload(id) => self
.client_to_server_id
.client_to_folder_id
.get(id)
.map(|item| item.is_some())
.unwrap_or(false),
@@ -128,6 +137,11 @@ impl ImportQueue {
// Enqueue a new request to the import queue.
pub fn enqueue(&mut self, arg: ImportQueueArgs, ctx: &mut ModelContext<Self>) {
let is_local = arg.owner == local_owner();
if !is_local {
self.ensure_remote_subscription(ctx);
}
// Update internal tracker of the object.
match &arg.content {
RequestContent::Folder {
@@ -135,17 +149,23 @@ impl ImportQueue {
folder_id,
..
} => {
self.client_to_server_id.insert(*client_id, None);
self.client_to_folder_id.insert(*client_id, None);
self.client_to_node_folder_id.insert(*client_id, *folder_id);
}
RequestContent::Notebook {
client_id, file_id, ..
} => self.file_completion.add_entry(*client_id, *file_id),
} => {
if !is_local {
self.file_completion.add_entry(*client_id, *file_id);
}
}
RequestContent::Workflow {
workflows, file_id, ..
} => {
for (_, client_id) in workflows {
self.file_completion.add_entry(*client_id, *file_id);
if !is_local {
for (_, client_id) in workflows {
self.file_completion.add_entry(*client_id, *file_id);
}
}
}
}
@@ -167,31 +187,47 @@ impl ImportQueue {
{
let dequeued_item = self.queue.remove(idx);
let parent_id = match dequeued_item.parent_id {
ParentId::FolderToUpload(client_id) => Some(SyncId::ServerId(
self.client_to_server_id
ParentId::FolderToUpload(client_id) => Some(
self.client_to_folder_id
.get(&client_id)
.expect("Client id entry should exist")
.expect("Server id entry should exist")
.into(),
)),
.expect("Folder id entry should exist"),
),
ParentId::InitialFolder(folder_id) => folder_id,
};
let is_local = dequeued_item.owner == local_owner();
match dequeued_item.content {
RequestContent::Folder {
name, client_id, ..
} => {
UpdateManager::handle(ctx).update(ctx, |update_manager, ctx| {
update_manager.create_folder(
name,
dequeued_item.owner,
client_id,
parent_id,
false,
InitiatedBy::User,
ctx,
);
});
if is_local {
let local_id = SyncId::ClientId(client_id);
LocalObjectRepository::handle(ctx).update(ctx, |repository, ctx| {
repository.create_folder_with_id(local_id, name, parent_id, ctx);
});
self.client_to_folder_id.insert(client_id, Some(local_id));
ctx.emit(ImportQueueEvent::FolderCompleted {
folder_id: self
.client_to_node_folder_id
.get(&client_id)
.copied()
.expect("Folder node id should exist"),
server_id: Some(local_id.uid()),
});
} else {
UpdateManager::handle(ctx).update(ctx, |update_manager, ctx| {
update_manager.create_folder(
name,
dequeued_item.owner,
client_id,
parent_id,
false,
InitiatedBy::User,
ctx,
);
});
}
}
RequestContent::Notebook {
title,
@@ -199,56 +235,104 @@ impl ImportQueue {
client_id,
file_id,
} => {
UpdateManager::handle(ctx).update(ctx, |update_manager, ctx| {
update_manager.create_notebook(
client_id,
dequeued_item.owner,
parent_id,
CloudNotebookModel {
title,
data,
ai_document_id: None,
conversation_id: None,
},
CloudObjectEventEntrypoint::ImportModal,
false,
ctx,
);
});
ctx.emit(ImportQueueEvent::FileSavedLocally(file_id));
if is_local {
let local_id = SyncId::ClientId(client_id);
LocalObjectRepository::handle(ctx).update(ctx, |repository, ctx| {
repository.create_notebook_with_id(
local_id,
parent_id,
CloudNotebookModel {
title,
data,
ai_document_id: None,
conversation_id: None,
},
ctx,
);
});
ctx.emit(ImportQueueEvent::FileCompleted {
file_id,
server_id: Some(local_id.uid()),
});
} else {
UpdateManager::handle(ctx).update(ctx, |update_manager, ctx| {
update_manager.create_notebook(
client_id,
dequeued_item.owner,
parent_id,
CloudNotebookModel {
title,
data,
ai_document_id: None,
conversation_id: None,
},
CloudObjectEventEntrypoint::ImportModal,
false,
ctx,
);
});
ctx.emit(ImportQueueEvent::FileSavedLocally(file_id));
}
}
RequestContent::Workflow {
workflows,
workflow_enums,
file_id,
} => {
UpdateManager::handle(ctx).update(ctx, |update_manager, ctx| {
// Create any new workflow enums
for (client_id, workflow_enum) in workflow_enums {
update_manager.create_workflow_enum(
workflow_enum,
dequeued_item.owner,
client_id,
CloudObjectEventEntrypoint::ImportModal,
false,
ctx,
);
}
if is_local {
let local_object_id = workflows
.first()
.map(|(_, client_id)| SyncId::ClientId(*client_id).uid());
LocalObjectRepository::handle(ctx).update(ctx, |repository, ctx| {
for (client_id, workflow_enum) in workflow_enums {
repository.create_workflow_enum_with_id(
SyncId::ClientId(client_id),
workflow_enum,
ctx,
);
}
for (workflow, client_id) in workflows {
repository.create_workflow_with_id(
SyncId::ClientId(client_id),
parent_id,
workflow,
ctx,
);
}
});
ctx.emit(ImportQueueEvent::FileCompleted {
file_id,
server_id: local_object_id,
});
} else {
UpdateManager::handle(ctx).update(ctx, |update_manager, ctx| {
// Create any new workflow enums
for (client_id, workflow_enum) in workflow_enums {
update_manager.create_workflow_enum(
workflow_enum,
dequeued_item.owner,
client_id,
CloudObjectEventEntrypoint::ImportModal,
false,
ctx,
);
}
// Create the workflow
for (workflow, client_id) in workflows {
update_manager.create_workflow(
workflow,
dequeued_item.owner,
parent_id,
client_id,
CloudObjectEventEntrypoint::ImportModal,
false,
ctx,
);
}
});
ctx.emit(ImportQueueEvent::FileSavedLocally(file_id));
// Create the workflow
for (workflow, client_id) in workflows {
update_manager.create_workflow(
workflow,
dequeued_item.owner,
parent_id,
client_id,
CloudObjectEventEntrypoint::ImportModal,
false,
ctx,
);
}
});
ctx.emit(ImportQueueEvent::FileSavedLocally(file_id));
}
}
}
self.dequeue(ctx);
@@ -294,14 +378,14 @@ impl ImportQueue {
let Some(folder_id) = cloud_model
.get_folder_by_uid(&result.server_id.expect("Expect id").uid())
.and_then(|folder| folder.id.into_server())
.map(|folder| folder.id)
else {
return;
};
let replaced = match self.client_to_server_id.get_mut(&client_id) {
let replaced = match self.client_to_folder_id.get_mut(&client_id) {
Some(value) if value.is_none() => {
*value = Some(folder_id.into());
*value = Some(folder_id);
true
}
_ => false,
@@ -323,3 +407,7 @@ impl ImportQueue {
impl Entity for ImportQueue {
type Event = ImportQueueEvent;
}
#[cfg(test)]
#[path = "queue_tests.rs"]
mod tests;
+193
View File
@@ -0,0 +1,193 @@
use std::cell::RefCell;
use std::collections::HashMap;
use std::rc::Rc;
use galaxyui::{App, SingletonEntity};
use super::*;
use crate::cloud_object::model::persistence::CloudModel;
use crate::local_object_repository::local_owner;
use crate::server::ids::ClientId;
use crate::workflows::workflow_enum::{EnumVariants, WorkflowEnum};
#[derive(Debug, PartialEq, Eq)]
enum EventKind {
Folder {
folder_id: nodes::FolderId,
object_id: Option<String>,
},
File {
file_id: FileId,
object_id: Option<String>,
},
FileSavedLocally(FileId),
}
#[test]
fn local_import_queue_persists_nested_content_and_reports_completion() {
App::test((), |mut app| async move {
app.add_singleton_model(|_| CloudModel::new(None, Vec::new(), None));
app.add_singleton_model(|ctx| {
crate::local_object_repository::LocalObjectRepository::new(None, None, ctx)
});
let queue = app.add_model(|_| ImportQueue::new());
let events = Rc::new(RefCell::new(Vec::new()));
let events_for_subscription = events.clone();
app.update(|ctx| {
ctx.subscribe_to_model(&queue, move |_, event: &ImportQueueEvent, _| {
let event = match event {
ImportQueueEvent::FolderCompleted {
folder_id,
server_id,
} => EventKind::Folder {
folder_id: *folder_id,
object_id: server_id.clone(),
},
ImportQueueEvent::FileCompleted { file_id, server_id } => EventKind::File {
file_id: *file_id,
object_id: server_id.clone(),
},
ImportQueueEvent::FileSavedLocally(file_id) => {
EventKind::FileSavedLocally(*file_id)
}
};
events_for_subscription.borrow_mut().push(event);
});
});
let parent_client_id = ClientId::new();
let child_client_id = ClientId::new();
let notebook_client_id = ClientId::new();
let workflow_client_id = ClientId::new();
let workflow_enum_client_id = ClientId::new();
queue.update(&mut app, |queue, ctx| {
queue.enqueue(
ImportQueueArgs {
owner: local_owner(),
parent_id: ParentId::InitialFolder(None),
content: RequestContent::Folder {
name: "Imported".to_string(),
client_id: parent_client_id,
folder_id: nodes::FolderId::from(1),
},
},
ctx,
);
queue.enqueue(
ImportQueueArgs {
owner: local_owner(),
parent_id: ParentId::FolderToUpload(parent_client_id),
content: RequestContent::Folder {
name: "Nested".to_string(),
client_id: child_client_id,
folder_id: nodes::FolderId::from(2),
},
},
ctx,
);
queue.enqueue(
ImportQueueArgs {
owner: local_owner(),
parent_id: ParentId::FolderToUpload(child_client_id),
content: RequestContent::Notebook {
title: "Imported notes".to_string(),
data: "hello".to_string(),
client_id: notebook_client_id,
file_id: FileId(0),
},
},
ctx,
);
queue.enqueue(
ImportQueueArgs {
owner: local_owner(),
parent_id: ParentId::FolderToUpload(child_client_id),
content: RequestContent::Workflow {
workflows: vec![(
crate::workflows::workflow::Workflow::new(
"Imported workflow",
"echo imported",
),
workflow_client_id,
)],
workflow_enums: HashMap::from([(
workflow_enum_client_id,
WorkflowEnum {
name: "Environment".to_string(),
is_shared: false,
variants: EnumVariants::Static(vec!["dev".to_string()]),
},
)]),
file_id: FileId(1),
},
},
ctx,
);
});
let parent_id = SyncId::ClientId(parent_client_id);
let child_id = SyncId::ClientId(child_client_id);
let notebook_id = SyncId::ClientId(notebook_client_id);
let workflow_id = SyncId::ClientId(workflow_client_id);
let workflow_enum_id = SyncId::ClientId(workflow_enum_client_id);
app.update(|ctx| {
let cloud_model = CloudModel::as_ref(ctx);
let parent = cloud_model.get_folder(&parent_id).expect("parent folder");
assert_eq!(parent.permissions.owner, local_owner());
assert_eq!(
cloud_model
.get_folder(&child_id)
.unwrap()
.metadata
.folder_id,
Some(parent_id)
);
assert_eq!(
cloud_model
.get_notebook(&notebook_id)
.unwrap()
.metadata
.folder_id,
Some(child_id)
);
assert_eq!(
cloud_model
.get_workflow(&workflow_id)
.unwrap()
.metadata
.folder_id,
Some(child_id)
);
assert_eq!(
cloud_model
.get_workflow_enum(&workflow_enum_id)
.unwrap()
.model()
.string_model
.name,
"Environment"
);
});
let events = events.borrow();
assert!(events.contains(&EventKind::Folder {
folder_id: nodes::FolderId::from(1),
object_id: Some(parent_id.uid()),
}));
assert!(events.contains(&EventKind::Folder {
folder_id: nodes::FolderId::from(2),
object_id: Some(child_id.uid()),
}));
assert!(events.contains(&EventKind::File {
file_id: FileId(0),
object_id: Some(notebook_id.uid()),
}));
assert!(events.contains(&EventKind::File {
file_id: FileId(1),
object_id: Some(workflow_id.uid()),
}));
});
}
+100 -21
View File
@@ -68,7 +68,7 @@ use crate::drive::panel::DrivePanelAction;
use crate::editor::{EditorView, Event as EditorEvent, SingleLineEditorOptions};
use crate::env_vars::CloudEnvVarCollection;
use crate::features::FeatureFlag;
use crate::local_object_repository::LocalObjectRepository;
use crate::local_object_repository::{local_owner, LocalObjectRepository};
use crate::menu::{Event, Menu, MenuItem, MenuItemFields};
use crate::network::NetworkStatus;
use crate::notebooks::CloudNotebookModel;
@@ -1064,6 +1064,12 @@ impl DriveIndex {
NetworkStatus::as_ref(app).is_online()
}
fn is_local_folder(folder_id: &SyncId, app: &AppContext) -> bool {
CloudModel::as_ref(app)
.get_folder(folder_id)
.is_some_and(|folder| folder.permissions.owner == local_owner())
}
pub fn scroll_item_into_view(&mut self, item_id: WarpDriveItemId, ctx: &mut ViewContext<Self>) {
self.clipped_scroll_state.scroll_to_position(ScrollTarget {
position_id: item_id.drive_row_position_id(),
@@ -3330,9 +3336,15 @@ impl DriveIndex {
match new_location {
CloudObjectLocation::Space(space) => self.open_section_of_space(space),
CloudObjectLocation::Folder(folder_id) => {
cloud_model.update(ctx, |cloud_model, ctx| {
cloud_model.open_folder(folder_id, ctx);
});
if Self::is_local_folder(&folder_id, ctx) {
LocalObjectRepository::handle(ctx).update(ctx, |repository, ctx| {
repository.open_folder(folder_id, ctx);
});
} else {
cloud_model.update(ctx, |cloud_model, ctx| {
cloud_model.open_folder(folder_id, ctx);
});
}
}
// If location is the trash, then the above move_[object]_to_location call already trashed the object
CloudObjectLocation::Trash => {}
@@ -3508,9 +3520,15 @@ impl DriveIndex {
if !new_name.is_empty() {
self.reset_menus(ctx);
UpdateManager::handle(ctx).update(ctx, move |update_manager, ctx| {
update_manager.rename_folder(folder_id, new_name, ctx);
});
if Self::is_local_folder(&folder_id, ctx) {
LocalObjectRepository::handle(ctx).update(ctx, |repository, ctx| {
repository.update_folder_name(folder_id, new_name, ctx);
});
} else {
UpdateManager::handle(ctx).update(ctx, move |update_manager, ctx| {
update_manager.rename_folder(folder_id, new_name, ctx);
});
}
self.cloud_object_naming_dialog.close(ctx);
ctx.notify();
@@ -3542,6 +3560,11 @@ impl DriveIndex {
repository.set_env_var_collection_trashed(id, true, ctx);
});
}
CloudObjectTypeAndId::Folder(id) if Self::is_local_folder(&id, ctx) => {
LocalObjectRepository::handle(ctx).update(ctx, |repository, ctx| {
repository.set_folder_trashed(id, true, ctx);
});
}
CloudObjectTypeAndId::Folder(_) | CloudObjectTypeAndId::GenericStringObject { .. } => {
UpdateManager::handle(ctx).update(ctx, move |update_manager, ctx| {
update_manager.trash_object(cloud_object_type_and_id, ctx);
@@ -3585,6 +3608,14 @@ impl DriveIndex {
ctx.notify();
return;
}
CloudObjectTypeAndId::Folder(id) if Self::is_local_folder(id, ctx) => {
LocalObjectRepository::handle(ctx).update(ctx, |repository, ctx| {
repository.set_folder_trashed(*id, false, ctx);
});
self.reset_menus(ctx);
ctx.notify();
return;
}
CloudObjectTypeAndId::Folder(_) | CloudObjectTypeAndId::GenericStringObject { .. } => {}
}
@@ -3736,6 +3767,11 @@ impl DriveIndex {
repository.delete_env_var_collection(*id, ctx);
});
}
CloudObjectTypeAndId::Folder(id) if Self::is_local_folder(id, ctx) => {
LocalObjectRepository::handle(ctx).update(ctx, |repository, ctx| {
repository.delete_folder(*id, ctx);
});
}
CloudObjectTypeAndId::Folder(_) | CloudObjectTypeAndId::GenericStringObject { .. } => {
UpdateManager::handle(ctx).update(ctx, move |update_manager, ctx| {
update_manager.delete_object_by_user(*cloud_object_type_and_id, ctx);
@@ -5088,14 +5124,35 @@ impl DriveIndex {
}
}
CloudObjectTypeAndId::Folder(id) => {
CloudModel::handle(ctx).update(ctx, |cloud_model, ctx| match key {
DriveIndexAction::EnterKey => {
cloud_model.toggle_folder_open(*id, ctx);
}
DriveIndexAction::LeftArrowKey => cloud_model.close_folder(*id, ctx),
DriveIndexAction::RightArrowKey => cloud_model.open_folder(*id, ctx),
_ => {}
});
if Self::is_local_folder(id, ctx) {
LocalObjectRepository::handle(ctx).update(ctx, |repository, ctx| {
match key {
DriveIndexAction::EnterKey => {
repository.toggle_folder_open(*id, ctx);
}
DriveIndexAction::LeftArrowKey => {
repository.close_folder(*id, ctx)
}
DriveIndexAction::RightArrowKey => {
repository.open_folder(*id, ctx)
}
_ => {}
}
});
} else {
CloudModel::handle(ctx).update(ctx, |cloud_model, ctx| match key {
DriveIndexAction::EnterKey => {
cloud_model.toggle_folder_open(*id, ctx);
}
DriveIndexAction::LeftArrowKey => {
cloud_model.close_folder(*id, ctx)
}
DriveIndexAction::RightArrowKey => {
cloud_model.open_folder(*id, ctx)
}
_ => {}
});
}
}
CloudObjectTypeAndId::GenericStringObject { object_type, id: _ } => {
if let GenericStringObjectFormat::Json(JsonObjectType::EnvVarCollection) =
@@ -5556,14 +5613,36 @@ impl TypedActionView for DriveIndex {
ctx,
);
}
CloudModel::handle(ctx).update(ctx, |cloud_model, ctx| {
cloud_model.toggle_folder_open(*id, ctx);
});
if Self::is_local_folder(id, ctx) {
LocalObjectRepository::handle(ctx).update(ctx, |repository, ctx| {
repository.toggle_folder_open(*id, ctx);
});
} else {
CloudModel::handle(ctx).update(ctx, |cloud_model, ctx| {
cloud_model.toggle_folder_open(*id, ctx);
});
}
}
DriveIndexAction::CollapseAllInLocation(location) => {
CloudModel::handle(ctx).update(ctx, |cloud_model, ctx| {
cloud_model.collapse_all_in_location(*location, self.index_variant, ctx);
});
if let CloudObjectLocation::Folder(folder_id) = location {
if Self::is_local_folder(folder_id, ctx) {
LocalObjectRepository::handle(ctx).update(ctx, |repository, ctx| {
repository.collapse_local_folders_in_location(*location, ctx);
});
} else {
CloudModel::handle(ctx).update(ctx, |cloud_model, ctx| {
cloud_model.collapse_all_in_location(
*location,
self.index_variant,
ctx,
);
});
}
} else {
CloudModel::handle(ctx).update(ctx, |cloud_model, ctx| {
cloud_model.collapse_all_in_location(*location, self.index_variant, ctx);
});
}
}
DriveIndexAction::TrashObject {
cloud_object_type_and_id,
+22 -11
View File
@@ -178,17 +178,28 @@ impl DrivePanel {
} => match Self::new_object_owner(*space, initial_folder_id.as_ref(), ctx) {
Some(owner) => {
let client_id = ClientId::default();
UpdateManager::handle(ctx).update(ctx, |update_manager, ctx| {
update_manager.create_folder(
title.clone(),
owner,
client_id,
*initial_folder_id,
true,
InitiatedBy::User,
ctx,
);
});
if owner == local_owner() {
LocalObjectRepository::handle(ctx).update(ctx, |repository, ctx| {
repository.create_folder_with_id(
SyncId::ClientId(client_id),
title.clone(),
*initial_folder_id,
ctx,
);
});
} else {
UpdateManager::handle(ctx).update(ctx, |update_manager, ctx| {
update_manager.create_folder(
title.clone(),
owner,
client_id,
*initial_folder_id,
true,
InitiatedBy::User,
ctx,
);
});
}
}
None => {
log::error!("Cannot identify a folder owner from {space:?}");
+1 -8
View File
@@ -1,4 +1,3 @@
use galaxy_core::features::FeatureFlag;
use settings::macros::define_settings_group;
use settings::{RespectUserSyncSetting, Setting, SupportedPlatforms, SyncToCloud};
@@ -37,14 +36,8 @@ define_settings_group!(WarpDriveSettings, settings: [
impl WarpDriveSettings {
/// Returns whether Warp Drive should be considered enabled.
/// Returns `false` when the user is anonymous or fully logged out,
/// regardless of the user setting.
pub fn is_warp_drive_enabled(app: &galaxyui::AppContext) -> bool {
use galaxyui::SingletonEntity as _;
let is_anonymous_or_logged_out = FeatureFlag::SkipFirebaseAnonymousUser.is_enabled()
&& crate::auth::AuthStateProvider::as_ref(app)
.get()
.is_anonymous_or_logged_out();
*Self::as_ref(app).enable_warp_drive && !is_anonymous_or_logged_out
*Self::as_ref(app).enable_warp_drive
}
}