diff --git a/.github/workflows/release-dev.yml b/.github/workflows/release-dev.yml index 115c586..17549c7 100644 --- a/.github/workflows/release-dev.yml +++ b/.github/workflows/release-dev.yml @@ -30,5 +30,4 @@ jobs: push: true build-args: | VERSION=dev - COMMIT=${{ github.sha }} tags: ghcr.io/lone-cloud/prism:dev diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1e5a488..481984e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -26,18 +26,17 @@ jobs: - name: Build binaries run: | VERSION=$(cat VERSION) - COMMIT=$(git rev-parse --short HEAD) # Linux AMD64 CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build \ -trimpath \ - -ldflags="-s -w -X main.version=$VERSION -X main.commit=$COMMIT" \ + -ldflags="-s -w -X main.version=$VERSION" \ -o prism-linux-amd64 . # Linux ARM64 CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build \ -trimpath \ - -ldflags="-s -w -X main.version=$VERSION -X main.commit=$COMMIT" \ + -ldflags="-s -w -X main.version=$VERSION" \ -o prism-linux-arm64 . - name: Create GitHub Release @@ -72,7 +71,6 @@ jobs: push: true build-args: | VERSION=${{ steps.version.outputs.tag }} - COMMIT=${{ github.sha }} tags: | ghcr.io/lone-cloud/prism:${{ steps.version.outputs.tag }} ghcr.io/lone-cloud/prism:latest diff --git a/Dockerfile b/Dockerfile index bb24e02..eb72fb4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,6 @@ FROM golang:1.25-alpine3.23 AS builder ARG VERSION=dev -ARG COMMIT=unknown WORKDIR /build @@ -14,7 +13,7 @@ COPY . . RUN CGO_ENABLED=0 GOOS=linux go build \ -trimpath \ - -ldflags="-w -s -X main.version=${VERSION} -X main.commit=${COMMIT}" \ + -ldflags="-w -s -X main.version=${VERSION}" \ -o prism . FROM debian:trixie-slim diff --git a/Makefile b/Makefile index 2626119..2786b06 100644 --- a/Makefile +++ b/Makefile @@ -2,14 +2,13 @@ BINARY_NAME=prism VERSION?=$(shell cat VERSION 2>/dev/null || echo "dev") -COMMIT?=$(shell git rev-parse --short HEAD 2>/dev/null || echo "unknown") GOBIN?=$(shell command -v go >/dev/null 2>&1 && go env GOPATH || echo "${HOME}/go")/bin export PATH := $(GOBIN):$(PATH) all: fix build build: - go build -ldflags="-s -w -X main.version=$(VERSION) -X main.commit=$(COMMIT)" -o $(BINARY_NAME) . + go build -ldflags="-s -w -X main.version=$(VERSION)" -o $(BINARY_NAME) . start: build ./$(BINARY_NAME) diff --git a/VERSION b/VERSION index 7dff5b8..f477849 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.2.1 \ No newline at end of file +0.2.2 \ No newline at end of file diff --git a/main.go b/main.go index cbf6b04..6504531 100644 --- a/main.go +++ b/main.go @@ -21,7 +21,6 @@ var publicAssets embed.FS var ( version = "dev" - commit = "unknown" ) func init() { @@ -30,7 +29,7 @@ func init() { func main() { if len(os.Args) > 1 && os.Args[1] == "version" { - fmt.Printf("Prism %s (%s)\n", version, commit) + fmt.Printf("Prism %s\n", version) return } diff --git a/public/index.css b/public/index.css index 7117dca..79abcd8 100644 --- a/public/index.css +++ b/public/index.css @@ -1,3 +1,4 @@ +/* Variables */ :root { --bg-primary: #f5f5f5; --bg-secondary: #fdfdfd; @@ -35,7 +36,7 @@ --spinner-track: #4a4a4a; } -/* CSS Reset */ +/* Reset */ *, *::before, *::after { @@ -78,9 +79,11 @@ h6 { overflow-wrap: break-word; } -/* Styles */ +/* Base */ body { font-family: system-ui; + line-height: 1.5; + -webkit-font-smoothing: antialiased; max-width: 50rem; margin: 1rem auto; padding: 0 1.25rem 1.25rem; @@ -88,6 +91,22 @@ body { color: var(--text-primary); } +h2 { + margin-bottom: 1.25rem; +} + +a { + color: var(--accent); + text-decoration: underline; +} + +a:hover { + opacity: 0.8; +} + +/* Components */ + +/* Cards */ .card { background: var(--bg-secondary); border-radius: 0.5rem; @@ -128,19 +147,7 @@ details[open] > .card-header::before { padding: 0 1.25rem 1.25rem 1.25rem; } -h2 { - margin-bottom: 1.25rem; -} - -a { - color: var(--accent); - text-decoration: underline; -} - -a:hover { - opacity: 0.8; -} - +/* Tooltips */ .channel-badge:has(.tooltip), .integration-status:has(.tooltip) { cursor: help; @@ -183,6 +190,7 @@ a:hover { opacity: 1; } +/* Theme Toggle */ .theme-toggle { position: fixed; bottom: 1.5rem; @@ -201,6 +209,7 @@ a:hover { opacity: 1; } +/* App List */ .app-list { list-style: none; padding: 0; @@ -300,6 +309,7 @@ a:hover { filter: brightness(0.85); } +/* Loading Spinner */ .loading { color: var(--text-secondary); display: flex; @@ -322,6 +332,7 @@ a:hover { } } +/* Integrations */ .integration-card { background: var(--bg-secondary); border-radius: 0.5rem; @@ -405,6 +416,7 @@ details[open] > .integration-header::before { color: var(--text-on-color); } +/* Forms */ .auth-form { margin-top: 1rem; max-width: 400px; @@ -433,6 +445,7 @@ details[open] > .integration-header::before { font-size: 1rem; } +/* Buttons */ .btn-primary, .btn-secondary, .btn-danger { @@ -500,6 +513,7 @@ details[open] > .integration-header::before { color: var(--text-on-color); } +/* QR Code */ .qr-container { margin-top: 1rem; } diff --git a/public/index.html b/public/index.html index 9a05be9..40c1e34 100644 --- a/public/index.html +++ b/public/index.html @@ -4,7 +4,7 @@
Error: ${msg}
`; + qrContainer.style.display = 'block'; + btn.style.display = 'inline-block'; + }; - btn.style.display = 'none'; - qrContainer.style.display = 'none'; + btn.style.display = 'none'; + qrContainer.style.display = 'none'; - try { - const response = await fetch('/api/signal/link', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ device_name: 'Prism' }), - }); + try { + const response = await fetch('/api/signal/link', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ device_name: 'Prism' }), + }); - if (!response.ok) { - const error = await response.json(); - qrContainer.innerHTML = `Error: ${error.error || 'Failed to generate link'}
`; - qrContainer.style.display = 'block'; - btn.style.display = 'inline-block'; - return; - } - - const data = await response.json(); - const qrUrl = `https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=${encodeURIComponent(data.qr_code)}`; - qrCode.src = qrUrl; - qrContainer.style.display = 'block'; - - signalLinkingPoll = setInterval(async () => { - try { - const statusResp = await fetch('/api/signal/status'); - const statusData = await statusResp.json(); - - if (statusData.linked) { - clearInterval(signalLinkingPoll); - qrContainer.innerHTML = - 'Linked! Refreshing...
'; - setTimeout(() => location.reload(), 1000); - } - } catch (err) { - console.error('Status check failed:', err); - } - }, 2000); - } catch (err) { - qrContainer.innerHTML = `Error: ${err.message}
`; - qrContainer.style.display = 'block'; - btn.style.display = 'inline-block'; - } - } - - if (e.target.classList.contains('reload-btn')) { - location.reload(); - } - - if (e.target.classList.contains('delete-telegram-btn')) { - e.preventDefault(); - - if (!confirm('Unlink Telegram integration?')) { + if (!response.ok) { + const error = await response.json(); + showQrError(error.error || 'Failed to generate link'); return; } - const btn = e.target; - btn.disabled = true; + const data = await response.json(); + const qrUrl = `https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=${encodeURIComponent(data.qr_code)}`; + qrCode.src = qrUrl; + qrContainer.style.display = 'block'; - try { - const response = await fetch('/api/telegram/auth', { - method: 'DELETE', - }); + signalLinkingPoll = setInterval(async () => { + try { + const statusResp = await fetch('/api/signal/status'); + const statusData = await statusResp.json(); - if (response.ok) { - location.reload(); - } else { - const error = await response.json(); - alert(`Error: ${error.error || 'Failed to unlink integration'}`); - btn.disabled = false; + if (statusData.linked) { + clearInterval(signalLinkingPoll); + qrContainer.innerHTML = + 'Linked! Refreshing...
'; + setTimeout(() => location.reload(), 1000); + } + } catch (err) { + console.error('Status check failed:', err); } - } catch (err) { - alert(`Error: ${err.message}`); + }, 2000); + } catch (err) { + showQrError(err.message); + } +} + +// biome-ignore lint/correctness/noUnusedVariables: called from HTML onclick +async function deleteTelegram(btn) { + if (!confirm('Unlink Telegram integration?')) return; + + btn.disabled = true; + + try { + const response = await fetch('/api/telegram/auth', { method: 'DELETE' }); + + if (response.ok) { + location.reload(); + } else { + const error = await response.json(); + alert(`Error: ${error.error || 'Failed to unlink integration'}`); btn.disabled = false; } + } catch (err) { + alert(`Error: ${err.message}`); + btn.disabled = false; } +} - if (e.target.classList.contains('delete-proton-btn')) { - if (!confirm('Unlink Proton Mail integration?')) { - return; - } - - try { - const response = await fetch('/api/proton/auth', { - method: 'DELETE', - }); - - if (response.ok) { - location.reload(); - } else { - const error = await response.json(); - alert(`Error: ${error.error || 'Failed to unlink integration'}`); - } - } catch (err) { - alert(`Error: ${err.message}`); +// biome-ignore lint/correctness/noUnusedVariables: called from HTML onclick +async function deleteProton(btn) { + if (!confirm('Unlink Proton Mail integration?')) return; + + btn.disabled = true; + + try { + const response = await fetch('/api/proton/auth', { method: 'DELETE' }); + + if (response.ok) { + location.reload(); + } else { + const error = await response.json(); + alert(`Error: ${error.error || 'Failed to unlink integration'}`); + btn.disabled = false; } + } catch (err) { + alert(`Error: ${err.message}`); + btn.disabled = false; } -}); +} diff --git a/public/manifest.json b/public/manifest.json index cfe4963..b1fe35f 100644 --- a/public/manifest.json +++ b/public/manifest.json @@ -5,7 +5,7 @@ "start_url": "/", "display": "standalone", "background_color": "#1a1a1a", - "theme_color": "#8159b8", + "theme_color": "#60c5ff", "icons": [ { "src": "/favicon.webp", diff --git a/public/theme.js b/public/theme.js index e2cbdcb..600b8c0 100644 --- a/public/theme.js +++ b/public/theme.js @@ -1,8 +1,7 @@ -const themes = ['system', 'light', 'dark']; -let currentIndex = 0; - const savedTheme = localStorage.getItem('theme') || 'system'; -currentIndex = themes.indexOf(savedTheme); +const themes = ['system', 'light', 'dark']; +let currentIndex = themes.indexOf(savedTheme); + if (currentIndex === -1) currentIndex = 0; function applyTheme(theme) { diff --git a/service/integration/proton/templates/proton-content.html b/service/integration/proton/templates/proton-content.html index c44e169..c7231f4 100644 --- a/service/integration/proton/templates/proton-content.html +++ b/service/integration/proton/templates/proton-content.html @@ -1,8 +1,8 @@ {{if .Connected}} - + {{else}}Link Proton Account:
-