start on login
This commit is contained in:
parent
ebc00a5df6
commit
741169d807
32
src-tauri/Cargo.lock
generated
32
src-tauri/Cargo.lock
generated
@ -68,6 +68,7 @@ checksum = "bb07d2053ccdbe10e2af2995a2f116c1330396493dc1269f6a91d0ae82e19704"
|
|||||||
name = "app"
|
name = "app"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"auto-launch",
|
||||||
"aws-config",
|
"aws-config",
|
||||||
"aws-sdk-sts",
|
"aws-sdk-sts",
|
||||||
"aws-smithy-types",
|
"aws-smithy-types",
|
||||||
@ -138,6 +139,17 @@ dependencies = [
|
|||||||
"wildmatch",
|
"wildmatch",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "auto-launch"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5904a4d734f0235edf29aab320a14899f3e090446e594ff96508a6215f76f89c"
|
||||||
|
dependencies = [
|
||||||
|
"dirs",
|
||||||
|
"thiserror",
|
||||||
|
"winreg",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "autocfg"
|
name = "autocfg"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
@ -915,6 +927,15 @@ dependencies = [
|
|||||||
"subtle",
|
"subtle",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dirs"
|
||||||
|
version = "4.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059"
|
||||||
|
dependencies = [
|
||||||
|
"dirs-sys",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dirs-next"
|
name = "dirs-next"
|
||||||
version = "2.0.0"
|
version = "2.0.0"
|
||||||
@ -925,6 +946,17 @@ dependencies = [
|
|||||||
"dirs-sys-next",
|
"dirs-sys-next",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dirs-sys"
|
||||||
|
version = "0.3.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"redox_users",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dirs-sys-next"
|
name = "dirs-sys-next"
|
||||||
version = "0.1.2"
|
version = "0.1.2"
|
||||||
|
@ -31,6 +31,7 @@ thiserror = "1.0.38"
|
|||||||
once_cell = "1.16.0"
|
once_cell = "1.16.0"
|
||||||
strum = "0.24"
|
strum = "0.24"
|
||||||
strum_macros = "0.24"
|
strum_macros = "0.24"
|
||||||
|
auto-launch = "0.4.0"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
# by default Tauri runs in production mode
|
# by default Tauri runs in production mode
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use std::net::Ipv4Addr;
|
use std::net::Ipv4Addr;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
use auto_launch::AutoLaunchBuilder;
|
||||||
use serde::{Serialize, Deserialize};
|
use serde::{Serialize, Deserialize};
|
||||||
use sqlx::SqlitePool;
|
use sqlx::SqlitePool;
|
||||||
|
|
||||||
@ -17,6 +18,8 @@ pub struct AppConfig {
|
|||||||
pub rehide_ms: u64,
|
pub rehide_ms: u64,
|
||||||
#[serde(default = "default_start_minimized")]
|
#[serde(default = "default_start_minimized")]
|
||||||
pub start_minimized: bool,
|
pub start_minimized: bool,
|
||||||
|
#[serde(default = "default_start_on_login")]
|
||||||
|
pub start_on_login: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -27,6 +30,7 @@ impl Default for AppConfig {
|
|||||||
listen_port: default_listen_port(),
|
listen_port: default_listen_port(),
|
||||||
rehide_ms: default_rehide_ms(),
|
rehide_ms: default_rehide_ms(),
|
||||||
start_minimized: default_start_minimized(),
|
start_minimized: default_start_minimized(),
|
||||||
|
start_on_login: default_start_on_login(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -62,6 +66,28 @@ impl AppConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub fn set_auto_launch(enable: bool) -> Result<(), SetupError> {
|
||||||
|
let path_buf = std::env::current_exe()
|
||||||
|
.map_err(|e| auto_launch::Error::Io(e))?;
|
||||||
|
let path = path_buf
|
||||||
|
.to_string_lossy();
|
||||||
|
|
||||||
|
let auto = AutoLaunchBuilder::new()
|
||||||
|
.set_app_name("Creddy")
|
||||||
|
.set_app_path(&path)
|
||||||
|
.build()?;
|
||||||
|
|
||||||
|
if enable {
|
||||||
|
auto.enable()?;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
auto.disable()?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn get_or_create_db_path() -> PathBuf {
|
pub fn get_or_create_db_path() -> PathBuf {
|
||||||
if cfg!(debug_assertions) {
|
if cfg!(debug_assertions) {
|
||||||
return PathBuf::from("./creddy.db");
|
return PathBuf::from("./creddy.db");
|
||||||
@ -90,7 +116,7 @@ fn default_listen_port() -> u16 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn default_listen_addr() -> Ipv4Addr { Ipv4Addr::LOCALHOST }
|
fn default_listen_addr() -> Ipv4Addr { Ipv4Addr::LOCALHOST }
|
||||||
|
|
||||||
fn default_rehide_ms() -> u64 { 1000 }
|
fn default_rehide_ms() -> u64 { 1000 }
|
||||||
|
// start minimized and on login only in production mode
|
||||||
fn default_start_minimized() -> bool { !cfg!(debug_assertions) } // default to start-minimized in production only
|
fn default_start_minimized() -> bool { !cfg!(debug_assertions) }
|
||||||
|
fn default_start_on_login() -> bool { !cfg!(debug_assertions) }
|
||||||
|
@ -87,6 +87,8 @@ pub enum SetupError {
|
|||||||
MigrationError(#[from] MigrateError),
|
MigrationError(#[from] MigrateError),
|
||||||
#[error("Error parsing configuration from database")]
|
#[error("Error parsing configuration from database")]
|
||||||
ConfigParseError(#[from] serde_json::Error),
|
ConfigParseError(#[from] serde_json::Error),
|
||||||
|
#[error("Failed to set up start-on-login: {0}")]
|
||||||
|
AutoLaunchError(#[from] auto_launch::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ use state::AppState;
|
|||||||
pub static APP: OnceCell<AppHandle> = OnceCell::new();
|
pub static APP: OnceCell<AppHandle> = OnceCell::new();
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let initial_state = match rt::block_on(state::AppState::load()) {
|
let initial_state = match rt::block_on(AppState::load()) {
|
||||||
Ok(state) => state,
|
Ok(state) => state,
|
||||||
Err(e) => {eprintln!("{}", e); return;}
|
Err(e) => {eprintln!("{}", e); return;}
|
||||||
};
|
};
|
||||||
@ -42,6 +42,8 @@ fn main() {
|
|||||||
APP.set(app.handle()).unwrap();
|
APP.set(app.handle()).unwrap();
|
||||||
let state = app.state::<AppState>();
|
let state = app.state::<AppState>();
|
||||||
let config = state.config.read().unwrap();
|
let config = state.config.read().unwrap();
|
||||||
|
config::set_auto_launch(config.start_on_login)?;
|
||||||
|
|
||||||
let addr = std::net::SocketAddrV4::new(config.listen_addr, config.listen_port);
|
let addr = std::net::SocketAddrV4::new(config.listen_addr, config.listen_port);
|
||||||
tauri::async_runtime::spawn(server::serve(addr, app.handle()));
|
tauri::async_runtime::spawn(server::serve(addr, app.handle()));
|
||||||
|
|
||||||
|
@ -150,13 +150,14 @@ impl AppState {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn update_config(&self, new_config: AppConfig) -> Result<(), sqlx::error::Error> {
|
pub async fn update_config(&self, new_config: AppConfig) -> Result<(), SetupError> {
|
||||||
let config = {
|
new_config.save(&self.pool).await?;
|
||||||
let mut live_config = self.config.write().unwrap();
|
|
||||||
*live_config = new_config;
|
let mut live_config = self.config.write().unwrap();
|
||||||
live_config.clone()
|
if new_config.start_on_login != live_config.start_on_login {
|
||||||
};
|
config::set_auto_launch(new_config.start_on_login)?;
|
||||||
config.save(&self.pool).await?;
|
}
|
||||||
|
*live_config = new_config;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -10,27 +10,28 @@
|
|||||||
export let max = null;
|
export let max = null;
|
||||||
export let decimal = false;
|
export let decimal = false;
|
||||||
|
|
||||||
|
console.log('min:', min);
|
||||||
|
|
||||||
const dispatch = createEventDispatcher();
|
const dispatch = createEventDispatcher();
|
||||||
let error = null;
|
let error = null;
|
||||||
|
let localValue = value.toString();
|
||||||
function validate(event) {
|
function validate(event) {
|
||||||
let v = event.target.value;
|
localValue = localValue.replace(/[^-0-9.]/g, '');
|
||||||
|
// Don't update the value, but also don't error, if it's empty
|
||||||
if (v === '') {
|
// or if it could be the start of a negative or decimal number
|
||||||
|
if (localValue.match(/^$|^-$|^\.$/) !== null) {
|
||||||
error = null;
|
error = null;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let num = parseFloat(v);
|
let num = parseFloat(localValue);
|
||||||
if (Number.isNaN(num)) {
|
if (num % 1 !== 0 && !decimal) {
|
||||||
error = `"${v}" is not a number`;
|
|
||||||
}
|
|
||||||
else if (num % 1 !== 0 && !decimal) {
|
|
||||||
error = `${num} is not a whole number`;
|
error = `${num} is not a whole number`;
|
||||||
}
|
}
|
||||||
else if (min && num < min) {
|
else if (min !== null && num < min) {
|
||||||
error = `Too low (minimum ${min})`;
|
error = `Too low (minimum ${min})`;
|
||||||
}
|
}
|
||||||
else if (max && num > max) {
|
else if (max !== null && num > max) {
|
||||||
error = `Too large (maximum ${max})`
|
error = `Too large (maximum ${max})`
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -47,12 +48,13 @@
|
|||||||
{#if unit}
|
{#if unit}
|
||||||
<span class="mr-2">{unit}:</span>
|
<span class="mr-2">{unit}:</span>
|
||||||
{/if}
|
{/if}
|
||||||
<div class="tooltip tooltip-error" class:tooltip-open={error !== null} data-tip={error}>
|
<div class="tooltip tooltip-error" class:tooltip-open={error !== null} data-tip="{error}">
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
class="input input-sm input-bordered text-right max-w-[4rem]"
|
class="input input-sm input-bordered text-right"
|
||||||
|
size="{Math.max(5, localValue.length)}"
|
||||||
class:input-error={error}
|
class:input-error={error}
|
||||||
value={value}
|
bind:value={localValue}
|
||||||
on:input="{validate}"
|
on:input="{validate}"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -12,6 +12,8 @@
|
|||||||
<slot name="input"></slot>
|
<slot name="input"></slot>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p class="mt-3">
|
{#if $$slots.description}
|
||||||
<slot name="description"></slot>
|
<p class="mt-3">
|
||||||
</p>
|
<slot name="description"></slot>
|
||||||
|
</p>
|
||||||
|
{/if}
|
||||||
|
@ -20,6 +20,12 @@
|
|||||||
<div class="max-w-md mx-auto mt-1.5 p-4">
|
<div class="max-w-md mx-auto mt-1.5 p-4">
|
||||||
<h2 class="text-2xl font-bold text-center">Settings</h2>
|
<h2 class="text-2xl font-bold text-center">Settings</h2>
|
||||||
|
|
||||||
|
<ToggleSetting title="Start on login" bind:value={$appState.config.start_on_login} on:update={save}>
|
||||||
|
<svelte:fragment slot="description">
|
||||||
|
Start Creddy when you log in to your computer.
|
||||||
|
</svelte:fragment>
|
||||||
|
</ToggleSetting>
|
||||||
|
|
||||||
<ToggleSetting title="Start minimized" bind:value={$appState.config.start_minimized} on:update={save}>
|
<ToggleSetting title="Start minimized" bind:value={$appState.config.start_minimized} on:update={save}>
|
||||||
<svelte:fragment slot="description">
|
<svelte:fragment slot="description">
|
||||||
Minimize to the system tray at startup.
|
Minimize to the system tray at startup.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user