Merge pull request #38 from SteelDynamite/tm-branch-2

tm-branch-2
This commit is contained in:
SteelDynamite 2026-04-06 17:32:27 -07:00 committed by GitHub
commit fdc556ddd5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 86 additions and 4 deletions

View file

@ -14,7 +14,7 @@
</script> </script>
<div class={app.isDark ? "dark" : ""} data-theme={app.currentTheme ?? ""}> <div class={app.isDark ? "dark" : ""} data-theme={app.currentTheme ?? ""}>
<div class="h-screen w-screen" class:p-2={isLinux}> <div class="h-screen w-screen" class:p-2={isLinux} class:onyx-border={app.currentTheme === "onyx"}>
<div <div
class="relative h-full w-full overflow-hidden bg-surface-light text-text-light dark:bg-surface-dark dark:text-text-dark" class="relative h-full w-full overflow-hidden bg-surface-light text-text-light dark:bg-surface-dark dark:text-text-dark"
class:rounded-xl={isLinux} class:rounded-xl={isLinux}

View file

@ -139,6 +139,67 @@ body {
--color-danger: #ff5555; --color-danger: #ff5555;
} }
[data-theme="onyx"] {
--color-primary: #f5ecd0;
--color-primary-hover: #e0d5b3;
--color-surface-light: #141414;
--color-surface-dark: #141414;
--color-card-light: #1e1e1e;
--color-card-dark: #1e1e1e;
--color-text-light: #d1bf82;
--color-text-dark: #d1bf82;
--color-text-secondary-light: #a6905a;
--color-text-secondary-dark: #a6905a;
--color-border-light: #5c4d2e;
--color-border-dark: #5c4d2e;
--color-danger: #ef4444;
}
[data-theme="onyx"] * {
scrollbar-color: #a6905a transparent;
}
[data-theme="onyx"] ::-webkit-scrollbar-thumb {
background: #a6905a;
}
[data-theme="onyx"] select option {
background-color: #141414;
color: #d1bf82;
}
/* Dark text/icons on primary buttons/FAB */
[data-theme="onyx"] .bg-primary,
[data-theme="onyx"] .bg-primary .text-white {
color: #141414;
}
/* FAB: match text gold instead of cream primary */
[data-theme="onyx"] .rounded-full.bg-primary.shadow-lg {
background-color: #d1bf82;
}
/* Checkbox borders: gold instead of gray */
[data-theme="onyx"] .border-gray-400,
[data-theme="onyx"] .border-gray-500 {
border-color: #a6905a;
}
/* Hover/focus highlights: gold tint instead of white */
[data-theme="onyx"] .dark\:hover\:bg-white\/10:hover,
[data-theme="onyx"] .dark\:hover\:bg-white\/5:hover,
[data-theme="onyx"] .dark\:bg-white\/10 {
background-color: rgb(209 191 130 / 0.1);
}
/* Linux window border */
[data-theme="onyx"] .linux-window-border {
border-color: rgba(209, 191, 130, 0.15);
}
/* Thick gold window border */
[data-theme="onyx"] .onyx-border {
border: 3px solid #a6905a;
}
[data-theme="solarized"] { [data-theme="solarized"] {
--color-primary: #268bd2; --color-primary: #268bd2;
--color-primary-hover: #1e7ac0; --color-primary-hover: #1e7ac0;

View file

@ -259,6 +259,7 @@
<option value="nord">Nord</option> <option value="nord">Nord</option>
<option value="dracula">Dracula</option> <option value="dracula">Dracula</option>
<option value="solarized">Solarized Dark</option> <option value="solarized">Solarized Dark</option>
<option value="onyx">Black and Gold</option>
</select> </select>
</section> </section>

View file

@ -67,7 +67,7 @@ let hasWorkspace = $derived(
Object.keys(config.workspaces).length > 0, Object.keys(config.workspaces).length > 0,
); );
const DARK_THEMES = new Set(["dark", "nord", "dracula", "solarized"]); const DARK_THEMES = new Set(["dark", "nord", "dracula", "solarized", "onyx"]);
let currentTheme = $derived( let currentTheme = $derived(
config?.current_workspace config?.current_workspace
? config.workspaces[config.current_workspace]?.theme ?? null ? config.workspaces[config.current_workspace]?.theme ?? null

View file

@ -688,7 +688,18 @@ async fn execute_action(
match action { match action {
SyncAction::Upload { path } => { SyncAction::Upload { path } => {
let local_path = workspace_path.join(path.replace('/', std::path::MAIN_SEPARATOR_STR)); let local_path = workspace_path.join(path.replace('/', std::path::MAIN_SEPARATOR_STR));
let data = std::fs::read(&local_path)?; let data = match std::fs::read(&local_path) {
Ok(d) => d,
Err(e) if e.kind() == std::io::ErrorKind::NotFound => {
// File was moved or deleted since the action was computed (e.g. task
// moved between lists). Drop the stale upload and clean up sync state
// so the next cycle can re-evaluate from a clean baseline.
report(&format!(" - Skipping upload for missing file {}", path));
sync_state.files.remove(path.as_str());
return Ok(());
}
Err(e) => return Err(e.into()),
};
let checksum = compute_checksum(&data); let checksum = compute_checksum(&data);
if let Some(parent) = path_parent(path) { if let Some(parent) = path_parent(path) {
@ -707,7 +718,16 @@ async fn execute_action(
SyncAction::Conflict { path } => { SyncAction::Conflict { path } => {
let local_path = workspace_path.join(path.replace('/', std::path::MAIN_SEPARATOR_STR)); let local_path = workspace_path.join(path.replace('/', std::path::MAIN_SEPARATOR_STR));
let local_data = std::fs::read(&local_path)?; let local_data = match std::fs::read(&local_path) {
Ok(d) => d,
Err(e) if e.kind() == std::io::ErrorKind::NotFound => {
// Local file gone — treat as remote-wins: download it on next cycle.
report(&format!(" - Skipping conflict for missing local file {}", path));
sync_state.files.remove(path.as_str());
return Ok(());
}
Err(e) => return Err(e.into()),
};
let local_checksum = compute_checksum(&local_data); let local_checksum = compute_checksum(&local_data);
let remote_data = client.get_file(path).await?; let remote_data = client.get_file(path).await?;