Mountain/Environment/
OutputProvider.rs

1//! # OutputProvider Implementation
2//!
3//! Implements the `OutputChannelManager` trait for the `MountainEnvironment`.
4//! This provider contains the core logic for managing output channels,
5//! including state management and emitting events to the `Sky` frontend for UI
6//! updates.
7
8#![allow(non_snake_case, non_camel_case_types)]
9
10use Common::{Error::CommonError::CommonError, Output::OutputChannelManager::OutputChannelManager};
11use async_trait::async_trait;
12use log::{info, trace, warn};
13use serde_json::json;
14use tauri::Emitter;
15
16use super::{MountainEnvironment::MountainEnvironment, Utility};
17use crate::ApplicationState::DTO::OutputChannelStateDTO::OutputChannelStateDTO;
18
19#[async_trait]
20impl OutputChannelManager for MountainEnvironment {
21	/// Registers a new output channel.
22	async fn RegisterChannel(&self, Name:String, LanguageIdentifier:Option<String>) -> Result<String, CommonError> {
23		info!("[OutputProvider] Registering channel: '{}'", Name);
24
25		let ChannelIdentifier = Name.clone();
26
27		let mut ChannelsGuard = self
28			.ApplicationState
29			.OutputChannels
30			.lock()
31			.map_err(Utility::MapApplicationStateLockErrorToCommonError)?;
32
33		ChannelsGuard
34			.entry(ChannelIdentifier.clone())
35			.or_insert_with(|| OutputChannelStateDTO::Create(&Name, LanguageIdentifier.clone()));
36
37		drop(ChannelsGuard);
38
39		let EventPayload = json!({ "Id": ChannelIdentifier, "Name": Name, "LanguageId": LanguageIdentifier });
40
41		self.ApplicationHandle
42			.emit("sky://output/create", EventPayload)
43			.map_err(|Error| CommonError::UserInterfaceInteraction { Reason:Error.to_string() })?;
44
45		Ok(ChannelIdentifier)
46	}
47
48	/// Appends text to an output channel.
49	async fn Append(&self, ChannelIdentifier:String, Value:String) -> Result<(), CommonError> {
50		trace!("[OutputProvider] Appending to channel: '{}'", ChannelIdentifier);
51
52		let mut ChannelsGuard = self
53			.ApplicationState
54			.OutputChannels
55			.lock()
56			.map_err(Utility::MapApplicationStateLockErrorToCommonError)?;
57
58		if let Some(ChannelState) = ChannelsGuard.get_mut(&ChannelIdentifier) {
59			ChannelState.Buffer.push_str(&Value);
60
61			let EventPayload = json!({ "Id": ChannelIdentifier, "AppendedText": Value });
62
63			self.ApplicationHandle
64				.emit("sky://output/append", EventPayload)
65				.map_err(|Error| CommonError::UserInterfaceInteraction { Reason:Error.to_string() })?;
66		} else {
67			warn!("[OutputProvider] Channel '{}' not found for append.", ChannelIdentifier);
68		}
69
70		Ok(())
71	}
72
73	/// Replaces the entire content of an output channel.
74	async fn Replace(&self, ChannelIdentifier:String, Value:String) -> Result<(), CommonError> {
75		info!("[OutputProvider] Replacing content of channel: '{}'", ChannelIdentifier);
76
77		let mut ChannelsGuard = self
78			.ApplicationState
79			.OutputChannels
80			.lock()
81			.map_err(Utility::MapApplicationStateLockErrorToCommonError)?;
82
83		if let Some(ChannelState) = ChannelsGuard.get_mut(&ChannelIdentifier) {
84			ChannelState.Buffer = Value.clone();
85
86			let EventPayload = json!({ "Id": ChannelIdentifier, "Content": Value });
87
88			self.ApplicationHandle
89				.emit("sky://output/replace", EventPayload)
90				.map_err(|Error| CommonError::UserInterfaceInteraction { Reason:Error.to_string() })?;
91		} else {
92			warn!("[OutputProvider] Channel '{}' not found for replace.", ChannelIdentifier);
93		}
94
95		Ok(())
96	}
97
98	/// Clears all content from an output channel.
99	async fn Clear(&self, ChannelIdentifier:String) -> Result<(), CommonError> {
100		info!("[OutputProvider] Clearing channel: '{}'", ChannelIdentifier);
101
102		let mut ChannelsGuard = self
103			.ApplicationState
104			.OutputChannels
105			.lock()
106			.map_err(Utility::MapApplicationStateLockErrorToCommonError)?;
107
108		if let Some(ChannelState) = ChannelsGuard.get_mut(&ChannelIdentifier) {
109			ChannelState.Buffer.clear();
110
111			self.ApplicationHandle
112				.emit("sky://output/clear", json!({ "Id": ChannelIdentifier }))
113				.map_err(|Error| CommonError::UserInterfaceInteraction { Reason:Error.to_string() })?;
114		} else {
115			warn!("[OutputProvider] Channel '{}' not found for clear.", ChannelIdentifier);
116		}
117
118		Ok(())
119	}
120
121	/// Reveals an output channel in the UI.
122	async fn Reveal(&self, ChannelIdentifier:String, PreserveFocus:bool) -> Result<(), CommonError> {
123		info!("[OutputProvider] Revealing channel: '{}'", ChannelIdentifier);
124
125		let mut ChannelsGuard = self
126			.ApplicationState
127			.OutputChannels
128			.lock()
129			.map_err(Utility::MapApplicationStateLockErrorToCommonError)?;
130
131		if let Some(ChannelState) = ChannelsGuard.get_mut(&ChannelIdentifier) {
132			ChannelState.IsVisible = true;
133
134			let EventPayload = json!({ "Id": ChannelIdentifier, "PreserveFocus": PreserveFocus });
135
136			self.ApplicationHandle
137				.emit("sky://output/reveal", EventPayload)
138				.map_err(|Error| CommonError::UserInterfaceInteraction { Reason:Error.to_string() })?;
139		} else {
140			warn!("[OutputProvider] Channel '{}' not found for reveal.", ChannelIdentifier);
141		}
142
143		Ok(())
144	}
145
146	/// Closes the view of an output channel in the UI.
147	async fn Close(&self, _ChannelIdentifier:String) -> Result<(), CommonError> {
148		warn!("[OutputProvider] Close is not fully implemented.");
149
150		Ok(())
151	}
152
153	/// Disposes of an output channel permanently.
154	async fn Dispose(&self, ChannelIdentifier:String) -> Result<(), CommonError> {
155		info!("[OutputProvider] Disposing channel: '{}'", ChannelIdentifier);
156
157		self.ApplicationState
158			.OutputChannels
159			.lock()
160			.map_err(Utility::MapApplicationStateLockErrorToCommonError)?
161			.remove(&ChannelIdentifier);
162
163		self.ApplicationHandle
164			.emit("sky://output/dispose", json!({ "Id": ChannelIdentifier }))
165			.map_err(|Error| CommonError::UserInterfaceInteraction { Reason:Error.to_string() })
166	}
167}