mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-04-24 09:38:29 +02:00
Some cleanup around window creation
This commit is contained in:
@@ -12,7 +12,6 @@ use crate::uri_scheme::handle_uri_scheme;
|
|||||||
use error::Result as YaakResult;
|
use error::Result as YaakResult;
|
||||||
use eventsource_client::{EventParser, SSE};
|
use eventsource_client::{EventParser, SSE};
|
||||||
use log::{debug, error, warn};
|
use log::{debug, error, warn};
|
||||||
use rand::random;
|
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use std::collections::{BTreeMap, HashMap};
|
use std::collections::{BTreeMap, HashMap};
|
||||||
use std::fs::{create_dir_all, File};
|
use std::fs::{create_dir_all, File};
|
||||||
@@ -20,7 +19,7 @@ use std::path::PathBuf;
|
|||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use std::{fs, panic};
|
use std::{fs, panic};
|
||||||
use tauri::{AppHandle, Emitter, RunEvent, State, WebviewWindow};
|
use tauri::{is_dev, AppHandle, Emitter, RunEvent, State, WebviewWindow};
|
||||||
use tauri::{Listener, Runtime};
|
use tauri::{Listener, Runtime};
|
||||||
use tauri::{Manager, WindowEvent};
|
use tauri::{Manager, WindowEvent};
|
||||||
use tauri_plugin_log::fern::colors::ColoredLevelConfig;
|
use tauri_plugin_log::fern::colors::ColoredLevelConfig;
|
||||||
@@ -68,6 +67,7 @@ use yaak_sse::sse::ServerSentEvent;
|
|||||||
use yaak_templates::format::format_json;
|
use yaak_templates::format::format_json;
|
||||||
use yaak_templates::{Parser, Tokens};
|
use yaak_templates::{Parser, Tokens};
|
||||||
|
|
||||||
|
mod commands;
|
||||||
mod encoding;
|
mod encoding;
|
||||||
mod error;
|
mod error;
|
||||||
mod grpc;
|
mod grpc;
|
||||||
@@ -83,15 +83,6 @@ mod uri_scheme;
|
|||||||
mod window;
|
mod window;
|
||||||
mod window_menu;
|
mod window_menu;
|
||||||
|
|
||||||
const DEFAULT_WINDOW_WIDTH: f64 = 1100.0;
|
|
||||||
const DEFAULT_WINDOW_HEIGHT: f64 = 600.0;
|
|
||||||
|
|
||||||
const MIN_WINDOW_WIDTH: f64 = 300.0;
|
|
||||||
const MIN_WINDOW_HEIGHT: f64 = 300.0;
|
|
||||||
|
|
||||||
const MAIN_WINDOW_PREFIX: &str = "main_";
|
|
||||||
const OTHER_WINDOW_PREFIX: &str = "other_";
|
|
||||||
|
|
||||||
#[derive(serde::Serialize)]
|
#[derive(serde::Serialize)]
|
||||||
#[serde(default, rename_all = "camelCase")]
|
#[serde(default, rename_all = "camelCase")]
|
||||||
struct AppMetaData {
|
struct AppMetaData {
|
||||||
@@ -1368,15 +1359,6 @@ async fn cmd_update_folder(folder: Folder, w: WebviewWindow) -> Result<Folder, S
|
|||||||
upsert_folder(&w, folder, &UpdateSource::Window).await.map_err(|e| e.to_string())
|
upsert_folder(&w, folder, &UpdateSource::Window).await.map_err(|e| e.to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
|
||||||
async fn cmd_write_file_dev(pathname: &str, contents: &str) -> Result<(), String> {
|
|
||||||
if !is_dev() {
|
|
||||||
panic!("Cannot write arbitrary files when not in dev mode");
|
|
||||||
}
|
|
||||||
|
|
||||||
fs::write(pathname, contents).map_err(|e| e.to_string())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
async fn cmd_delete_folder(w: WebviewWindow, folder_id: &str) -> Result<Folder, String> {
|
async fn cmd_delete_folder(w: WebviewWindow, folder_id: &str) -> Result<Folder, String> {
|
||||||
delete_folder(&w, folder_id, &UpdateSource::Window).await.map_err(|e| e.to_string())
|
delete_folder(&w, folder_id, &UpdateSource::Window).await.map_err(|e| e.to_string())
|
||||||
@@ -1632,72 +1614,13 @@ async fn cmd_new_child_window(
|
|||||||
title: &str,
|
title: &str,
|
||||||
inner_size: (f64, f64),
|
inner_size: (f64, f64),
|
||||||
) -> Result<(), String> {
|
) -> Result<(), String> {
|
||||||
let app_handle = parent_window.app_handle();
|
window::create_child_window(&parent_window, url, label, title, inner_size);
|
||||||
let label = format!("{OTHER_WINDOW_PREFIX}_{label}");
|
|
||||||
let scale_factor = parent_window.scale_factor().unwrap();
|
|
||||||
|
|
||||||
let current_pos = parent_window.inner_position().unwrap().to_logical::<f64>(scale_factor);
|
|
||||||
let current_size = parent_window.inner_size().unwrap().to_logical::<f64>(scale_factor);
|
|
||||||
|
|
||||||
// Position the new window in the middle of the parent
|
|
||||||
let position = (
|
|
||||||
current_pos.x + current_size.width / 2.0 - inner_size.0 / 2.0,
|
|
||||||
current_pos.y + current_size.height / 2.0 - inner_size.1 / 2.0,
|
|
||||||
);
|
|
||||||
|
|
||||||
let config = window::CreateWindowConfig {
|
|
||||||
label: label.as_str(),
|
|
||||||
title,
|
|
||||||
url,
|
|
||||||
inner_size: Some(inner_size),
|
|
||||||
position: Some(position),
|
|
||||||
hide_titlebar: true,
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
let child_window = window::create_window(&app_handle, config);
|
|
||||||
|
|
||||||
// NOTE: These listeners will remain active even when the windows close. Unfortunately,
|
|
||||||
// there's no way to unlisten to events for now, so we just have to be defensive.
|
|
||||||
|
|
||||||
{
|
|
||||||
let parent_window = parent_window.clone();
|
|
||||||
let child_window = child_window.clone();
|
|
||||||
child_window.clone().on_window_event(move |e| match e {
|
|
||||||
// When the new window is destroyed, bring the other up behind it
|
|
||||||
WindowEvent::Destroyed => {
|
|
||||||
if let Some(w) = parent_window.get_webview_window(child_window.label()) {
|
|
||||||
w.set_focus().unwrap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
let parent_window = parent_window.clone();
|
|
||||||
let child_window = child_window.clone();
|
|
||||||
parent_window.clone().on_window_event(move |e| match e {
|
|
||||||
// When the parent window is closed, close the child
|
|
||||||
WindowEvent::CloseRequested { .. } => child_window.destroy().unwrap(),
|
|
||||||
// When the parent window is focused, bring the child above
|
|
||||||
WindowEvent::Focused(focus) => {
|
|
||||||
if *focus {
|
|
||||||
if let Some(w) = parent_window.get_webview_window(child_window.label()) {
|
|
||||||
w.set_focus().unwrap();
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
async fn cmd_new_main_window(app_handle: AppHandle, url: &str) -> Result<(), String> {
|
async fn cmd_new_main_window(app_handle: AppHandle, url: &str) -> Result<(), String> {
|
||||||
create_main_window(&app_handle, url);
|
window::create_main_window(&app_handle, url);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1724,33 +1647,6 @@ async fn cmd_check_for_updates(
|
|||||||
pub fn run() {
|
pub fn run() {
|
||||||
#[allow(unused_mut)]
|
#[allow(unused_mut)]
|
||||||
let mut builder = tauri::Builder::default()
|
let mut builder = tauri::Builder::default()
|
||||||
.plugin(
|
|
||||||
Builder::default()
|
|
||||||
.targets([
|
|
||||||
Target::new(TargetKind::Stdout),
|
|
||||||
Target::new(TargetKind::LogDir { file_name: None }),
|
|
||||||
Target::new(TargetKind::Webview),
|
|
||||||
])
|
|
||||||
.level_for("plugin_runtime", log::LevelFilter::Info)
|
|
||||||
.level_for("cookie_store", log::LevelFilter::Info)
|
|
||||||
.level_for("eventsource_client::event_parser", log::LevelFilter::Info)
|
|
||||||
.level_for("h2", log::LevelFilter::Info)
|
|
||||||
.level_for("hyper", log::LevelFilter::Info)
|
|
||||||
.level_for("hyper_util", log::LevelFilter::Info)
|
|
||||||
.level_for("hyper_rustls", log::LevelFilter::Info)
|
|
||||||
.level_for("reqwest", log::LevelFilter::Info)
|
|
||||||
.level_for("sqlx", log::LevelFilter::Warn)
|
|
||||||
.level_for("tao", log::LevelFilter::Info)
|
|
||||||
.level_for("tokio_util", log::LevelFilter::Info)
|
|
||||||
.level_for("tonic", log::LevelFilter::Info)
|
|
||||||
.level_for("tower", log::LevelFilter::Info)
|
|
||||||
.level_for("tracing", log::LevelFilter::Warn)
|
|
||||||
.level_for("swc_ecma_codegen", log::LevelFilter::Off)
|
|
||||||
.level_for("swc_ecma_transforms_base", log::LevelFilter::Off)
|
|
||||||
.with_colors(ColoredLevelConfig::default())
|
|
||||||
.level(if is_dev() { log::LevelFilter::Debug } else { log::LevelFilter::Info })
|
|
||||||
.build(),
|
|
||||||
)
|
|
||||||
.plugin(
|
.plugin(
|
||||||
Builder::default()
|
Builder::default()
|
||||||
.targets([
|
.targets([
|
||||||
@@ -1905,7 +1801,6 @@ pub fn run() {
|
|||||||
cmd_update_settings,
|
cmd_update_settings,
|
||||||
cmd_update_workspace,
|
cmd_update_workspace,
|
||||||
cmd_update_workspace_meta,
|
cmd_update_workspace_meta,
|
||||||
cmd_write_file_dev,
|
|
||||||
])
|
])
|
||||||
.register_uri_scheme_protocol("yaak", handle_uri_scheme)
|
.register_uri_scheme_protocol("yaak", handle_uri_scheme)
|
||||||
.build(tauri::generate_context!())
|
.build(tauri::generate_context!())
|
||||||
@@ -1913,7 +1808,7 @@ pub fn run() {
|
|||||||
.run(|app_handle, event| {
|
.run(|app_handle, event| {
|
||||||
match event {
|
match event {
|
||||||
RunEvent::Ready => {
|
RunEvent::Ready => {
|
||||||
let w = create_main_window(app_handle, "/");
|
let w = window::create_main_window(app_handle, "/");
|
||||||
tauri::async_runtime::spawn(async move {
|
tauri::async_runtime::spawn(async move {
|
||||||
let info = history::store_launch_history(&w).await;
|
let info = history::store_launch_history(&w).await;
|
||||||
debug!("Launched Yaak {:?}", info);
|
debug!("Launched Yaak {:?}", info);
|
||||||
@@ -1973,45 +1868,6 @@ pub fn run() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_dev() -> bool {
|
|
||||||
#[cfg(dev)]
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
#[cfg(not(dev))]
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn create_main_window(handle: &AppHandle, url: &str) -> WebviewWindow {
|
|
||||||
let mut counter = 0;
|
|
||||||
let label = loop {
|
|
||||||
let label = format!("{MAIN_WINDOW_PREFIX}{counter}");
|
|
||||||
match handle.webview_windows().get(label.as_str()) {
|
|
||||||
None => break Some(label),
|
|
||||||
Some(_) => counter += 1,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.expect("Failed to generate label for new window");
|
|
||||||
|
|
||||||
let config = window::CreateWindowConfig {
|
|
||||||
url,
|
|
||||||
label: label.as_str(),
|
|
||||||
title: "Yaak",
|
|
||||||
inner_size: Some((DEFAULT_WINDOW_WIDTH, DEFAULT_WINDOW_HEIGHT)),
|
|
||||||
position: Some((
|
|
||||||
// Offset by random amount so it's easier to differentiate
|
|
||||||
100.0 + random::<f64>() * 20.0,
|
|
||||||
100.0 + random::<f64>() * 20.0,
|
|
||||||
)),
|
|
||||||
hide_titlebar: true,
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
window::create_window(handle, config)
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn get_update_mode(h: &AppHandle) -> UpdateMode {
|
async fn get_update_mode(h: &AppHandle) -> UpdateMode {
|
||||||
let settings = get_or_create_settings(h).await;
|
let settings = get_or_create_settings(h).await;
|
||||||
UpdateMode::new(settings.update_channel.as_str())
|
UpdateMode::new(settings.update_channel.as_str())
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use crate::MAIN_WINDOW_PREFIX;
|
use crate::window::MAIN_WINDOW_PREFIX;
|
||||||
use hex_color::HexColor;
|
use hex_color::HexColor;
|
||||||
use log::warn;
|
use log::warn;
|
||||||
use objc::{msg_send, sel, sel_impl};
|
use objc::{msg_send, sel, sel_impl};
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use crate::window_menu::app_menu;
|
use crate::window_menu::app_menu;
|
||||||
use crate::{DEFAULT_WINDOW_HEIGHT, DEFAULT_WINDOW_WIDTH, MIN_WINDOW_HEIGHT, MIN_WINDOW_WIDTH};
|
|
||||||
use log::{info, warn};
|
use log::{info, warn};
|
||||||
|
use rand::random;
|
||||||
use std::process::exit;
|
use std::process::exit;
|
||||||
use tauri::{
|
use tauri::{
|
||||||
AppHandle, Emitter, LogicalSize, Manager, Runtime, WebviewUrl, WebviewWindow, WindowEvent,
|
AppHandle, Emitter, LogicalSize, Manager, Runtime, WebviewUrl, WebviewWindow, WindowEvent,
|
||||||
@@ -8,6 +8,15 @@ use tauri::{
|
|||||||
use tauri_plugin_opener::OpenerExt;
|
use tauri_plugin_opener::OpenerExt;
|
||||||
use tokio::sync::mpsc;
|
use tokio::sync::mpsc;
|
||||||
|
|
||||||
|
const DEFAULT_WINDOW_WIDTH: f64 = 1100.0;
|
||||||
|
const DEFAULT_WINDOW_HEIGHT: f64 = 600.0;
|
||||||
|
|
||||||
|
const MIN_WINDOW_WIDTH: f64 = 300.0;
|
||||||
|
const MIN_WINDOW_HEIGHT: f64 = 300.0;
|
||||||
|
|
||||||
|
pub(crate) const MAIN_WINDOW_PREFIX: &str = "main_";
|
||||||
|
const OTHER_WINDOW_PREFIX: &str = "other_";
|
||||||
|
|
||||||
#[derive(Default, Debug)]
|
#[derive(Default, Debug)]
|
||||||
pub(crate) struct CreateWindowConfig<'s> {
|
pub(crate) struct CreateWindowConfig<'s> {
|
||||||
pub url: &'s str,
|
pub url: &'s str,
|
||||||
@@ -161,3 +170,95 @@ pub(crate) fn create_window<R: Runtime>(
|
|||||||
|
|
||||||
win
|
win
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn create_main_window(handle: &AppHandle, url: &str) -> WebviewWindow {
|
||||||
|
let mut counter = 0;
|
||||||
|
let label = loop {
|
||||||
|
let label = format!("{MAIN_WINDOW_PREFIX}{counter}");
|
||||||
|
match handle.webview_windows().get(label.as_str()) {
|
||||||
|
None => break Some(label),
|
||||||
|
Some(_) => counter += 1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.expect("Failed to generate label for new window");
|
||||||
|
|
||||||
|
let config = CreateWindowConfig {
|
||||||
|
url,
|
||||||
|
label: label.as_str(),
|
||||||
|
title: "Yaak",
|
||||||
|
inner_size: Some((DEFAULT_WINDOW_WIDTH, DEFAULT_WINDOW_HEIGHT)),
|
||||||
|
position: Some((
|
||||||
|
// Offset by random amount so it's easier to differentiate
|
||||||
|
100.0 + random::<f64>() * 20.0,
|
||||||
|
100.0 + random::<f64>() * 20.0,
|
||||||
|
)),
|
||||||
|
hide_titlebar: true,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
create_window(handle, config)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn create_child_window(parent_window: &WebviewWindow, url: &str, label: &str, title: &str, inner_size: (f64, f64)) -> WebviewWindow {
|
||||||
|
let app_handle = parent_window.app_handle();
|
||||||
|
let label = format!("{OTHER_WINDOW_PREFIX}_{label}");
|
||||||
|
let scale_factor = parent_window.scale_factor().unwrap();
|
||||||
|
|
||||||
|
let current_pos = parent_window.inner_position().unwrap().to_logical::<f64>(scale_factor);
|
||||||
|
let current_size = parent_window.inner_size().unwrap().to_logical::<f64>(scale_factor);
|
||||||
|
|
||||||
|
// Position the new window in the middle of the parent
|
||||||
|
let position = (
|
||||||
|
current_pos.x + current_size.width / 2.0 - inner_size.0 / 2.0,
|
||||||
|
current_pos.y + current_size.height / 2.0 - inner_size.1 / 2.0,
|
||||||
|
);
|
||||||
|
|
||||||
|
let config = CreateWindowConfig {
|
||||||
|
label: label.as_str(),
|
||||||
|
title,
|
||||||
|
url,
|
||||||
|
inner_size: Some(inner_size),
|
||||||
|
position: Some(position),
|
||||||
|
hide_titlebar: true,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
let child_window = create_window(&app_handle, config);
|
||||||
|
|
||||||
|
// NOTE: These listeners will remain active even when the windows close. Unfortunately,
|
||||||
|
// there's no way to unlisten to events for now, so we just have to be defensive.
|
||||||
|
|
||||||
|
{
|
||||||
|
let parent_window = parent_window.clone();
|
||||||
|
let child_window = child_window.clone();
|
||||||
|
child_window.clone().on_window_event(move |e| match e {
|
||||||
|
// When the new window is destroyed, bring the other up behind it
|
||||||
|
WindowEvent::Destroyed => {
|
||||||
|
if let Some(w) = parent_window.get_webview_window(child_window.label()) {
|
||||||
|
w.set_focus().unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let parent_window = parent_window.clone();
|
||||||
|
let child_window = child_window.clone();
|
||||||
|
parent_window.clone().on_window_event(move |e| match e {
|
||||||
|
// When the parent window is closed, close the child
|
||||||
|
WindowEvent::CloseRequested { .. } => child_window.destroy().unwrap(),
|
||||||
|
// When the parent window is focused, bring the child above
|
||||||
|
WindowEvent::Focused(focus) => {
|
||||||
|
if *focus {
|
||||||
|
if let Some(w) = parent_window.get_webview_window(child_window.label()) {
|
||||||
|
w.set_focus().unwrap();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
child_window
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,167 +0,0 @@
|
|||||||
import { open } from '@tauri-apps/plugin-dialog';
|
|
||||||
import React, { useState } from 'react';
|
|
||||||
import { useLocalStorage } from 'react-use';
|
|
||||||
import { capitalize } from '../../lib/capitalize';
|
|
||||||
import { invokeCmd } from '../../lib/tauri';
|
|
||||||
import { getThemes } from '../../lib/theme/themes';
|
|
||||||
import { yaakDark } from '../../lib/theme/themes/yaak';
|
|
||||||
import { getThemeCSS } from '../../lib/theme/window';
|
|
||||||
import { Banner } from '../core/Banner';
|
|
||||||
import { Button } from '../core/Button';
|
|
||||||
import {Editor} from "../core/Editor/Editor";
|
|
||||||
import type { IconProps } from '../core/Icon';
|
|
||||||
import { Icon } from '../core/Icon';
|
|
||||||
import { IconButton } from '../core/IconButton';
|
|
||||||
import { InlineCode } from '../core/InlineCode';
|
|
||||||
import { Input } from '../core/Input';
|
|
||||||
import { Separator } from '../core/Separator';
|
|
||||||
import { HStack, VStack } from '../core/Stacks';
|
|
||||||
|
|
||||||
const buttonColors = [
|
|
||||||
'primary',
|
|
||||||
'secondary',
|
|
||||||
'info',
|
|
||||||
'success',
|
|
||||||
'warning',
|
|
||||||
'danger',
|
|
||||||
'default',
|
|
||||||
] as const;
|
|
||||||
|
|
||||||
const icons: IconProps['icon'][] = [
|
|
||||||
'info',
|
|
||||||
'box',
|
|
||||||
'update',
|
|
||||||
'alert_triangle',
|
|
||||||
'arrow_big_right_dash',
|
|
||||||
'download',
|
|
||||||
'copy',
|
|
||||||
'magic_wand',
|
|
||||||
'settings',
|
|
||||||
'trash',
|
|
||||||
'sparkles',
|
|
||||||
'pencil',
|
|
||||||
'paste',
|
|
||||||
'search',
|
|
||||||
'send_horizontal',
|
|
||||||
];
|
|
||||||
|
|
||||||
const themes = getThemes();
|
|
||||||
|
|
||||||
export function SettingsDesign() {
|
|
||||||
const [exportDir, setExportDir] = useLocalStorage<string | null>('theme_export_dir', null);
|
|
||||||
const [loadingExport, setLoadingExport] = useState<boolean>(false);
|
|
||||||
|
|
||||||
const saveThemes = () => {
|
|
||||||
setLoadingExport(true);
|
|
||||||
setTimeout(async () => {
|
|
||||||
const allThemesCSS = themes.themes.map(getThemeCSS).join('\n\n');
|
|
||||||
const coreThemeCSS = [yaakDark].map(getThemeCSS).join('\n\n');
|
|
||||||
|
|
||||||
try {
|
|
||||||
await invokeCmd('cmd_write_file_dev', {
|
|
||||||
pathname: exportDir + '/themes-all.css',
|
|
||||||
contents: allThemesCSS,
|
|
||||||
});
|
|
||||||
await invokeCmd('cmd_write_file_dev', {
|
|
||||||
pathname: exportDir + '/themes-slim.css',
|
|
||||||
contents: coreThemeCSS,
|
|
||||||
});
|
|
||||||
} catch (err) {
|
|
||||||
console.log('FAILED', err);
|
|
||||||
}
|
|
||||||
setLoadingExport(false);
|
|
||||||
}, 500);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="p-2 flex flex-col gap-3">
|
|
||||||
<VStack space={2}>
|
|
||||||
<InlineCode>{exportDir}</InlineCode>
|
|
||||||
<HStack space={2}>
|
|
||||||
<Button
|
|
||||||
size="sm"
|
|
||||||
color="secondary"
|
|
||||||
variant="border"
|
|
||||||
onClick={() => {
|
|
||||||
open({ directory: true }).then(setExportDir);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Change Export Dir
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
disabled={exportDir == null}
|
|
||||||
isLoading={loadingExport}
|
|
||||||
size="sm"
|
|
||||||
color="primary"
|
|
||||||
variant="border"
|
|
||||||
onClick={saveThemes}
|
|
||||||
>
|
|
||||||
Export CSS
|
|
||||||
</Button>
|
|
||||||
</HStack>
|
|
||||||
</VStack>
|
|
||||||
<Separator className="my-6" />
|
|
||||||
<Input
|
|
||||||
label="Field Label"
|
|
||||||
name="demo"
|
|
||||||
placeholder="Placeholder"
|
|
||||||
size="sm"
|
|
||||||
rightSlot={<IconButton title="search" size="xs" className="w-8 m-0.5" icon="search" />}
|
|
||||||
stateKey={null}
|
|
||||||
/>
|
|
||||||
<Editor
|
|
||||||
defaultValue={[
|
|
||||||
'// Demo code editor',
|
|
||||||
'let foo = {',
|
|
||||||
' foo: ("bar" || "baz" ?? \'qux\'),',
|
|
||||||
' baz: [1, 10.2, null, false, true],',
|
|
||||||
'};',
|
|
||||||
].join('\n')}
|
|
||||||
heightMode="auto"
|
|
||||||
language="javascript"
|
|
||||||
stateKey={null}
|
|
||||||
/>
|
|
||||||
<div className="flex flex-col gap-1">
|
|
||||||
<div className="flex flex-wrap gap-1">
|
|
||||||
{buttonColors.map((c, i) => (
|
|
||||||
<Button key={c} color={c} size="sm" leftSlot={<Icon size="sm" icon={icons[i]!} />}>
|
|
||||||
{capitalize(c).slice(0, 4)}
|
|
||||||
</Button>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
<div className="flex flex-wrap gap-1">
|
|
||||||
{buttonColors.map((c, i) => (
|
|
||||||
<Button
|
|
||||||
key={c}
|
|
||||||
color={c}
|
|
||||||
variant="border"
|
|
||||||
size="sm"
|
|
||||||
leftSlot={<Icon size="sm" icon={icons[i]!} />}
|
|
||||||
>
|
|
||||||
{capitalize(c).slice(0, 4)}
|
|
||||||
</Button>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
<div className="flex gap-1">
|
|
||||||
{icons.map((v, i) => (
|
|
||||||
<IconButton
|
|
||||||
color={buttonColors[i % buttonColors.length]}
|
|
||||||
title={v}
|
|
||||||
variant="border"
|
|
||||||
size="sm"
|
|
||||||
key={v}
|
|
||||||
icon={v}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="flex flex-col gap-1">
|
|
||||||
<Banner color="primary">Primary banner</Banner>
|
|
||||||
<Banner color="secondary">Secondary banner</Banner>
|
|
||||||
<Banner color="danger">Danger banner</Banner>
|
|
||||||
<Banner color="warning">Warning banner</Banner>
|
|
||||||
<Banner color="success">Success banner</Banner>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -77,14 +77,6 @@ export function SettingsGeneral() {
|
|||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Checkbox
|
|
||||||
className="mt-3"
|
|
||||||
checked={false}
|
|
||||||
title="Send Usage Statistics (all tracking was removed in 2025.1.2)"
|
|
||||||
disabled
|
|
||||||
onChange={() => {}}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Separator className="my-4" />
|
<Separator className="my-4" />
|
||||||
|
|
||||||
<Heading level={2}>
|
<Heading level={2}>
|
||||||
|
|||||||
@@ -78,8 +78,7 @@ type TauriCmd =
|
|||||||
| 'cmd_update_http_request'
|
| 'cmd_update_http_request'
|
||||||
| 'cmd_update_settings'
|
| 'cmd_update_settings'
|
||||||
| 'cmd_update_workspace'
|
| 'cmd_update_workspace'
|
||||||
| 'cmd_update_workspace_meta'
|
| 'cmd_update_workspace_meta';
|
||||||
| 'cmd_write_file_dev';
|
|
||||||
|
|
||||||
export async function invokeCmd<T>(cmd: TauriCmd, args?: InvokeArgs): Promise<T> {
|
export async function invokeCmd<T>(cmd: TauriCmd, args?: InvokeArgs): Promise<T> {
|
||||||
// console.log('RUN COMMAND', cmd, args);
|
// console.log('RUN COMMAND', cmd, args);
|
||||||
|
|||||||
Reference in New Issue
Block a user