make terminal emulator configurable

This commit is contained in:
Joseph Montanaro 2023-09-09 06:30:19 -07:00
parent e46c3d2b4d
commit c98a065587
10 changed files with 107 additions and 24 deletions

View File

@ -25,7 +25,7 @@ tauri-build = { version = "1.0.4", features = [] }
[dependencies] [dependencies]
serde_json = "1.0" serde_json = "1.0"
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
tauri = { version = "1.2", features = ["dialog", "os-all", "system-tray"] } tauri = { version = "1.2", features = ["dialog", "dialog-open", "os-all", "system-tray"] }
tauri-plugin-single-instance = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "dev" } tauri-plugin-single-instance = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "dev" }
sodiumoxide = "0.2.7" sodiumoxide = "0.2.7"
tokio = { version = ">=1.19", features = ["full"] } tokio = { version = ">=1.19", features = ["full"] }

View File

@ -1,5 +1,4 @@
use std::net::Ipv4Addr; use std::net::Ipv4Addr;
use std::ffi::OsString;
use std::path::PathBuf; use std::path::PathBuf;
use auto_launch::AutoLaunchBuilder; use auto_launch::AutoLaunchBuilder;
@ -15,8 +14,9 @@ pub struct TermConfig {
pub name: String, pub name: String,
// we call it exec because it isn't always the actual path, // we call it exec because it isn't always the actual path,
// in some cases it's just the name and relies on path-searching // in some cases it's just the name and relies on path-searching
pub exec: PathBuf, // it's a string because it can come from the frontend as json
pub args: Vec<OsString>, pub exec: String,
pub args: Vec<String>,
} }
@ -134,18 +134,20 @@ fn default_listen_port() -> u16 {
fn default_term_config() -> TermConfig { fn default_term_config() -> TermConfig {
#[cfg(windows)] #[cfg(windows)]
{ {
if let Ok(path) = which::which("pwsh.exe") { let shell = if which::which("pwsh.exe").is_ok() {
return TermConfig { "pwsh.exe".to_string()
name: "pwsh.exe".into(),
exec: "conhost.exe".into(),
args: vec![path.into_os_string()]
};
} }
return TermConfig { else {
name: "powershell.exe".into(), "powershell.exe".to_string()
exec: "conhost.exe".into(),
args: vec!["powershell.exe".into()]
}; };
let (exec, args) = if cfg!(debug_assertions) {
("conhost.exe".to_string(), vec![shell.clone()])
} else {
(shell.clone(), vec![])
};
TermConfig { name: shell, exec, args }
} }
#[cfg(unix)] #[cfg(unix)]

View File

@ -12,7 +12,8 @@
}, },
"tauri": { "tauri": {
"allowlist": { "allowlist": {
"os": {"all": true} "os": {"all": true},
"dialog": {"open": true}
}, },
"bundle": { "bundle": {
"active": true, "active": true,

View File

@ -0,0 +1,28 @@
<script>
import { createEventDispatcher } from 'svelte';
import { open } from '@tauri-apps/api/dialog';
import Setting from './Setting.svelte';
export let title;
export let divider = true;
export let value;
const dispatch = createEventDispatcher();
</script>
<Setting {title} {divider}>
<div slot="input">
<input
type="text"
class="input input-sm input-bordered grow text-right"
bind:value
on:change={() => dispatch('update', {value})}
>
<button
class="btn btn-sm btn-primary"
on:click={async () => value = await open()}
>Browse</button>
</div>
<slot name="description" slot="description"></slot>
</Setting>

View File

@ -4,6 +4,7 @@
import Setting from './Setting.svelte'; import Setting from './Setting.svelte';
export let title; export let title;
export let divider = true;
export let value; export let value;
export let unit = ''; export let unit = '';
export let min = null; export let min = null;
@ -59,7 +60,7 @@
</script> </script>
<Setting {title}> <Setting {title} {divider}>
<div slot="input"> <div slot="input">
{#if unit} {#if unit}
<span class="mr-2">{unit}:</span> <span class="mr-2">{unit}:</span>

View File

@ -3,12 +3,15 @@
import ErrorAlert from '../ErrorAlert.svelte'; import ErrorAlert from '../ErrorAlert.svelte';
export let title; export let title;
export let divider = true;
</script> </script>
<div class="divider"></div> {#if divider}
<div class="flex justify-between"> <div class="divider"></div>
<h3 class="text-lg font-bold">{title}</h3> {/if}
<div class="flex flex-wrap justify-between gap-y-4">
<h3 class="text-lg font-bold shrink-0">{title}</h3>
<slot name="input"></slot> <slot name="input"></slot>
</div> </div>

View File

@ -0,0 +1,23 @@
<script>
import { createEventDispatcher } from 'svelte';
import Setting from './Setting.svelte';
export let title;
export let divider = true;
export let value;
const dispatch = createEventDispatcher();
</script>
<Setting {title} {divider}>
<div slot="input">
<input
type="text"
class="input input-sm input-bordered grow text-right"
bind:value
on:change={() => dispatch('update', {value})}
>
</div>
<slot name="description" slot="description"></slot>
</Setting>

View File

@ -4,13 +4,14 @@
import Setting from './Setting.svelte'; import Setting from './Setting.svelte';
export let title; export let title;
export let divider = true; // passed through to Setting
export let value; export let value;
const dispatch = createEventDispatcher(); const dispatch = createEventDispatcher();
</script> </script>
<Setting {title}> <Setting {title} {divider}>
<input <input
slot="input" slot="input"
type="checkbox" type="checkbox"

View File

@ -1,3 +1,5 @@
export { default as Setting } from './Setting.svelte'; export { default as Setting } from './Setting.svelte';
export { default as ToggleSetting } from './ToggleSetting.svelte'; export { default as ToggleSetting } from './ToggleSetting.svelte';
export { default as NumericSetting } from './NumericSetting.svelte'; export { default as NumericSetting } from './NumericSetting.svelte';
export { default as FileSetting } from './FileSetting.svelte';
export { default as TextSetting } from './TextSetting.svelte';

View File

@ -6,7 +6,7 @@
import Nav from '../ui/Nav.svelte'; import Nav from '../ui/Nav.svelte';
import Link from '../ui/Link.svelte'; import Link from '../ui/Link.svelte';
import ErrorAlert from '../ui/ErrorAlert.svelte'; import ErrorAlert from '../ui/ErrorAlert.svelte';
import { Setting, ToggleSetting, NumericSetting } from '../ui/settings'; import { Setting, ToggleSetting, NumericSetting, FileSetting, TextSetting } from '../ui/settings';
import { fly } from 'svelte/transition'; import { fly } from 'svelte/transition';
import { backInOut } from 'svelte/easing'; import { backInOut } from 'svelte/easing';
@ -25,18 +25,25 @@
let osType = ''; let osType = '';
type().then(t => osType = t); type().then(t => osType = t);
console.log($appState.config.terminal);
window.term = $appState.config.terminal;
</script> </script>
<Nav> <Nav>
<h2 slot="title" class="text-2xl font-bold">Settings</h2> <h1 slot="title" class="text-2xl font-bold">Settings</h1>
</Nav> </Nav>
{#await invoke('get_config') then config} {#await invoke('get_config') then config}
<div class="max-w-md mx-auto mt-1.5 p-4"> <div class="max-w-lg 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}> <div class="divider mt-0 mb-8">
<h2 class="text-xl font-bold">General</h2>
</div>
<ToggleSetting title="Start on login" divider={false} bind:value={$appState.config.start_on_login} on:update={save}>
<svelte:fragment slot="description"> <svelte:fragment slot="description">
Start Creddy when you log in to your computer. Start Creddy when you log in to your computer.
</svelte:fragment> </svelte:fragment>
@ -76,6 +83,21 @@
Update or re-enter your encrypted credentials. Update or re-enter your encrypted credentials.
</svelte:fragment> </svelte:fragment>
</Setting> </Setting>
<div class="divider mt-10 mb-8">
<h2 class="text-xl font-bold">Terminal</h2>
</div>
<FileSetting
title="Emulator"
divider={false}
bind:value={$appState.config.terminal.exec}
on:update={save}
>
<svelte:fragment slot="description">
Choose your preferred terminal emulator (e.g. <code>gnome-terminal</code>, <code>wt.exe</code>.) May be an absolute path or an executable discoverable on <code>$PATH</code>.
</svelte:fragment>
</FileSetting>
</div> </div>
{/await} {/await}