feat(ui): the running version in the sidebar, linked to its release
ci / gate (push) Successful in 13m48s

The sidebar now reads "wallet v0.3.0" under the mark, and the version
opens its release tag on git.lair.cafe in the system browser. The number
is the binary's own, from app_info, so a packaged build always names the
tag it was cut from. The opener's allow-list gains this repository's
URLs and nothing else on that host.

On a dev run with crystal_alice unlocked: the tagline rendered with the
version in mono, not uppercased; opening the tag URL resolved, and
git.lair.cafe/other/repo was refused by the opener.

Closes #70

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NUx7SPonBnB3ofU4mH41WT
This commit is contained in:
2026-10-09 10:47:05 +03:00
co-authored by Claude Opus 5.5
parent bfb016d76f
commit b059a8d5d0
4 changed files with 34 additions and 6 deletions
+2 -2
View File
@@ -15,8 +15,8 @@ permissions = [
"dialog:allow-open",
# Copy an address from the receive screen. Write only: the app never reads what is on the clipboard.
"clipboard-manager:allow-write-text",
# Open an account's page on the public explorer in the system browser, from the history screen. Only these two hosts, and only URLs: never a file, never a path.
{ identifier = "opener:allow-open-url", allow = [{ url = "https://explorer.quantus.com/*" }, { url = "https://blackbeard.observer/*" }] },
# Open pages in the system browser: an account on the public explorer, from the history screen, and the release this build came from, from the version in the sidebar. Only these hosts (and only this repository on the forge), and only URLs: never a file, never a path.
{ identifier = "opener:allow-open-url", allow = [{ url = "https://explorer.quantus.com/*" }, { url = "https://blackbeard.observer/*" }, { url = "https://git.lair.cafe/blackbeard/wallet/*" }] },
# Check for, download and install a release signed with the key in tauri.conf.json; the manifest lives on our own host. The person is asked first, always.
"updater:default",
# Relaunch after an accepted update. Only relaunch: no exit, no restart of anything else.
+2 -2
View File
@@ -1,5 +1,5 @@
// Open a page in the system browser. Only the explorer hosts allow-listed
// in the capability file will open; anything else is refused by Rust.
// Open a page in the system browser. Only the explorer hosts and the
// wallet's own repository, allow-listed in the capability file, will open; anything else is refused by Rust.
import { openUrl } from '@tauri-apps/plugin-opener'
+21 -2
View File
@@ -1,5 +1,6 @@
import { NavLink } from 'react-router-dom'
import { useLock, useSession } from '../api/hooks'
import { useAppInfo, useLock, useSession } from '../api/hooks'
import { openExternal } from '../api/opener'
import { NetworkSwitcher } from './NetworkSwitcher'
const SECTIONS = [
@@ -11,7 +12,13 @@ const SECTIONS = [
{ to: '/settings', label: 'Settings' },
]
/** The release tag this build was cut from, on the repository. */
function tagUrl(version: string): string {
return `https://git.lair.cafe/blackbeard/wallet/releases/tag/v${version}`
}
export function Sidebar() {
const info = useAppInfo()
const session = useSession()
const lock = useLock()
return (
@@ -20,7 +27,19 @@ export function Sidebar() {
<div className="mark-name">
black<span>beard</span>
</div>
<div className="mark-tagline">wallet</div>
<div className="mark-tagline">
wallet
{info.data && (
<button
className="linkish mark-version numeral"
type="button"
title={`Release v${info.data.version} on git.lair.cafe`}
onClick={() => void openExternal(tagUrl(info.data.version))}
>
v{info.data.version}
</button>
)}
</div>
</div>
<nav className="sections" aria-label="Section">
{SECTIONS.map((s) => (
+9
View File
@@ -105,6 +105,15 @@ select {
color: var(--text-muted);
margin-top: 6px;
}
.mark-version {
margin-left: 8px;
font-size: 11px;
letter-spacing: 0.02em;
text-transform: none;
}
.mark-version:hover {
color: var(--text-primary);
}
.sections {
display: flex;
flex-direction: column;