mirror of
https://github.com/nyakang/nyaterm.git
synced 2026-10-03 08:00:54 +00:00
refactor(desktop): encapsulate settings store status
This commit is contained in:
@@ -180,8 +180,9 @@ impl NyaTermApp {
|
||||
cx.spawn(async move |this, cx| {
|
||||
if let Err(error) = task.await {
|
||||
let _ = this.update(cx, |this, cx| {
|
||||
this.settings.store_status.message = format!("AI audit save failed: {error}");
|
||||
this.settings.store_status.ready = false;
|
||||
this.settings
|
||||
.set_store_message(format!("AI audit save failed: {error}"));
|
||||
this.settings.set_store_ready(false);
|
||||
cx.notify();
|
||||
});
|
||||
} else {
|
||||
|
||||
@@ -85,14 +85,16 @@ impl NyaTermApp {
|
||||
Ok(discoveries) => {
|
||||
let count = self.apply_ai_model_discoveries(&event.profile_id, discoveries);
|
||||
self.ai.panel.status = format!("Discovered {count} AI model(s)");
|
||||
self.settings.store_status.message = self.ai.panel.status.clone();
|
||||
self.settings.store_status.ready = true;
|
||||
self.settings
|
||||
.set_store_message(self.ai.panel.status.clone());
|
||||
self.settings.set_store_ready(true);
|
||||
self.persist_ai_settings_now(cx);
|
||||
}
|
||||
Err(error) => {
|
||||
self.ai.panel.status = format!("AI model discovery failed: {error}");
|
||||
self.settings.store_status.message = self.ai.panel.status.clone();
|
||||
self.settings.store_status.ready = false;
|
||||
self.settings
|
||||
.set_store_message(self.ai.panel.status.clone());
|
||||
self.settings.set_store_ready(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,7 +75,8 @@ impl NyaTermApp {
|
||||
"AI Agent request was cancelled",
|
||||
);
|
||||
}
|
||||
self.settings.store_status.message = self.ai.panel.status.clone();
|
||||
self.settings
|
||||
.set_store_message(self.ai.panel.status.clone());
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
@@ -790,9 +791,9 @@ impl NyaTermApp {
|
||||
} else {
|
||||
"AI stream receiving".to_string()
|
||||
};
|
||||
self.settings.store_status.message =
|
||||
format!("AI session {session_id} streaming");
|
||||
self.settings.store_status.ready = true;
|
||||
self.settings
|
||||
.set_store_message(format!("AI session {session_id} streaming"));
|
||||
self.settings.set_store_ready(true);
|
||||
}
|
||||
AiChatWorkerEvent::AgentToolCallDelta {
|
||||
job_id,
|
||||
@@ -832,9 +833,10 @@ impl NyaTermApp {
|
||||
format!("Streaming arguments (+{arguments_delta_len} chars)")
|
||||
},
|
||||
);
|
||||
self.settings.store_status.message =
|
||||
format!("AI session {session_id} streaming Agent tool call");
|
||||
self.settings.store_status.ready = true;
|
||||
self.settings.set_store_message(format!(
|
||||
"AI session {session_id} streaming Agent tool call"
|
||||
));
|
||||
self.settings.set_store_ready(true);
|
||||
}
|
||||
AiChatWorkerEvent::AgentBackgroundFinished {
|
||||
job_id,
|
||||
@@ -879,8 +881,9 @@ impl NyaTermApp {
|
||||
"Failed",
|
||||
truncate_preview(&error, 140),
|
||||
);
|
||||
self.settings.store_status.message = self.ai.panel.status.clone();
|
||||
self.settings.store_status.ready = false;
|
||||
self.settings
|
||||
.set_store_message(self.ai.panel.status.clone());
|
||||
self.settings.set_store_ready(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -958,9 +961,11 @@ impl NyaTermApp {
|
||||
message.command_cards = output.command_cards.clone();
|
||||
}
|
||||
}
|
||||
self.settings.store_status.message =
|
||||
format!("AI session {} updated", event.session_id);
|
||||
self.settings.store_status.ready = true;
|
||||
self.settings.set_store_message(format!(
|
||||
"AI session {} updated",
|
||||
event.session_id
|
||||
));
|
||||
self.settings.set_store_ready(true);
|
||||
self.reset_text_input("ai.chat.prompt", "", cx);
|
||||
self.ai.chat.prompt_draft.clear();
|
||||
self.refresh_ai_usage_counts(cx);
|
||||
@@ -1007,8 +1012,9 @@ impl NyaTermApp {
|
||||
truncate_preview(&error, 140),
|
||||
);
|
||||
}
|
||||
self.settings.store_status.message = self.ai.panel.status.clone();
|
||||
self.settings.store_status.ready = false;
|
||||
self.settings
|
||||
.set_store_message(self.ai.panel.status.clone());
|
||||
self.settings.set_store_ready(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,13 +125,15 @@ impl NyaTermApp {
|
||||
if self.ai.panel.status.trim().is_empty() {
|
||||
self.ai.panel.status = "AI settings saved".to_string();
|
||||
}
|
||||
self.settings.store_status.message = self.ai.panel.status.clone();
|
||||
self.settings.store_status.ready = true;
|
||||
self.settings
|
||||
.set_store_message(self.ai.panel.status.clone());
|
||||
self.settings.set_store_ready(true);
|
||||
}
|
||||
Err(error) => {
|
||||
self.ai.panel.status = format!("AI settings save failed: {error}");
|
||||
self.settings.store_status.message = self.ai.panel.status.clone();
|
||||
self.settings.store_status.ready = false;
|
||||
self.settings
|
||||
.set_store_message(self.ai.panel.status.clone());
|
||||
self.settings.set_store_ready(false);
|
||||
}
|
||||
}
|
||||
cx.notify();
|
||||
|
||||
@@ -14,7 +14,7 @@ use nyaterm_transport::{SessionManager, SftpDuplicatePolicy};
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
|
||||
use super::super::settings::{SettingsFeatureFocus, SettingsFeatureState, StoreStatus};
|
||||
use super::super::settings::{SettingsFeatureFocus, SettingsFeatureState};
|
||||
use super::super::{
|
||||
AiFeatureFocus, AiFeatureState, CloudSyncFeatureState, CommandFeatureInit, CommandFeatureState,
|
||||
ConnectionCatalogState, ConnectionFeatureFocus, ConnectionFeatureState,
|
||||
@@ -111,11 +111,7 @@ impl NyaTermApp {
|
||||
command_history,
|
||||
keyword_highlights,
|
||||
settings,
|
||||
StoreStatus {
|
||||
path,
|
||||
message: "redb connection store online".to_string(),
|
||||
ready: true,
|
||||
},
|
||||
(path, "redb connection store online".to_string(), true),
|
||||
cloud_sync_settings,
|
||||
cloud_sync_state,
|
||||
translation_settings,
|
||||
@@ -141,11 +137,7 @@ impl NyaTermApp {
|
||||
Vec::new(),
|
||||
KeywordHighlightConfig::default(),
|
||||
AppSettingsSummary::default(),
|
||||
StoreStatus {
|
||||
path,
|
||||
message: format!("failed to load sessions: {error}"),
|
||||
ready: false,
|
||||
},
|
||||
(path, format!("failed to load sessions: {error}"), false),
|
||||
CloudSyncSettings::default(),
|
||||
CloudSyncState::default(),
|
||||
TranslationSettings::default(),
|
||||
@@ -172,15 +164,15 @@ impl NyaTermApp {
|
||||
Vec::new(),
|
||||
KeywordHighlightConfig::default(),
|
||||
AppSettingsSummary::default(),
|
||||
StoreStatus {
|
||||
path: runtime
|
||||
(
|
||||
runtime
|
||||
.config_dir()
|
||||
.join("nyaterm.redb")
|
||||
.display()
|
||||
.to_string(),
|
||||
message: format!("failed to open store: {error}"),
|
||||
ready: false,
|
||||
},
|
||||
format!("failed to open store: {error}"),
|
||||
false,
|
||||
),
|
||||
CloudSyncSettings::default(),
|
||||
CloudSyncState::default(),
|
||||
TranslationSettings::default(),
|
||||
@@ -431,7 +423,9 @@ impl NyaTermApp {
|
||||
settings: SettingsFeatureState::new(
|
||||
settings,
|
||||
keyword_highlights,
|
||||
store_status,
|
||||
store_status.0,
|
||||
store_status.1,
|
||||
store_status.2,
|
||||
appearance_ui_font_options,
|
||||
appearance_terminal_font_options,
|
||||
SettingsFeatureFocus {
|
||||
|
||||
@@ -267,17 +267,17 @@ impl NyaTermApp {
|
||||
}
|
||||
}
|
||||
if !self.commands.queue_command_history(submitted) {
|
||||
self.settings.store_status.message =
|
||||
"command history worker is unavailable".to_string();
|
||||
self.settings.store_status.ready = false;
|
||||
self.settings
|
||||
.set_store_message("command history worker is unavailable".to_string());
|
||||
self.settings.set_store_ready(false);
|
||||
}
|
||||
}
|
||||
|
||||
pub(in crate::features) fn queue_quick_command_use_count(&mut self, command_id: String) {
|
||||
if !self.commands.queue_quick_command_use_count(command_id) {
|
||||
self.settings.store_status.message =
|
||||
"command persistence worker is unavailable".to_string();
|
||||
self.settings.store_status.ready = false;
|
||||
self.settings
|
||||
.set_store_message("command persistence worker is unavailable".to_string());
|
||||
self.settings.set_store_ready(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -289,9 +289,10 @@ impl NyaTermApp {
|
||||
CommandPersistencePoll::Empty => break,
|
||||
CommandPersistencePoll::Disconnected { had_pending } => {
|
||||
if had_pending {
|
||||
self.settings.store_status.message =
|
||||
"command persistence worker disconnected".to_string();
|
||||
self.settings.store_status.ready = false;
|
||||
self.settings.set_store_message(
|
||||
"command persistence worker disconnected".to_string(),
|
||||
);
|
||||
self.settings.set_store_ready(false);
|
||||
dirty = true;
|
||||
}
|
||||
break;
|
||||
@@ -299,8 +300,8 @@ impl NyaTermApp {
|
||||
};
|
||||
dirty = true;
|
||||
if let Err(message) = self.commands.apply_persistence_result(event) {
|
||||
self.settings.store_status.message = message;
|
||||
self.settings.store_status.ready = false;
|
||||
self.settings.set_store_message(message);
|
||||
self.settings.set_store_ready(false);
|
||||
}
|
||||
}
|
||||
dirty
|
||||
|
||||
@@ -23,9 +23,9 @@ impl NyaTermApp {
|
||||
.replace_quick_command_catalog(config.commands, config.categories);
|
||||
}
|
||||
Err(error) => {
|
||||
self.settings.store_status.message =
|
||||
format!("quick command refresh failed: {error}");
|
||||
self.settings.store_status.ready = false;
|
||||
self.settings
|
||||
.set_store_message(format!("quick command refresh failed: {error}"));
|
||||
self.settings.set_store_ready(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -61,15 +61,16 @@ impl NyaTermApp {
|
||||
{
|
||||
Ok(settings) => {
|
||||
self.apply_gpui_settings(settings);
|
||||
self.settings.store_status.message = "quick command UI settings saved".to_string();
|
||||
self.settings.store_status.ready = true;
|
||||
self.settings
|
||||
.set_store_message("quick command UI settings saved".to_string());
|
||||
self.settings.set_store_ready(true);
|
||||
self.terminal.view.status = "quick command UI settings saved".to_string();
|
||||
}
|
||||
Err(error) => {
|
||||
self.settings.store_status.message =
|
||||
format!("quick command UI settings save failed: {error}");
|
||||
self.settings.store_status.ready = false;
|
||||
self.terminal.view.status = self.settings.store_status.message.clone();
|
||||
self.settings
|
||||
.set_store_message(format!("quick command UI settings save failed: {error}"));
|
||||
self.settings.set_store_ready(false);
|
||||
self.terminal.view.status = self.settings.store_status().message.to_string();
|
||||
}
|
||||
}
|
||||
cx.notify();
|
||||
|
||||
@@ -153,19 +153,19 @@ impl NyaTermApp {
|
||||
self.commands
|
||||
.replace_quick_command_catalog(config.commands, config.categories);
|
||||
self.commands.clear_quick_delete();
|
||||
self.settings.store_status.message = if deleted {
|
||||
self.settings.set_store_message(if deleted {
|
||||
format!("quick command '{}' deleted", delete.label)
|
||||
} else {
|
||||
format!("quick command '{}' was already deleted", delete.label)
|
||||
};
|
||||
self.settings.store_status.ready = deleted;
|
||||
self.terminal.view.status = self.settings.store_status.message.clone();
|
||||
});
|
||||
self.settings.set_store_ready(deleted);
|
||||
self.terminal.view.status = self.settings.store_status().message.to_string();
|
||||
}
|
||||
Err(error) => {
|
||||
self.settings.store_status.message =
|
||||
format!("quick command delete failed: {error}");
|
||||
self.settings.store_status.ready = false;
|
||||
self.terminal.view.status = self.settings.store_status.message.clone();
|
||||
self.settings
|
||||
.set_store_message(format!("quick command delete failed: {error}"));
|
||||
self.settings.set_store_ready(false);
|
||||
self.terminal.view.status = self.settings.store_status().message.to_string();
|
||||
}
|
||||
}
|
||||
cx.notify();
|
||||
@@ -242,7 +242,7 @@ impl NyaTermApp {
|
||||
self.commands
|
||||
.replace_quick_command_catalog(config.commands, config.categories);
|
||||
self.commands.finish_quick_category_delete(&delete.id);
|
||||
self.settings.store_status.message = if deleted_category {
|
||||
self.settings.set_store_message(if deleted_category {
|
||||
format!(
|
||||
"quick command category '{}' deleted with {} command(s)",
|
||||
delete.name, deleted_commands
|
||||
@@ -252,15 +252,15 @@ impl NyaTermApp {
|
||||
"quick command category '{}' was already deleted",
|
||||
delete.name
|
||||
)
|
||||
};
|
||||
self.settings.store_status.ready = deleted_category;
|
||||
self.terminal.view.status = self.settings.store_status.message.clone();
|
||||
});
|
||||
self.settings.set_store_ready(deleted_category);
|
||||
self.terminal.view.status = self.settings.store_status().message.to_string();
|
||||
}
|
||||
Err(error) => {
|
||||
self.settings.store_status.message =
|
||||
format!("quick command category delete failed: {error}");
|
||||
self.settings.store_status.ready = false;
|
||||
self.terminal.view.status = self.settings.store_status.message.clone();
|
||||
self.settings
|
||||
.set_store_message(format!("quick command category delete failed: {error}"));
|
||||
self.settings.set_store_ready(false);
|
||||
self.terminal.view.status = self.settings.store_status().message.to_string();
|
||||
}
|
||||
}
|
||||
cx.notify();
|
||||
@@ -362,28 +362,29 @@ impl NyaTermApp {
|
||||
.replace_quick_command_catalog(config.commands, config.categories);
|
||||
if renamed {
|
||||
self.commands.clear_quick_category_rename();
|
||||
self.settings.store_status.message = format!(
|
||||
self.settings.set_store_message(format!(
|
||||
"quick command category '{}' renamed to '{}'",
|
||||
rename.original_name, name
|
||||
);
|
||||
self.settings.store_status.ready = true;
|
||||
));
|
||||
self.settings.set_store_ready(true);
|
||||
} else {
|
||||
self.commands.set_quick_category_rename_error(
|
||||
"Category is no longer available".to_string(),
|
||||
);
|
||||
self.settings.store_status.message =
|
||||
"quick command category rename failed: category missing".to_string();
|
||||
self.settings.store_status.ready = false;
|
||||
self.settings.set_store_message(
|
||||
"quick command category rename failed: category missing".to_string(),
|
||||
);
|
||||
self.settings.set_store_ready(false);
|
||||
}
|
||||
self.terminal.view.status = self.settings.store_status.message.clone();
|
||||
self.terminal.view.status = self.settings.store_status().message.to_string();
|
||||
}
|
||||
Err(error) => {
|
||||
self.commands
|
||||
.set_quick_category_rename_error(error.to_string());
|
||||
self.settings.store_status.message =
|
||||
format!("quick command category rename failed: {error}");
|
||||
self.settings.store_status.ready = false;
|
||||
self.terminal.view.status = self.settings.store_status.message.clone();
|
||||
self.settings
|
||||
.set_store_message(format!("quick command category rename failed: {error}"));
|
||||
self.settings.set_store_ready(false);
|
||||
self.terminal.view.status = self.settings.store_status().message.to_string();
|
||||
}
|
||||
}
|
||||
cx.notify();
|
||||
|
||||
@@ -180,17 +180,18 @@ impl NyaTermApp {
|
||||
self.commands
|
||||
.replace_quick_command_catalog(config.commands, config.categories);
|
||||
self.commands.close_quick_editor();
|
||||
self.settings.store_status.message =
|
||||
format!("quick command '{}' saved", command.label);
|
||||
self.settings.store_status.ready = true;
|
||||
self.terminal.view.status = self.settings.store_status.message.clone();
|
||||
self.settings
|
||||
.set_store_message(format!("quick command '{}' saved", command.label));
|
||||
self.settings.set_store_ready(true);
|
||||
self.terminal.view.status = self.settings.store_status().message.to_string();
|
||||
}
|
||||
Err(error) => {
|
||||
self.commands
|
||||
.set_quick_editor_error(error.to_string(), None);
|
||||
self.settings.store_status.message = format!("quick command save failed: {error}");
|
||||
self.settings.store_status.ready = false;
|
||||
self.terminal.view.status = self.settings.store_status.message.clone();
|
||||
self.settings
|
||||
.set_store_message(format!("quick command save failed: {error}"));
|
||||
self.settings.set_store_ready(false);
|
||||
self.terminal.view.status = self.settings.store_status().message.to_string();
|
||||
}
|
||||
}
|
||||
cx.notify();
|
||||
|
||||
@@ -112,16 +112,18 @@ impl NyaTermApp {
|
||||
self.terminal.view.status = format!(
|
||||
"imported {imported_commands} quick command(s), updated {updated_commands}, categories +{imported_categories}, total {total_commands}/{total_categories}"
|
||||
);
|
||||
self.settings.store_status.message = self.terminal.view.status.clone();
|
||||
self.settings.store_status.ready = true;
|
||||
self.settings
|
||||
.set_store_message(self.terminal.view.status.clone());
|
||||
self.settings.set_store_ready(true);
|
||||
}
|
||||
QuickCommandImportPathPromptResult::Cancelled => {
|
||||
self.terminal.view.status = "quick command import cancelled".to_string();
|
||||
}
|
||||
QuickCommandImportPathPromptResult::Failed(error) => {
|
||||
self.terminal.view.status = format!("quick command import failed: {error}");
|
||||
self.settings.store_status.message = self.terminal.view.status.clone();
|
||||
self.settings.store_status.ready = false;
|
||||
self.settings
|
||||
.set_store_message(self.terminal.view.status.clone());
|
||||
self.settings.set_store_ready(false);
|
||||
}
|
||||
QuickCommandImportPathPromptResult::Closed => {
|
||||
self.terminal.view.status =
|
||||
|
||||
@@ -126,14 +126,16 @@ impl NyaTermApp {
|
||||
"Saved AI command card '{}' to Quick Commands",
|
||||
label
|
||||
));
|
||||
self.settings.store_status.message = self.ai.panel_status().to_string();
|
||||
self.settings.store_status.ready = true;
|
||||
self.settings
|
||||
.set_store_message(self.ai.panel_status().to_string());
|
||||
self.settings.set_store_ready(true);
|
||||
}
|
||||
Err(error) => {
|
||||
self.ai
|
||||
.set_panel_status(format!("Quick command save failed: {error}"));
|
||||
self.settings.store_status.message = self.ai.panel_status().to_string();
|
||||
self.settings.store_status.ready = false;
|
||||
self.settings
|
||||
.set_store_message(self.ai.panel_status().to_string());
|
||||
self.settings.set_store_ready(false);
|
||||
}
|
||||
}
|
||||
cx.notify();
|
||||
|
||||
@@ -147,8 +147,8 @@ impl NyaTermApp {
|
||||
.tr("savedConnections.importSuccess")
|
||||
.replace("{{count}}", &count.to_string());
|
||||
self.terminal.view.status = message.clone();
|
||||
self.settings.store_status.message = message;
|
||||
self.settings.store_status.ready = true;
|
||||
self.settings.set_store_message(message);
|
||||
self.settings.set_store_ready(true);
|
||||
}
|
||||
ConnectionImportResult::Cancelled => {
|
||||
self.terminal.view.status = "connection import cancelled".to_string();
|
||||
@@ -158,8 +158,8 @@ impl NyaTermApp {
|
||||
.tr("savedConnections.importFailed")
|
||||
.replace("{{error}}", &error);
|
||||
self.terminal.view.status = message.clone();
|
||||
self.settings.store_status.message = message;
|
||||
self.settings.store_status.ready = false;
|
||||
self.settings.set_store_message(message);
|
||||
self.settings.set_store_ready(false);
|
||||
}
|
||||
ConnectionImportResult::Closed => {
|
||||
self.terminal.view.status = "connection import picker closed".to_string();
|
||||
|
||||
@@ -38,8 +38,9 @@ impl NyaTermApp {
|
||||
Err(error) => {
|
||||
self.connection_state.close_clear_all();
|
||||
self.terminal.view.status = format!("clear saved connections failed: {error}");
|
||||
self.settings.store_status.message = self.terminal.view.status.clone();
|
||||
self.settings.store_status.ready = false;
|
||||
self.settings
|
||||
.set_store_message(self.terminal.view.status.clone());
|
||||
self.settings.set_store_ready(false);
|
||||
}
|
||||
}
|
||||
cx.notify();
|
||||
|
||||
@@ -67,8 +67,9 @@ impl NyaTermApp {
|
||||
}
|
||||
Err(error) => {
|
||||
self.terminal.view.status = format!("reorder connection failed: {error}");
|
||||
self.settings.store_status.message = self.terminal.view.status.clone();
|
||||
self.settings.store_status.ready = false;
|
||||
self.settings
|
||||
.set_store_message(self.terminal.view.status.clone());
|
||||
self.settings.set_store_ready(false);
|
||||
}
|
||||
}
|
||||
self.connection_state.clear_list_drop_target();
|
||||
@@ -139,8 +140,9 @@ impl NyaTermApp {
|
||||
}
|
||||
Err(error) => {
|
||||
self.terminal.view.status = format!("reorder connection failed: {error}");
|
||||
self.settings.store_status.message = self.terminal.view.status.clone();
|
||||
self.settings.store_status.ready = false;
|
||||
self.settings
|
||||
.set_store_message(self.terminal.view.status.clone());
|
||||
self.settings.set_store_ready(false);
|
||||
}
|
||||
}
|
||||
self.connection_state.clear_list_drop_target();
|
||||
@@ -190,8 +192,9 @@ impl NyaTermApp {
|
||||
}
|
||||
Err(error) => {
|
||||
self.terminal.view.status = format!("move connection failed: {error}");
|
||||
self.settings.store_status.message = self.terminal.view.status.clone();
|
||||
self.settings.store_status.ready = false;
|
||||
self.settings
|
||||
.set_store_message(self.terminal.view.status.clone());
|
||||
self.settings.set_store_ready(false);
|
||||
}
|
||||
}
|
||||
cx.notify();
|
||||
@@ -238,8 +241,9 @@ impl NyaTermApp {
|
||||
}
|
||||
Err(error) => {
|
||||
self.terminal.view.status = format!("move connections failed: {error}");
|
||||
self.settings.store_status.message = self.terminal.view.status.clone();
|
||||
self.settings.store_status.ready = false;
|
||||
self.settings
|
||||
.set_store_message(self.terminal.view.status.clone());
|
||||
self.settings.set_store_ready(false);
|
||||
}
|
||||
}
|
||||
cx.notify();
|
||||
|
||||
@@ -70,8 +70,9 @@ impl NyaTermApp {
|
||||
}
|
||||
Err(error) => {
|
||||
self.terminal.view.status = format!("copy connection failed: {error}");
|
||||
self.settings.store_status.message = self.terminal.view.status.clone();
|
||||
self.settings.store_status.ready = false;
|
||||
self.settings
|
||||
.set_store_message(self.terminal.view.status.clone());
|
||||
self.settings.set_store_ready(false);
|
||||
}
|
||||
}
|
||||
cx.notify();
|
||||
|
||||
@@ -54,8 +54,9 @@ impl NyaTermApp {
|
||||
}
|
||||
Err(error) => {
|
||||
self.terminal.view.status = format!("copy selected connections failed: {error}");
|
||||
self.settings.store_status.message = self.terminal.view.status.clone();
|
||||
self.settings.store_status.ready = false;
|
||||
self.settings
|
||||
.set_store_message(self.terminal.view.status.clone());
|
||||
self.settings.set_store_ready(false);
|
||||
}
|
||||
}
|
||||
cx.notify();
|
||||
@@ -94,8 +95,9 @@ impl NyaTermApp {
|
||||
.map_err(|error| error.to_string())?
|
||||
.connections,
|
||||
);
|
||||
self.settings.store_status.message = "saved connections copied".to_string();
|
||||
self.settings.store_status.ready = true;
|
||||
self.settings
|
||||
.set_store_message("saved connections copied".to_string());
|
||||
self.settings.set_store_ready(true);
|
||||
Ok(connections.len())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -358,7 +358,7 @@ impl NyaTermApp {
|
||||
div()
|
||||
.rounded_md()
|
||||
.border_1()
|
||||
.border_color(if self.settings.store_status.ready {
|
||||
.border_color(if self.settings.store_status().ready {
|
||||
rgb(palette.hover)
|
||||
} else {
|
||||
rgb(palette.hover)
|
||||
@@ -375,19 +375,19 @@ impl NyaTermApp {
|
||||
div()
|
||||
.mt_1()
|
||||
.text_sm()
|
||||
.text_color(if self.settings.store_status.ready {
|
||||
.text_color(if self.settings.store_status().ready {
|
||||
rgb(palette.success)
|
||||
} else {
|
||||
rgb(palette.danger)
|
||||
})
|
||||
.child(self.settings.store_status.message.clone()),
|
||||
.child(self.settings.store_status().message.to_string()),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.mt_2()
|
||||
.text_xs()
|
||||
.text_color(rgb(palette.text_muted))
|
||||
.child(self.settings.store_status.path.clone()),
|
||||
.child(self.settings.store_status().path.to_string()),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -331,15 +331,16 @@ impl NyaTermApp {
|
||||
{
|
||||
Ok(settings) => {
|
||||
self.apply_gpui_settings(settings);
|
||||
self.settings.store_status.message = "file explorer favorites saved".to_string();
|
||||
self.settings.store_status.ready = true;
|
||||
self.settings
|
||||
.set_store_message("file explorer favorites saved".to_string());
|
||||
self.settings.set_store_ready(true);
|
||||
}
|
||||
Err(error) => {
|
||||
self.settings.store_status.message =
|
||||
format!("file explorer favorites save failed: {error}");
|
||||
self.settings.store_status.ready = false;
|
||||
self.settings
|
||||
.set_store_message(format!("file explorer favorites save failed: {error}"));
|
||||
self.settings.set_store_ready(false);
|
||||
self.transfer
|
||||
.set_browser_status(self.settings.store_status.message.clone());
|
||||
.set_browser_status(self.settings.store_status().message.to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,10 +37,10 @@ impl SettingsMasterPasswordState {
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub(in crate::features) struct StoreStatus {
|
||||
pub path: String,
|
||||
pub message: String,
|
||||
pub ready: bool,
|
||||
pub(super) struct StoreStatus {
|
||||
pub(super) path: String,
|
||||
pub(super) message: String,
|
||||
pub(super) ready: bool,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -10,8 +10,6 @@ use crate::models::{
|
||||
TranslationSecretDraft,
|
||||
};
|
||||
|
||||
use super::StoreStatus;
|
||||
|
||||
impl NyaTermApp {
|
||||
pub(in crate::features) fn prompt_config_export(&mut self, cx: &mut Context<Self>) {
|
||||
if !self
|
||||
@@ -592,11 +590,11 @@ impl NyaTermApp {
|
||||
.set_duplicate_policy(SftpDuplicatePolicy::from_legacy_value(
|
||||
&self.settings.summary.transfer_duplicate_strategy,
|
||||
));
|
||||
self.settings.store_status = StoreStatus {
|
||||
self.settings.replace_store_status(
|
||||
path,
|
||||
message: "redb connection store online".to_string(),
|
||||
ready: true,
|
||||
};
|
||||
"redb connection store online".to_string(),
|
||||
true,
|
||||
);
|
||||
}
|
||||
Err(error) => {
|
||||
self.connection_catalog.clear_loaded();
|
||||
@@ -609,11 +607,11 @@ impl NyaTermApp {
|
||||
TranslationSettings::default(),
|
||||
TranslationSecretDraft::default(),
|
||||
);
|
||||
self.settings.store_status = StoreStatus {
|
||||
self.settings.replace_store_status(
|
||||
path,
|
||||
message: format!("failed to load sessions: {error}"),
|
||||
ready: false,
|
||||
};
|
||||
format!("failed to load sessions: {error}"),
|
||||
false,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -626,16 +624,15 @@ impl NyaTermApp {
|
||||
TranslationSettings::default(),
|
||||
TranslationSecretDraft::default(),
|
||||
);
|
||||
self.settings.store_status = StoreStatus {
|
||||
path: self
|
||||
.runtime
|
||||
self.settings.replace_store_status(
|
||||
self.runtime
|
||||
.config_dir()
|
||||
.join("nyaterm.redb")
|
||||
.display()
|
||||
.to_string(),
|
||||
message: format!("failed to open store: {error}"),
|
||||
ready: false,
|
||||
};
|
||||
format!("failed to open store: {error}"),
|
||||
false,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ mod security_state;
|
||||
mod settings_runtime;
|
||||
mod state;
|
||||
|
||||
pub(in crate::features) use catalog::StoreStatus;
|
||||
pub(in crate::features) use security_state::{
|
||||
SecurityCatalogState, SecurityFeatureFocus, SecurityFeatureState,
|
||||
};
|
||||
|
||||
@@ -17,7 +17,7 @@ pub(in crate::features) struct SettingsFeatureState {
|
||||
pub summary: AppSettingsSummary,
|
||||
pub keyword_config: KeywordHighlightConfig,
|
||||
pub master_password: SettingsMasterPasswordState,
|
||||
pub store_status: StoreStatus,
|
||||
pub(super) store_status: StoreStatus,
|
||||
search_engines: SearchEngineSettingsState,
|
||||
keyword_highlights: KeywordHighlightSettingsState,
|
||||
appearance: AppearanceSettingsState,
|
||||
@@ -39,6 +39,12 @@ pub(in crate::features) struct SettingsFeatureFocus {
|
||||
pub keybindings: FocusHandle,
|
||||
}
|
||||
|
||||
pub(in crate::features) struct StoreStatusView<'a> {
|
||||
pub path: &'a str,
|
||||
pub message: &'a str,
|
||||
pub ready: bool,
|
||||
}
|
||||
|
||||
struct SearchEngineSettingsState {
|
||||
expanded_index: Option<usize>,
|
||||
icon_picker_index: Option<usize>,
|
||||
@@ -97,7 +103,9 @@ impl SettingsFeatureState {
|
||||
pub(in crate::features) fn new(
|
||||
summary: AppSettingsSummary,
|
||||
keyword_config: KeywordHighlightConfig,
|
||||
store_status: StoreStatus,
|
||||
store_path: String,
|
||||
store_message: String,
|
||||
store_ready: bool,
|
||||
ui_font_options: Vec<String>,
|
||||
terminal_font_options: Vec<String>,
|
||||
focus: SettingsFeatureFocus,
|
||||
@@ -107,7 +115,11 @@ impl SettingsFeatureState {
|
||||
summary,
|
||||
keyword_config,
|
||||
master_password,
|
||||
store_status,
|
||||
store_status: StoreStatus {
|
||||
path: store_path,
|
||||
message: store_message,
|
||||
ready: store_ready,
|
||||
},
|
||||
search_engines: SearchEngineSettingsState {
|
||||
expanded_index: None,
|
||||
icon_picker_index: None,
|
||||
@@ -139,6 +151,35 @@ impl SettingsFeatureState {
|
||||
self.master_password.reset(self.summary.has_master_password);
|
||||
}
|
||||
|
||||
pub(in crate::features) fn store_status(&self) -> StoreStatusView<'_> {
|
||||
StoreStatusView {
|
||||
path: &self.store_status.path,
|
||||
message: &self.store_status.message,
|
||||
ready: self.store_status.ready,
|
||||
}
|
||||
}
|
||||
|
||||
pub(in crate::features) fn set_store_message(&mut self, message: impl Into<String>) {
|
||||
self.store_status.message = message.into();
|
||||
}
|
||||
|
||||
pub(in crate::features) fn set_store_ready(&mut self, ready: bool) {
|
||||
self.store_status.ready = ready;
|
||||
}
|
||||
|
||||
pub(in crate::features) fn replace_store_status(
|
||||
&mut self,
|
||||
path: String,
|
||||
message: String,
|
||||
ready: bool,
|
||||
) {
|
||||
self.store_status = StoreStatus {
|
||||
path,
|
||||
message,
|
||||
ready,
|
||||
};
|
||||
}
|
||||
|
||||
pub(in crate::features) fn search_engine_presentation(&self) -> SearchEnginePresentationState {
|
||||
SearchEnginePresentationState {
|
||||
expanded_index: self.search_engines.expanded_index,
|
||||
@@ -535,7 +576,6 @@ mod tests {
|
||||
};
|
||||
|
||||
use super::{SearchEngineMenu, SettingsFeatureFocus, SettingsFeatureState};
|
||||
use crate::features::settings::StoreStatus;
|
||||
use crate::models::{
|
||||
ConfigPathPromptKind, KeywordHighlightEditorField, SnapshotPasswordPromptKind,
|
||||
};
|
||||
@@ -546,11 +586,9 @@ mod tests {
|
||||
SettingsFeatureState::new(
|
||||
AppSettingsSummary::default(),
|
||||
KeywordHighlightConfig::default(),
|
||||
StoreStatus {
|
||||
path: String::new(),
|
||||
message: String::new(),
|
||||
ready: true,
|
||||
},
|
||||
String::new(),
|
||||
String::new(),
|
||||
true,
|
||||
vec!["Inter".to_string()],
|
||||
vec!["JetBrains Mono".to_string()],
|
||||
SettingsFeatureFocus {
|
||||
@@ -657,4 +695,26 @@ mod tests {
|
||||
assert_eq!(interaction.pending_keys, None);
|
||||
assert!(interaction.search_draft.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn settings_owner_controls_store_status_updates_and_replacement() {
|
||||
let mut state = settings_state();
|
||||
|
||||
state.set_store_message("saving settings");
|
||||
state.set_store_ready(false);
|
||||
let status = state.store_status();
|
||||
assert_eq!(status.path, "");
|
||||
assert_eq!(status.message, "saving settings");
|
||||
assert!(!status.ready);
|
||||
|
||||
state.replace_store_status(
|
||||
"/tmp/nyaterm.redb".to_string(),
|
||||
"store reopened".to_string(),
|
||||
true,
|
||||
);
|
||||
let status = state.store_status();
|
||||
assert_eq!(status.path, "/tmp/nyaterm.redb");
|
||||
assert_eq!(status.message, "store reopened");
|
||||
assert!(status.ready);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -594,15 +594,16 @@ impl NyaTermApp {
|
||||
Ok(settings) => {
|
||||
self.apply_gpui_settings(settings);
|
||||
self.refresh_visible_terminal_surfaces(cx);
|
||||
self.settings.store_status.message = "appearance settings saved".to_string();
|
||||
self.settings.store_status.ready = true;
|
||||
self.settings
|
||||
.set_store_message("appearance settings saved".to_string());
|
||||
self.settings.set_store_ready(true);
|
||||
self.terminal.view.status = "appearance settings saved".to_string();
|
||||
}
|
||||
Err(error) => {
|
||||
self.settings.store_status.message =
|
||||
format!("appearance settings save failed: {error}");
|
||||
self.settings.store_status.ready = false;
|
||||
self.terminal.view.status = self.settings.store_status.message.clone();
|
||||
self.settings
|
||||
.set_store_message(format!("appearance settings save failed: {error}"));
|
||||
self.settings.set_store_ready(false);
|
||||
self.terminal.view.status = self.settings.store_status().message.to_string();
|
||||
}
|
||||
}
|
||||
cx.notify();
|
||||
|
||||
@@ -107,14 +107,15 @@ impl NyaTermApp {
|
||||
Ok(settings) => {
|
||||
self.apply_gpui_settings(settings);
|
||||
self.settings.finish_keybinding_recording();
|
||||
self.settings.store_status.message = success_message.clone();
|
||||
self.settings.store_status.ready = true;
|
||||
self.settings.set_store_message(success_message.clone());
|
||||
self.settings.set_store_ready(true);
|
||||
self.terminal.view.status = success_message;
|
||||
}
|
||||
Err(error) => {
|
||||
self.settings.store_status.message = format!("shortcut save failed: {error}");
|
||||
self.settings.store_status.ready = false;
|
||||
self.terminal.view.status = self.settings.store_status.message.clone();
|
||||
self.settings
|
||||
.set_store_message(format!("shortcut save failed: {error}"));
|
||||
self.settings.set_store_ready(false);
|
||||
self.terminal.view.status = self.settings.store_status().message.to_string();
|
||||
}
|
||||
}
|
||||
cx.notify();
|
||||
|
||||
+13
-10
@@ -38,15 +38,16 @@ impl NyaTermApp {
|
||||
{
|
||||
Ok(config) => {
|
||||
self.settings.keyword_config = config;
|
||||
self.settings.store_status.message = "keyword highlight settings saved".to_string();
|
||||
self.settings.store_status.ready = true;
|
||||
self.settings
|
||||
.set_store_message("keyword highlight settings saved".to_string());
|
||||
self.settings.set_store_ready(true);
|
||||
self.terminal.view.status = "keyword highlight settings saved".to_string();
|
||||
}
|
||||
Err(error) => {
|
||||
self.settings.store_status.message =
|
||||
format!("keyword highlight settings save failed: {error}");
|
||||
self.settings.store_status.ready = false;
|
||||
self.terminal.view.status = self.settings.store_status.message.clone();
|
||||
self.settings
|
||||
.set_store_message(format!("keyword highlight settings save failed: {error}"));
|
||||
self.settings.set_store_ready(false);
|
||||
self.terminal.view.status = self.settings.store_status().message.to_string();
|
||||
}
|
||||
}
|
||||
cx.notify();
|
||||
@@ -130,16 +131,18 @@ impl NyaTermApp {
|
||||
self.terminal.view.status = format!(
|
||||
"imported {imported_rules} keyword highlight rule(s), updated {updated_rules}, total {total_rules}"
|
||||
);
|
||||
self.settings.store_status.message = self.terminal.view.status.clone();
|
||||
self.settings.store_status.ready = true;
|
||||
self.settings
|
||||
.set_store_message(self.terminal.view.status.clone());
|
||||
self.settings.set_store_ready(true);
|
||||
}
|
||||
KeywordHighlightPathPromptResult::Cancelled => {
|
||||
self.terminal.view.status = "keyword highlight import cancelled".to_string();
|
||||
}
|
||||
KeywordHighlightPathPromptResult::Failed(error) => {
|
||||
self.terminal.view.status = format!("keyword highlight import failed: {error}");
|
||||
self.settings.store_status.message = self.terminal.view.status.clone();
|
||||
self.settings.store_status.ready = false;
|
||||
self.settings
|
||||
.set_store_message(self.terminal.view.status.clone());
|
||||
self.settings.set_store_ready(false);
|
||||
}
|
||||
KeywordHighlightPathPromptResult::Closed => {
|
||||
self.terminal.view.status =
|
||||
|
||||
@@ -162,13 +162,14 @@ impl NyaTermApp {
|
||||
match store.save_ui_layout_settings(&self.settings.summary) {
|
||||
Ok(summary) => {
|
||||
self.apply_gpui_settings(summary);
|
||||
self.settings.store_status.ready = true;
|
||||
self.settings.store_status.message = "panel layout saved".to_string();
|
||||
self.settings.set_store_ready(true);
|
||||
self.settings
|
||||
.set_store_message("panel layout saved".to_string());
|
||||
}
|
||||
Err(error) => {
|
||||
self.settings.store_status.ready = false;
|
||||
self.settings.store_status.message =
|
||||
format!("failed to save panel layout: {error}");
|
||||
self.settings.set_store_ready(false);
|
||||
self.settings
|
||||
.set_store_message(format!("failed to save panel layout: {error}"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,13 +44,15 @@ impl NyaTermApp {
|
||||
{
|
||||
Ok(saved) => {
|
||||
self.translation.settings_saved(saved);
|
||||
self.settings.store_status.message = "translation settings saved".to_string();
|
||||
self.settings.store_status.ready = true;
|
||||
self.settings
|
||||
.set_store_message("translation settings saved".to_string());
|
||||
self.settings.set_store_ready(true);
|
||||
}
|
||||
Err(error) => {
|
||||
self.translation.settings_save_failed(error);
|
||||
self.settings.store_status.message = self.translation.status().to_string();
|
||||
self.settings.store_status.ready = false;
|
||||
self.settings
|
||||
.set_store_message(self.translation.status().to_string());
|
||||
self.settings.set_store_ready(false);
|
||||
}
|
||||
}
|
||||
cx.notify();
|
||||
|
||||
@@ -69,13 +69,15 @@ impl NyaTermApp {
|
||||
self.tunnel_state.commit_tunnels(next_tunnels);
|
||||
self.connection_state.close_network_move_picker();
|
||||
self.terminal.view.status = format!("tunnel moved to {label}");
|
||||
self.settings.store_status.message = "tunnel group saved".to_string();
|
||||
self.settings.store_status.ready = true;
|
||||
self.settings
|
||||
.set_store_message("tunnel group saved".to_string());
|
||||
self.settings.set_store_ready(true);
|
||||
}
|
||||
Err(error) => {
|
||||
self.terminal.view.status = format!("failed to move tunnel: {error}");
|
||||
self.settings.store_status.message = self.terminal.view.status.clone();
|
||||
self.settings.store_status.ready = false;
|
||||
self.settings
|
||||
.set_store_message(self.terminal.view.status.clone());
|
||||
self.settings.set_store_ready(false);
|
||||
}
|
||||
}
|
||||
cx.notify();
|
||||
@@ -117,13 +119,15 @@ impl NyaTermApp {
|
||||
self.tunnel_state.commit_proxies(next_proxies);
|
||||
self.connection_state.close_network_move_picker();
|
||||
self.terminal.view.status = format!("proxy moved to {label}");
|
||||
self.settings.store_status.message = "proxy group saved".to_string();
|
||||
self.settings.store_status.ready = true;
|
||||
self.settings
|
||||
.set_store_message("proxy group saved".to_string());
|
||||
self.settings.set_store_ready(true);
|
||||
}
|
||||
Err(error) => {
|
||||
self.terminal.view.status = format!("failed to move proxy: {error}");
|
||||
self.settings.store_status.message = self.terminal.view.status.clone();
|
||||
self.settings.store_status.ready = false;
|
||||
self.settings
|
||||
.set_store_message(self.terminal.view.status.clone());
|
||||
self.settings.set_store_ready(false);
|
||||
}
|
||||
}
|
||||
cx.notify();
|
||||
@@ -192,13 +196,15 @@ impl NyaTermApp {
|
||||
} else {
|
||||
format!("tunnel '{label}' was already deleted")
|
||||
};
|
||||
self.settings.store_status.message = self.terminal.view.status.clone();
|
||||
self.settings.store_status.ready = deleted;
|
||||
self.settings
|
||||
.set_store_message(self.terminal.view.status.clone());
|
||||
self.settings.set_store_ready(deleted);
|
||||
}
|
||||
Err(error) => {
|
||||
self.terminal.view.status = format!("failed to delete tunnel: {error}");
|
||||
self.settings.store_status.message = self.terminal.view.status.clone();
|
||||
self.settings.store_status.ready = false;
|
||||
self.settings
|
||||
.set_store_message(self.terminal.view.status.clone());
|
||||
self.settings.set_store_ready(false);
|
||||
}
|
||||
}
|
||||
cx.notify();
|
||||
@@ -226,13 +232,15 @@ impl NyaTermApp {
|
||||
} else {
|
||||
format!("proxy '{label}' was already deleted")
|
||||
};
|
||||
self.settings.store_status.message = self.terminal.view.status.clone();
|
||||
self.settings.store_status.ready = deleted;
|
||||
self.settings
|
||||
.set_store_message(self.terminal.view.status.clone());
|
||||
self.settings.set_store_ready(deleted);
|
||||
}
|
||||
Err(error) => {
|
||||
self.terminal.view.status = format!("failed to delete proxy: {error}");
|
||||
self.settings.store_status.message = self.terminal.view.status.clone();
|
||||
self.settings.store_status.ready = false;
|
||||
self.settings
|
||||
.set_store_message(self.terminal.view.status.clone());
|
||||
self.settings.set_store_ready(false);
|
||||
}
|
||||
}
|
||||
cx.notify();
|
||||
|
||||
@@ -109,13 +109,15 @@ impl NyaTermApp {
|
||||
self.tunnel_state.commit_tunnel_groups(groups);
|
||||
self.connection_state.close_network_group_editor();
|
||||
self.terminal.view.status = format!("tunnel group '{name}' saved");
|
||||
self.settings.store_status.message = self.terminal.view.status.clone();
|
||||
self.settings.store_status.ready = true;
|
||||
self.settings
|
||||
.set_store_message(self.terminal.view.status.clone());
|
||||
self.settings.set_store_ready(true);
|
||||
}
|
||||
Err(error) => {
|
||||
self.terminal.view.status = format!("failed to save tunnel group: {error}");
|
||||
self.settings.store_status.message = self.terminal.view.status.clone();
|
||||
self.settings.store_status.ready = false;
|
||||
self.settings
|
||||
.set_store_message(self.terminal.view.status.clone());
|
||||
self.settings.set_store_ready(false);
|
||||
}
|
||||
}
|
||||
cx.notify();
|
||||
@@ -146,13 +148,15 @@ impl NyaTermApp {
|
||||
self.tunnel_state.commit_proxy_groups(groups);
|
||||
self.connection_state.close_network_group_editor();
|
||||
self.terminal.view.status = format!("proxy group '{name}' saved");
|
||||
self.settings.store_status.message = self.terminal.view.status.clone();
|
||||
self.settings.store_status.ready = true;
|
||||
self.settings
|
||||
.set_store_message(self.terminal.view.status.clone());
|
||||
self.settings.set_store_ready(true);
|
||||
}
|
||||
Err(error) => {
|
||||
self.terminal.view.status = format!("failed to save proxy group: {error}");
|
||||
self.settings.store_status.message = self.terminal.view.status.clone();
|
||||
self.settings.store_status.ready = false;
|
||||
self.settings
|
||||
.set_store_message(self.terminal.view.status.clone());
|
||||
self.settings.set_store_ready(false);
|
||||
}
|
||||
}
|
||||
cx.notify();
|
||||
@@ -220,13 +224,15 @@ impl NyaTermApp {
|
||||
&deleted_tunnel_ids,
|
||||
);
|
||||
self.terminal.view.status = format!("tunnel group '{label}' deleted");
|
||||
self.settings.store_status.message = self.terminal.view.status.clone();
|
||||
self.settings.store_status.ready = true;
|
||||
self.settings
|
||||
.set_store_message(self.terminal.view.status.clone());
|
||||
self.settings.set_store_ready(true);
|
||||
}
|
||||
Err(error) => {
|
||||
self.terminal.view.status = format!("failed to delete tunnel group: {error}");
|
||||
self.settings.store_status.message = self.terminal.view.status.clone();
|
||||
self.settings.store_status.ready = false;
|
||||
self.settings
|
||||
.set_store_message(self.terminal.view.status.clone());
|
||||
self.settings.set_store_ready(false);
|
||||
}
|
||||
}
|
||||
cx.notify();
|
||||
@@ -256,13 +262,15 @@ impl NyaTermApp {
|
||||
&deleted_proxy_ids,
|
||||
);
|
||||
self.terminal.view.status = format!("proxy group '{label}' deleted");
|
||||
self.settings.store_status.message = self.terminal.view.status.clone();
|
||||
self.settings.store_status.ready = true;
|
||||
self.settings
|
||||
.set_store_message(self.terminal.view.status.clone());
|
||||
self.settings.set_store_ready(true);
|
||||
}
|
||||
Err(error) => {
|
||||
self.terminal.view.status = format!("failed to delete proxy group: {error}");
|
||||
self.settings.store_status.message = self.terminal.view.status.clone();
|
||||
self.settings.store_status.ready = false;
|
||||
self.settings
|
||||
.set_store_message(self.terminal.view.status.clone());
|
||||
self.settings.set_store_ready(false);
|
||||
}
|
||||
}
|
||||
cx.notify();
|
||||
|
||||
@@ -199,13 +199,15 @@ impl NyaTermApp {
|
||||
self.tunnel_state.commit_proxies(next_proxies);
|
||||
self.connection_state.close_network_proxy_editor();
|
||||
self.terminal.view.status = format!("proxy '{name}' saved");
|
||||
self.settings.store_status.message = self.terminal.view.status.clone();
|
||||
self.settings.store_status.ready = true;
|
||||
self.settings
|
||||
.set_store_message(self.terminal.view.status.clone());
|
||||
self.settings.set_store_ready(true);
|
||||
}
|
||||
Err(error) => {
|
||||
self.terminal.view.status = format!("failed to save proxy: {error}");
|
||||
self.settings.store_status.message = self.terminal.view.status.clone();
|
||||
self.settings.store_status.ready = false;
|
||||
self.settings
|
||||
.set_store_message(self.terminal.view.status.clone());
|
||||
self.settings.set_store_ready(false);
|
||||
self.connection_state
|
||||
.set_network_proxy_editor_error(self.terminal.view.status.clone());
|
||||
}
|
||||
|
||||
@@ -254,13 +254,15 @@ impl NyaTermApp {
|
||||
self.tunnel_state.commit_tunnels(next_tunnels);
|
||||
self.connection_state.close_network_tunnel_editor();
|
||||
self.terminal.view.status = format!("tunnel '{name}' saved");
|
||||
self.settings.store_status.message = self.terminal.view.status.clone();
|
||||
self.settings.store_status.ready = true;
|
||||
self.settings
|
||||
.set_store_message(self.terminal.view.status.clone());
|
||||
self.settings.set_store_ready(true);
|
||||
}
|
||||
Err(error) => {
|
||||
self.terminal.view.status = format!("failed to save tunnel: {error}");
|
||||
self.settings.store_status.message = self.terminal.view.status.clone();
|
||||
self.settings.store_status.ready = false;
|
||||
self.settings
|
||||
.set_store_message(self.terminal.view.status.clone());
|
||||
self.settings.set_store_ready(false);
|
||||
self.connection_state
|
||||
.set_network_tunnel_editor_error(self.terminal.view.status.clone());
|
||||
}
|
||||
|
||||
@@ -232,7 +232,11 @@ these as staged extraction candidates, not as formatting-only refactor targets.
|
||||
reconciliation, keyword expansion/edit lifecycle, appearance-menu exclusion,
|
||||
keybinding recording/search transitions and kind-matched prompt completion
|
||||
execute on `SettingsFeatureState`; views receive immutable presentation data
|
||||
and focus handles. Filesystem prompts, persistence and GPUI notification stay
|
||||
and focus handles. A storage-status follow-up made the implementation type
|
||||
and backing child settings-module-private. Cross-domain persistence adapters
|
||||
now update its message/readiness through owner methods, rendering receives a
|
||||
borrowed immutable view, and store reopen replaces path/message/readiness as
|
||||
one transition. Filesystem prompts, persistence and GPUI notification stay
|
||||
in their existing adapters.
|
||||
- Translation and native-update background state now have authoritative
|
||||
`TranslationFeatureState` and `UpdateFeatureState` owners. Eighteen app fields
|
||||
@@ -1487,6 +1491,7 @@ Current ownership map:
|
||||
| Command history and persistence worker | Private state in `NyaTermApp.commands` | Persisted catalog plus background runtime | History snapshots, queue admission, event polling and idle checks enter through `CommandFeatureState`; failed optimistic use-count updates roll back on the owner. |
|
||||
| Send-command composer/options/progress | Private children in `NyaTermApp.send_command` | Transient editor and send lifecycle | Views receive immutable presentation data; control edits, mutually-exclusive menus, data/mode defaults, progress counters and cancellation enter through `SendCommandFeatureState`. Session selection, terminal writes, GPUI/text-input routing and status remain in adapters. |
|
||||
| Settings interaction and prompts | Private children in `NyaTermApp.settings` | Transient settings UI and prompt lifecycle | Search-engine rows, keyword-highlight editing, appearance menus, keybinding recording/search and config/diagnostics/import/password prompt admission enter through `SettingsFeatureState`; views use immutable presentation values and read-only focus/font access. Persistence, native filesystem prompts, text inputs and GPUI notification remain in adapters. |
|
||||
| Global storage status | Settings-module-private child in `NyaTermApp.settings` | Runtime persistence health/presentation state | Cross-domain persistence adapters update message/readiness through `SettingsFeatureState`; rendering receives a borrowed immutable view, while store reopen replaces path/message/readiness together. Database work and compatibility handling remain in existing adapters and `nyaterm-core`. |
|
||||
| AI settings/chat/history/discovery/agent/panel | AI-module-private children in `NyaTermApp.ai` | Persisted settings plus transient UI and background lifecycle | Desktop consumers use read-only slices/queries and semantic transitions; settings draft groups, menu exclusion, confirmations, request/focus preparation, detected-error throttling, picker clamping and Agent capture/reset enter through `AiFeatureState`. Persistence, terminal-context collection, GPUI focus/rendering and notification remain in adapters. |
|
||||
| Shell viewport/navigation/panels/chrome/workspace | Shell-module-private children in `NyaTermApp.shell` | Transient GPUI composition and interaction state | Other desktop modules use read-only geometry/navigation/pane queries and semantic transitions; menu exclusion, settings-window lifecycle, mobile panels, failure chrome, submenu paths and pane ownership update through `ShellFeatureState`. Persistence, rendering, GPUI windows/notification and terminal coordination remain in adapters. |
|
||||
| Remote Docker/process/stats panes | Private children in `NyaTermApp.remote_ops` | Transient UI state plus typed background-event lifecycle | Views use immutable presentation values; menu exclusion, list-offset clamping, Docker details/Compose/confirmation cleanup, process PID-scoped cleanup, Stats expansion/data and job identity/failure timing enter through `RemoteOpsFeatureState`. SSH service launch, active-session policy, terminal status mirroring and GPUI notification remain in adapters. |
|
||||
@@ -1746,6 +1751,10 @@ honest remaining list.
|
||||
cross-domain consumers receive a borrowed immutable view, and navigation,
|
||||
session cache, history/favorites, search/sort, path editing, selection/rename,
|
||||
menu and resize transitions moved onto `TransferFeatureState`.
|
||||
The settings storage-status batch then made the backing child and
|
||||
implementation type settings-module-private, moved cross-domain status
|
||||
writes behind owner transitions, and gave rendering a borrowed immutable
|
||||
view without changing storage execution or compatibility formats.
|
||||
What remains at the
|
||||
composition root is stores, runtime and focused feature owners.
|
||||
Group by cohesion where a cluster exists; do not force the count down for
|
||||
|
||||
@@ -251,6 +251,23 @@ check_no_multiline_matches \
|
||||
"settings interaction child access must use SettingsFeatureState methods" \
|
||||
'(self|this|app)\.settings[[:space:]]*\.(search_engines|keyword_highlights|appearance|keybindings|prompts)(\.|[[:space:]]*=)' \
|
||||
crates/nyaterm-desktop/src/features
|
||||
check_no_multiline_matches \
|
||||
"SettingsFeatureState store status must stay inside the settings module" \
|
||||
'struct[[:space:]]+SettingsFeatureState[[:space:]]*\{[^}]*pub([[:space:]]|\(crate\)|\(in crate\)|\(in crate::features\))[[:space:]]+store_status[[:space:]]*:' \
|
||||
crates/nyaterm-desktop/src/features/settings/state.rs
|
||||
check_no_matches \
|
||||
"StoreStatus implementation must stay inside the settings module" \
|
||||
'pub([[:space:]]|\(crate\)|\(in crate\)|\(in crate::features\))[[:space:]]+struct[[:space:]]+StoreStatus' \
|
||||
crates/nyaterm-desktop/src/features/settings/catalog.rs
|
||||
check_no_matches \
|
||||
"StoreStatus implementation must not be re-exported from settings" \
|
||||
'pub([^;]*)use([^;]*)StoreStatus' \
|
||||
crates/nyaterm-desktop/src/features/settings/mod.rs
|
||||
check_no_multiline_matches_excluding \
|
||||
"settings store status access must use SettingsFeatureState methods outside settings" \
|
||||
'(self|this|app)\.settings[[:space:]]*\.[[:space:]]*store_status[[:space:]]*(\.|=)' \
|
||||
crates/nyaterm-desktop/src/features \
|
||||
'crates/nyaterm-desktop/src/features/settings/**'
|
||||
|
||||
check_no_matches \
|
||||
"translation state must stay grouped under TranslationFeatureState" \
|
||||
|
||||
Reference in New Issue
Block a user