Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
71 changes: 58 additions & 13 deletions packages/app/src/app/pages/dashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ import {
Box,
ChevronDown,
ChevronRight,
Circle,
History,
HeartPulse,
Loader2,
Expand Down Expand Up @@ -749,12 +750,50 @@ export default function DashboardView(props: DashboardViewProps) {
return "Update available";
});

const updatePillTone = createMemo(() => {
const updatePillButtonTone = createMemo(() => {
const state = props.updateStatus?.state;
if (state === "ready") {
return "border-transparent bg-green-9 text-white shadow-[0_2px_10px_rgba(22,163,74,0.35)] hover:bg-green-10";
return props.anyActiveRuns
? "text-amber-11 hover:text-amber-11 hover:bg-amber-3/35"
: "text-green-11 hover:text-green-11 hover:bg-green-3/35";
}
if (state === "downloading") {
return "text-blue-11 hover:text-blue-11 hover:bg-blue-3/35";
}
return "text-emerald-11 hover:text-emerald-11 hover:bg-emerald-3/35";
});

const updatePillBorderTone = createMemo(() => {
const state = props.updateStatus?.state;
if (state === "ready") {
return props.anyActiveRuns ? "border-amber-7/35" : "border-green-7/35";
}
if (state === "downloading") {
return "border-blue-7/35";
}
return "border-emerald-7/35";
});

const updatePillDotTone = createMemo(() => {
const state = props.updateStatus?.state;
if (state === "ready") {
return props.anyActiveRuns ? "text-amber-10 fill-amber-10" : "text-green-10 fill-green-10";
}
if (state === "downloading") {
return "text-blue-10";
}
return "text-emerald-10 fill-emerald-10";
});

const updatePillVersionTone = createMemo(() => {
const state = props.updateStatus?.state;
if (state === "ready") {
return props.anyActiveRuns ? "text-amber-11/75" : "text-green-11/75";
}
if (state === "downloading") {
return "text-blue-11/75";
}
return "border-transparent bg-dls-accent text-white shadow-[0_2px_10px_rgba(var(--dls-accent-rgb),0.35)] hover:bg-[var(--dls-accent-hover)]";
return "text-emerald-11/75";
});

const updatePillTitle = createMemo(() => {
Expand Down Expand Up @@ -785,23 +824,26 @@ export default function DashboardView(props: DashboardViewProps) {
<Show when={showUpdatePill()}>
<button
type="button"
class={`mb-3 w-full flex h-9 items-center gap-2 rounded-xl border px-3 text-xs font-medium transition-all hover:-translate-y-[1px] ${updatePillTone()}`}
class={`group mb-3 w-full flex items-center gap-2 rounded-md px-2 py-1.5 text-xs font-medium transition-colors ${updatePillButtonTone()}`}
onClick={handleUpdatePillClick}
title={updatePillTitle()}
aria-label={updatePillTitle()}
>
<Show
when={props.updateStatus?.state === "downloading"}
fallback={
<span class="w-2 h-2 rounded-full bg-white/85" />
<Circle
size={8}
class={`${updatePillDotTone()} shrink-0 ${props.updateStatus?.state === "available" ? "group-hover:animate-pulse" : ""}`}
/>
}
>
<Loader2 size={14} class="animate-spin text-white/90" />
<Loader2 size={13} class={`animate-spin shrink-0 ${updatePillDotTone()}`} />
</Show>
<span class="text-[11px] font-semibold text-white">{updatePillLabel()}</span>
<span class="flex-1 text-left">{updatePillLabel()}</span>
<Show when={props.updateStatus?.version}>
{(version) => (
<span class="ml-auto text-[11px] text-white/80 font-mono">v{version()}</span>
<span class={`ml-auto font-mono text-[10px] ${updatePillVersionTone()}`}>v{version()}</span>
)}
</Show>
</button>
Expand Down Expand Up @@ -1181,23 +1223,26 @@ export default function DashboardView(props: DashboardViewProps) {
<Show when={showUpdatePill()}>
<button
type="button"
class={`md:hidden flex h-8 items-center gap-2 rounded-full border px-3 text-xs font-medium transition-colors ${updatePillTone()}`}
class={`md:hidden flex items-center gap-1.5 rounded-full border bg-white px-2.5 py-1 text-xs font-medium shadow-sm transition-colors active:scale-[0.99] ${updatePillBorderTone()} ${updatePillButtonTone()}`}
onClick={handleUpdatePillClick}
title={updatePillTitle()}
aria-label={updatePillTitle()}
>
<Show
when={props.updateStatus?.state === "downloading"}
fallback={
<span class="w-2 h-2 rounded-full bg-white/85" />
<Circle
size={8}
class={`${updatePillDotTone()} shrink-0 ${props.updateStatus?.state === "available" ? "animate-pulse" : ""}`}
/>
}
>
<Loader2 size={14} class="animate-spin text-white/90" />
<Loader2 size={13} class={`animate-spin shrink-0 ${updatePillDotTone()}`} />
</Show>
<span class="text-[11px] font-semibold text-white">{updatePillLabel()}</span>
<span class="text-[11px]">{updatePillLabel()}</span>
<Show when={props.updateStatus?.version}>
{(version) => (
<span class="hidden sm:inline text-[11px] text-white/80 font-mono">v{version()}</span>
<span class={`hidden sm:inline font-mono text-[10px] ${updatePillVersionTone()}`}>v{version()}</span>
)}
</Show>
</button>
Expand Down
71 changes: 58 additions & 13 deletions packages/app/src/app/pages/session.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import {
Check,
ChevronDown,
ChevronRight,
Circle,
Cpu,
HeartPulse,
HardDrive,
Expand Down Expand Up @@ -2121,12 +2122,50 @@ export default function SessionView(props: SessionViewProps) {
return "Update available";
});

const updatePillTone = createMemo(() => {
const updatePillButtonTone = createMemo(() => {
const state = props.updateStatus?.state;
if (state === "ready") {
return "border-transparent bg-green-9 text-white shadow-[0_2px_10px_rgba(22,163,74,0.35)] hover:bg-green-10";
return props.anyActiveRuns
? "text-amber-11 hover:text-amber-11 hover:bg-amber-3/35"
: "text-green-11 hover:text-green-11 hover:bg-green-3/35";
}
if (state === "downloading") {
return "text-blue-11 hover:text-blue-11 hover:bg-blue-3/35";
}
return "text-emerald-11 hover:text-emerald-11 hover:bg-emerald-3/35";
});

const updatePillBorderTone = createMemo(() => {
const state = props.updateStatus?.state;
if (state === "ready") {
return props.anyActiveRuns ? "border-amber-7/35" : "border-green-7/35";
}
if (state === "downloading") {
return "border-blue-7/35";
}
return "border-emerald-7/35";
});

const updatePillDotTone = createMemo(() => {
const state = props.updateStatus?.state;
if (state === "ready") {
return props.anyActiveRuns ? "text-amber-10 fill-amber-10" : "text-green-10 fill-green-10";
}
if (state === "downloading") {
return "text-blue-10";
}
return "text-emerald-10 fill-emerald-10";
});

const updatePillVersionTone = createMemo(() => {
const state = props.updateStatus?.state;
if (state === "ready") {
return props.anyActiveRuns ? "text-amber-11/75" : "text-green-11/75";
}
if (state === "downloading") {
return "text-blue-11/75";
}
return "border-transparent bg-dls-accent text-white shadow-[0_2px_10px_rgba(var(--dls-accent-rgb),0.35)] hover:bg-[var(--dls-accent-hover)]";
return "text-emerald-11/75";
});

const updatePillTitle = createMemo(() => {
Expand Down Expand Up @@ -2187,23 +2226,26 @@ export default function SessionView(props: SessionViewProps) {
<Show when={showUpdatePill()}>
<button
type="button"
class={`mb-3 w-full flex h-9 items-center gap-2 rounded-xl border px-3 text-xs font-medium transition-all hover:-translate-y-[1px] ${updatePillTone()}`}
class={`group mb-3 w-full flex items-center gap-2 rounded-md px-2 py-1.5 text-xs font-medium transition-colors ${updatePillButtonTone()}`}
onClick={handleUpdatePillClick}
title={updatePillTitle()}
aria-label={updatePillTitle()}
>
<Show
when={props.updateStatus?.state === "downloading"}
fallback={
<span class="w-2 h-2 rounded-full bg-white/85" />
<Circle
size={8}
class={`${updatePillDotTone()} shrink-0 ${props.updateStatus?.state === "available" ? "group-hover:animate-pulse" : ""}`}
/>
}
>
<Loader2 size={14} class="animate-spin text-white/90" />
<Loader2 size={13} class={`animate-spin shrink-0 ${updatePillDotTone()}`} />
</Show>
<span class="text-[11px] font-semibold text-white">{updatePillLabel()}</span>
<span class="flex-1 text-left">{updatePillLabel()}</span>
<Show when={props.updateStatus?.version}>
{(version) => (
<span class="ml-auto text-[11px] text-white/80 font-mono">v{version()}</span>
<span class={`ml-auto font-mono text-[10px] ${updatePillVersionTone()}`}>v{version()}</span>
)}
</Show>
</button>
Expand Down Expand Up @@ -2572,23 +2614,26 @@ export default function SessionView(props: SessionViewProps) {
<Show when={showUpdatePill()}>
<button
type="button"
class={`md:hidden flex h-8 items-center gap-2 rounded-full border px-3 text-xs font-medium transition-colors ${updatePillTone()}`}
class={`md:hidden flex items-center gap-1.5 rounded-full border bg-white px-2.5 py-1 text-xs font-medium shadow-sm transition-colors active:scale-[0.99] ${updatePillBorderTone()} ${updatePillButtonTone()}`}
onClick={handleUpdatePillClick}
title={updatePillTitle()}
aria-label={updatePillTitle()}
>
<Show
when={props.updateStatus?.state === "downloading"}
fallback={
<span class="w-2 h-2 rounded-full bg-white/85" />
<Circle
size={8}
class={`${updatePillDotTone()} shrink-0 ${props.updateStatus?.state === "available" ? "animate-pulse" : ""}`}
/>
}
>
<Loader2 size={14} class="animate-spin text-white/90" />
<Loader2 size={13} class={`animate-spin shrink-0 ${updatePillDotTone()}`} />
</Show>
<span class="text-[11px] font-semibold text-white">{updatePillLabel()}</span>
<span class="text-[11px]">{updatePillLabel()}</span>
<Show when={props.updateStatus?.version}>
{(version) => (
<span class="hidden sm:inline text-[11px] text-white/80 font-mono">v{version()}</span>
<span class={`hidden sm:inline font-mono text-[10px] ${updatePillVersionTone()}`}>v{version()}</span>
)}
</Show>
</button>
Expand Down
40 changes: 28 additions & 12 deletions packages/app/src/app/pages/settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { For, Match, Show, Switch, createEffect, createMemo, createSignal, onMou
import { formatBytes, formatRelativeTime, isTauriRuntime } from "../utils";

import Button from "../components/button";
import { HardDrive, MessageCircle, PlugZap, RefreshCcw, Shield, Smartphone, X } from "lucide-solid";
import { CircleAlert, HardDrive, MessageCircle, PlugZap, RefreshCcw, Smartphone, X, Zap } from "lucide-solid";
import type { OpencodeConnectStatus, ProviderListItem, SettingsTab, StartupPreference } from "../types";
import type {
OpenworkAuditEntry,
Expand Down Expand Up @@ -842,10 +842,14 @@ export default function SettingsView(props: SettingsViewProps) {
Enables debug tools, diagnostics, and the Developer tab.
</div>
<div class="pt-1 flex flex-wrap items-center gap-3">
<Button variant={props.developerMode ? "secondary" : "outline"} onClick={props.toggleDeveloperMode}>
<Shield size={16} />
<button
type="button"
class="bg-white hover:bg-gray-50 text-gray-7 border border-gray-6 rounded-md px-3 py-1.5 flex items-center gap-1.5 shadow-sm transition-all duration-200 active:bg-gray-3 text-xs font-medium"
onClick={props.toggleDeveloperMode}
>
<Zap size={14} class="text-gray-9" />
{props.developerMode ? "Disable Developer Mode" : "Enable Developer Mode"}
</Button>
</button>
<div class="text-xs text-gray-10">
{props.developerMode ? "Developer panel enabled." : "Enable this to access the Developer panel."}
</div>
Expand All @@ -857,23 +861,35 @@ export default function SettingsView(props: SettingsViewProps) {
<div class="text-xs text-gray-9">{props.headerStatus}</div>
<div class="text-xs text-gray-8 font-mono">{props.baseUrl}</div>
<div class="pt-2 flex flex-wrap gap-2">
<Button
variant="outline"
<button
type="button"
class="bg-white hover:bg-gray-50 text-gray-7 border border-gray-6 rounded-md px-3 py-1.5 flex items-center gap-1.5 shadow-sm transition-all duration-200 active:bg-gray-3 text-xs font-medium disabled:opacity-60 disabled:cursor-not-allowed"
onClick={handleReconnectOpenworkServer}
disabled={props.busy || props.openworkReconnectBusy || !props.openworkServerUrl.trim()}
>
<RefreshCcw size={14} class={props.openworkReconnectBusy ? "animate-spin" : ""} />
<RefreshCcw size={14} class={`text-gray-9 ${props.openworkReconnectBusy ? "animate-spin" : ""}`} />
{props.openworkReconnectBusy ? "Reconnecting..." : "Reconnect server"}
</Button>
</button>
<Show when={isLocalEngineRunning()}>
<Button variant="danger" onClick={props.stopHost} disabled={props.busy}>
<button
type="button"
class="bg-red-3 hover:bg-red-4 text-red-11 rounded-md px-3 py-1.5 flex items-center gap-1.5 transition-all duration-200 active:scale-[0.98] text-xs font-medium border border-transparent hover:border-red-7/30 disabled:opacity-60 disabled:cursor-not-allowed"
onClick={props.stopHost}
disabled={props.busy}
>
<CircleAlert size={14} />
Stop local server
</Button>
</button>
</Show>
<Show when={!isLocalEngineRunning() && props.openworkServerStatus === "connected"}>
<Button variant="outline" onClick={props.stopHost} disabled={props.busy}>
<button
type="button"
class="bg-white hover:bg-gray-50 text-gray-7 border border-gray-6 rounded-md px-3 py-1.5 flex items-center gap-1.5 shadow-sm transition-all duration-200 active:bg-gray-3 text-xs font-medium disabled:opacity-60 disabled:cursor-not-allowed"
onClick={props.stopHost}
disabled={props.busy}
>
Disconnect server
</Button>
</button>
</Show>
</div>
<Show when={openworkReconnectStatus()}>
Expand Down
Loading