separate window for doll editor
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
"$schema": "../gen/schemas/desktop-schema.json",
|
||||
"identifier": "default",
|
||||
"description": "Capability for the main window",
|
||||
"windows": ["main", "scene", "app_menu"],
|
||||
"windows": ["main", "scene", "app_menu", "doll_editor"],
|
||||
"permissions": [
|
||||
"core:default",
|
||||
"opener:default",
|
||||
|
||||
@@ -7,6 +7,7 @@ use crate::{
|
||||
},
|
||||
remotes::user::UserRemote,
|
||||
services::cursor::start_cursor_tracking,
|
||||
services::doll_editor::open_doll_editor_window,
|
||||
state::{init_app_data, FDOLL},
|
||||
};
|
||||
use tauri::async_runtime;
|
||||
@@ -188,6 +189,14 @@ async fn get_dolls() -> Result<Vec<DollDto>, String> {
|
||||
.map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
async fn get_doll(id: String) -> Result<DollDto, String> {
|
||||
DollsRemote::new()
|
||||
.get_doll(&id)
|
||||
.await
|
||||
.map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
async fn create_doll(dto: CreateDollDto) -> Result<DollDto, String> {
|
||||
DollsRemote::new()
|
||||
@@ -268,13 +277,15 @@ pub fn run() {
|
||||
deny_friend_request,
|
||||
unfriend,
|
||||
get_dolls,
|
||||
get_doll,
|
||||
create_doll,
|
||||
update_doll,
|
||||
delete_doll,
|
||||
set_active_doll,
|
||||
remove_active_doll,
|
||||
recolor_gif_base64,
|
||||
quit_app
|
||||
quit_app,
|
||||
open_doll_editor_window
|
||||
])
|
||||
.setup(|app| {
|
||||
APP_HANDLE
|
||||
|
||||
@@ -105,6 +105,30 @@ impl DollsRemote {
|
||||
Ok(dolls)
|
||||
}
|
||||
|
||||
pub async fn get_doll(&self, id: &str) -> Result<DollDto, RemoteError> {
|
||||
let url = format!("{}/dolls/{}", self.base_url, id);
|
||||
tracing::info!("DollsRemote::get_doll - Sending GET request to URL: {}", url);
|
||||
|
||||
let resp = with_auth(self.client.get(url)).await.send().await?;
|
||||
|
||||
let resp = resp.error_for_status().map_err(|e| {
|
||||
tracing::error!("DollsRemote::get_doll - HTTP error: {}", e);
|
||||
e
|
||||
})?;
|
||||
|
||||
let text = resp.text().await.map_err(|e| {
|
||||
tracing::error!("DollsRemote::get_doll - Failed to read response text: {}", e);
|
||||
e
|
||||
})?;
|
||||
|
||||
let doll: DollDto = serde_json::from_str(&text).map_err(|e| {
|
||||
tracing::error!("DollsRemote::get_doll - Failed to parse JSON: {}", e);
|
||||
e
|
||||
})?;
|
||||
|
||||
Ok(doll)
|
||||
}
|
||||
|
||||
pub async fn create_doll(&self, dto: CreateDollDto) -> Result<DollDto, RemoteError> {
|
||||
let url = format!("{}/dolls", self.base_url);
|
||||
tracing::info!("DollsRemote::create_doll - Sending POST request to URL: {}", url);
|
||||
|
||||
85
src-tauri/src/services/doll_editor.rs
Normal file
85
src-tauri/src/services/doll_editor.rs
Normal file
@@ -0,0 +1,85 @@
|
||||
use tauri::{Emitter, Manager};
|
||||
use tracing::{error, info};
|
||||
|
||||
use crate::get_app_handle;
|
||||
|
||||
static DOLL_EDITOR_WINDOW_LABEL: &str = "doll_editor";
|
||||
static APP_MENU_WINDOW_LABEL: &str = "app_menu";
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn open_doll_editor_window(doll_id: Option<String>) {
|
||||
let app_handle = get_app_handle().clone();
|
||||
|
||||
// Dispatch to main thread to avoid potential deadlocks on Windows when setting parent window
|
||||
let _ = app_handle.run_on_main_thread(move || {
|
||||
let app_handle = get_app_handle();
|
||||
|
||||
// Check if the window already exists
|
||||
let existing_window = app_handle.get_webview_window(DOLL_EDITOR_WINDOW_LABEL);
|
||||
if let Some(window) = existing_window {
|
||||
// If it exists, we might want to reload it with new params or just focus it
|
||||
if let Err(e) = window.set_focus() {
|
||||
error!("Failed to focus existing doll editor window: {}", e);
|
||||
}
|
||||
|
||||
// Emit event to update context
|
||||
if let Some(id) = doll_id {
|
||||
if let Err(e) = window.emit("edit-doll", id) {
|
||||
error!("Failed to emit edit-doll event: {}", e);
|
||||
}
|
||||
} else {
|
||||
if let Err(e) = window.emit("create-doll", ()) {
|
||||
error!("Failed to emit create-doll event: {}", e);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
let url_path = if let Some(id) = doll_id {
|
||||
format!("/app-menu/tabs/your-dolls/doll-editor?id={}", id)
|
||||
} else {
|
||||
"/app-menu/tabs/your-dolls/doll-editor".to_string()
|
||||
};
|
||||
|
||||
let mut builder = tauri::WebviewWindowBuilder::new(
|
||||
app_handle,
|
||||
DOLL_EDITOR_WINDOW_LABEL,
|
||||
tauri::WebviewUrl::App(url_path.into()),
|
||||
)
|
||||
.title("Doll Editor")
|
||||
.inner_size(300.0, 400.0)
|
||||
.resizable(false)
|
||||
.decorations(true)
|
||||
.transparent(true)
|
||||
.shadow(true)
|
||||
.visible(true)
|
||||
.skip_taskbar(false)
|
||||
.always_on_top(true) // Helper window, nice to stay on top
|
||||
.visible_on_all_workspaces(false);
|
||||
|
||||
// Set parent if app menu exists
|
||||
if let Some(parent) = app_handle.get_webview_window(APP_MENU_WINDOW_LABEL) {
|
||||
match builder.parent(&parent) {
|
||||
Ok(b) => builder = b,
|
||||
Err(e) => {
|
||||
error!("Failed to set parent for doll editor window: {}", e);
|
||||
// If we fail to set parent, we effectively lost the builder because .parent() consumes it.
|
||||
// We must return here to avoid using moved value.
|
||||
return;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
match builder.build() {
|
||||
Ok(window) => {
|
||||
info!("{} window builder succeeded", DOLL_EDITOR_WINDOW_LABEL);
|
||||
#[cfg(debug_assertions)]
|
||||
window.open_devtools();
|
||||
}
|
||||
Err(e) => {
|
||||
error!("Failed to build {} window: {}", DOLL_EDITOR_WINDOW_LABEL, e);
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
pub mod app_menu;
|
||||
pub mod auth;
|
||||
pub mod cursor;
|
||||
pub mod doll_editor;
|
||||
pub mod scene;
|
||||
pub mod sprite_recolor;
|
||||
pub mod ws;
|
||||
|
||||
@@ -39,6 +39,9 @@ impl WS_EVENT {
|
||||
pub const FRIEND_DOLL_CREATED: &str = "friend-doll-created";
|
||||
pub const FRIEND_DOLL_UPDATED: &str = "friend-doll-updated";
|
||||
pub const FRIEND_DOLL_DELETED: &str = "friend-doll-deleted";
|
||||
pub const DOLL_CREATED: &str = "doll.created";
|
||||
pub const DOLL_UPDATED: &str = "doll.updated";
|
||||
pub const DOLL_DELETED: &str = "doll.deleted";
|
||||
}
|
||||
|
||||
fn on_friend_request_received(payload: Payload, _socket: RawClient) {
|
||||
@@ -184,6 +187,54 @@ fn on_friend_doll_deleted(payload: Payload, _socket: RawClient) {
|
||||
}
|
||||
}
|
||||
|
||||
fn on_doll_created(payload: Payload, _socket: RawClient) {
|
||||
match payload {
|
||||
Payload::Text(values) => {
|
||||
if let Some(first_value) = values.first() {
|
||||
info!("Received doll.created event: {:?}", first_value);
|
||||
if let Err(e) = get_app_handle().emit(WS_EVENT::DOLL_CREATED, first_value) {
|
||||
error!("Failed to emit doll.created event: {:?}", e);
|
||||
}
|
||||
} else {
|
||||
info!("Received doll.created event with empty payload");
|
||||
}
|
||||
}
|
||||
_ => error!("Received unexpected payload format for doll.created"),
|
||||
}
|
||||
}
|
||||
|
||||
fn on_doll_updated(payload: Payload, _socket: RawClient) {
|
||||
match payload {
|
||||
Payload::Text(values) => {
|
||||
if let Some(first_value) = values.first() {
|
||||
info!("Received doll.updated event: {:?}", first_value);
|
||||
if let Err(e) = get_app_handle().emit(WS_EVENT::DOLL_UPDATED, first_value) {
|
||||
error!("Failed to emit doll.updated event: {:?}", e);
|
||||
}
|
||||
} else {
|
||||
info!("Received doll.updated event with empty payload");
|
||||
}
|
||||
}
|
||||
_ => error!("Received unexpected payload format for doll.updated"),
|
||||
}
|
||||
}
|
||||
|
||||
fn on_doll_deleted(payload: Payload, _socket: RawClient) {
|
||||
match payload {
|
||||
Payload::Text(values) => {
|
||||
if let Some(first_value) = values.first() {
|
||||
info!("Received doll.deleted event: {:?}", first_value);
|
||||
if let Err(e) = get_app_handle().emit(WS_EVENT::DOLL_DELETED, first_value) {
|
||||
error!("Failed to emit doll.deleted event: {:?}", e);
|
||||
}
|
||||
} else {
|
||||
info!("Received doll.deleted event with empty payload");
|
||||
}
|
||||
}
|
||||
_ => error!("Received unexpected payload format for doll.deleted"),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn report_cursor_data(cursor_position: CursorPosition) {
|
||||
// Only attempt to get clients if lock_r succeeds (it should, but safety first)
|
||||
// and if clients are actually initialized.
|
||||
@@ -272,6 +323,9 @@ pub async fn build_ws_client(
|
||||
.on(WS_EVENT::FRIEND_DOLL_CREATED, on_friend_doll_created)
|
||||
.on(WS_EVENT::FRIEND_DOLL_UPDATED, on_friend_doll_updated)
|
||||
.on(WS_EVENT::FRIEND_DOLL_DELETED, on_friend_doll_deleted)
|
||||
.on(WS_EVENT::DOLL_CREATED, on_doll_created)
|
||||
.on(WS_EVENT::DOLL_UPDATED, on_doll_updated)
|
||||
.on(WS_EVENT::DOLL_DELETED, on_doll_deleted)
|
||||
.auth(json!({ "token": token }))
|
||||
.connect()
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user