Let error messages stay until read; show the remote form on the welcome screen

Error messages now stay for 8 seconds or until clicked, and keep each
hint on its own line. The welcome screen shows how to start gites with
a repository on another machine. The spec follows these changes and the
new ssh options and socket folder.
This commit is contained in:
2026-10-15 15:26:16 +02:00
parent bf6ae3e2bb
commit 7b902616fe
3 changed files with 39 additions and 11 deletions
+19 -7
View File
@@ -70,7 +70,7 @@ watch(
if (!settingsLoaded) return;
clearTimeout(settingsTimer);
settingsTimer = window.setTimeout(() => {
invoke("save_settings", { value: { ...settings } }).catch((e) => showToast(`could not save settings: ${e}`));
invoke("save_settings", { value: { ...settings } }).catch((e) => showToast(`could not save settings: ${e}`, { error: true }));
}, 300);
},
{ deep: true },
@@ -117,7 +117,7 @@ async function load() {
if (data) await applyRepo(data);
} catch (e) {
// A repository already on screen stays, for example when a connection drops.
if (repo.value) showToast(`could not reload: ${e}`);
if (repo.value) showToast(`could not reload: ${e}`, { error: true });
else error.value = String(e);
} finally {
loading = false;
@@ -131,7 +131,7 @@ async function openRepo(path: string) {
await applyRepo(await invoke<RepoData>("open_repo", { path }));
} catch (e) {
// The repository that was open stays open.
showToast(`could not open ${path}: ${e}`);
showToast(`could not open ${path}: ${e}`, { error: true });
}
}
@@ -177,7 +177,7 @@ watch(
invoke("save_filters", {
repo: repoRoot,
value: { hidden: filters.hidden, rules: filters.rules, hideTags: filters.hideTags, collapseAll: collapseAll.value },
}).catch((e) => showToast(`could not save filters: ${e}`));
}).catch((e) => showToast(`could not save filters: ${e}`, { error: true }));
}, 300);
},
{ deep: true },
@@ -366,10 +366,17 @@ async function copyText(text: string) {
// ---- actions -------------------------------------------------------------
let toastTimer: number | undefined;
function showToast(text: string) {
/** Shows a short message. An error message stays longer, 8 seconds, so there is time to
* read it; a click on any message closes it. */
function showToast(text: string, { error = false } = {}) {
toast.value = text;
clearTimeout(toastTimer);
toastTimer = window.setTimeout(() => (toast.value = null), 1800);
toastTimer = window.setTimeout(() => (toast.value = null), error ? 8000 : 1800);
}
function closeToast() {
clearTimeout(toastTimer);
toast.value = null;
}
async function copyHash() {
@@ -653,7 +660,7 @@ onUnmounted(() => {
</footer>
<transition name="fade">
<div v-if="toast" class="toast">{{ toast }}</div>
<div v-if="toast" class="toast" @click="closeToast">{{ toast }}</div>
</transition>
</div>
</template>
@@ -760,6 +767,11 @@ onUnmounted(() => {
padding: 6px 14px;
border-radius: 8px;
box-shadow: 0 6px 24px #0008;
/* Keeps each line of a message on its own line, such as the hint under an ssh error. */
white-space: pre-line;
max-width: min(640px, calc(100vw - 32px));
overflow-wrap: anywhere;
cursor: pointer;
}
.fade-enter-active, .fade-leave-active { transition: opacity 0.2s; }
.fade-enter-from, .fade-leave-to { opacity: 0; }
+4 -1
View File
@@ -56,7 +56,10 @@ const name = (p: string) => p.split(/[\\/]/).filter(Boolean).pop() ?? p;
/>
<button v-else class="browse" @click="startTyping">Open on another machine…</button>
</div>
<p class="hint">You can also start gites with a path: <code>gites ~/code/my-project</code></p>
<p class="hint">
You can also start gites with a path: <code>gites ~/code/my-project</code>,
or with a repository on another machine: <code>gites myserver:/srv/app</code>
</p>
</div>
</div>
</template>