Documentation
¶
Index ¶
- Variables
- func ConfirmRedownload(filename string) bool
- func DisplayProgressBar() bool
- func Errorf(format string, a ...any) (n int, err error)
- func Errorln(a ...any) (n int, err error)
- func IsTerminal(f *os.File) bool
- func NewExtractorModel(url string, onQuit func()) extractorModel
- func NewProgram(numConns int) *tea.Program
- func NewTUIModel(numConns int, willVerify bool, batchCurrent, batchTotal int, ...) tuiModel
- func NewTUIModelWithHistory(numConns int, willVerify bool, batchCurrent, batchTotal int, ...) tuiModel
- func PrintHelp()
- func PrintVerifySummary(ok bool, detail string)
- func Printf(format string, a ...any) (n int, err error)
- func ResumePrompt(taskName string, downloaded, total int64) (bool, error)
- func RunExtractorTUI(opts ExtractorRunOptions, worker func(ExtractorSelector) error) error
- func RunWithTUI(opts RunOptions, fn func() error) error
- func ShowMessage(msgType MessageType, title, message string)
- func ThemeBox(border lipgloss.Color, width int) lipgloss.Style
- func Warnf(format string, a ...any) (n int, err error)
- type BatchFinishedMsg
- type BatchItemBeginMsg
- type BatchItemEndMsg
- type BatchItemResult
- type BatchItemSnapshot
- type BatchItemStatus
- type BatchRunOptions
- type BatchSummary
- type CassetteItem
- type CassetteShelf
- func (s *CassetteShelf) Items() []CassetteItem
- func (s *CassetteShelf) Len() int
- func (s *CassetteShelf) SetActive(i int)
- func (s *CassetteShelf) SetMeta(i int, title, channel, resolution string, dur time.Duration)
- func (s *CassetteShelf) SetStatus(i int, st CassetteStatus, errMsg string)
- func (s *CassetteShelf) Tick()
- func (s *CassetteShelf) View(termWidth int) string
- type CassetteStatus
- type Console
- type DownloadDoneMsg
- type DownloadErrorMsg
- type DownloadStartMsg
- type ExtractorDoneMsg
- type ExtractorErrorMsg
- type ExtractorFormat
- type ExtractorFormatsMsg
- type ExtractorLogMsg
- type ExtractorMetaMsg
- type ExtractorOutputMsg
- type ExtractorPhaseMsg
- type ExtractorProgressMsg
- type ExtractorResetDeckMsg
- type ExtractorRunOptions
- type ExtractorSelectionMsg
- type ExtractorSelector
- type ExtractorShelfActiveMsg
- type ExtractorShelfMetaMsg
- type ExtractorShelfSeedMsg
- type ExtractorShelfStatusMsg
- type ExtractorURLMsg
- type JoinDoneMsg
- type JoinProgressMsg
- type JoinStartMsg
- type LogMsg
- type MessageType
- type MixerAnimation
- type MixerMeta
- type MixerMode
- type PartDoneMsg
- type PartProgressMsg
- type RunOptions
- type SkippingMsg
- type StoppingMsg
- type UI
- type VCRAnimation
- func (v VCRAnimation) CurrentAudio() (ExtractorFormat, bool)
- func (v VCRAnimation) CurrentContainer() string
- func (v VCRAnimation) CurrentVideo() (ExtractorFormat, bool)
- func (v *VCRAnimation) CycleAudio(step int)
- func (v *VCRAnimation) CycleContainer(step int)
- func (v *VCRAnimation) CycleVideo(step int)
- func (v *VCRAnimation) Frame() int
- func (v VCRAnimation) HasFormats() bool
- func (v *VCRAnimation) Mode() VCRMode
- func (v VCRAnimation) Selection() ExtractorSelectionMsg
- func (v *VCRAnimation) SetFormats(video, audio []ExtractorFormat, containers []string)
- func (v *VCRAnimation) SetMeta(m VCRMeta)
- func (v *VCRAnimation) SetMode(m VCRMode)
- func (v *VCRAnimation) Tick()
- func (v *VCRAnimation) Update(pct float64, downloaded, total int64, speedBPS float64, eta time.Duration, ...)
- func (v VCRAnimation) View() string
- type VCRMeta
- type VCRMode
- type VerifyDetails
- type VerifyDoneMsg
- type VerifyStartMsg
Constants ¶
This section is empty.
Variables ¶
var ( Stdout io.Writer = os.Stdout Stderr io.Writer = os.Stderr DefaultUI = Console{Stdout: Stdout, Stderr: Stderr} // Log is the global structured console logger used when the TUI is inactive. // It uses charmbracelet/log with custom lipgloss styles matching the TUI palette. Log *charmlog.Logger )
Stdout / Stderr — direct os handles. termenv (used by lipgloss) detects the active output's capabilities and writes appropriate ANSI sequences, including on modern Windows terminals (10+, 2019+) which support VT processing natively. go-colorable is no longer required.
var DisplayProgress = true
DisplayProgress controls whether the TUI progress bar is shown. Set to false in tests to disable TUI output.
var Program *tea.Program
Program is the global tea.Program; goroutines call Program.Send() to deliver messages.
var Theme = theme{ Phosphor: lipgloss.Color("#73E0FF"), Amber: lipgloss.Color("#FFB75A"), Mint: lipgloss.Color("#5EE6A1"), Magenta: lipgloss.Color("#FF5478"), Steel: lipgloss.Color("#5A6B85"), Slate: lipgloss.Color("#3A475C"), Frost: lipgloss.Color("#E8F1F8"), DeepCyan: lipgloss.Color("#1E7A99"), }
Functions ¶
func ConfirmRedownload ¶
func DisplayProgressBar ¶
func DisplayProgressBar() bool
DisplayProgressBar returns true when running in interactive TTY mode.
func IsTerminal ¶
IsTerminal checks if f is connected to a real TTY.
func NewExtractorModel ¶
func NewExtractorModel(url string, onQuit func()) extractorModel
NewExtractorModel constructs the extractor-mode TUI model.
func NewProgram ¶
NewProgram creates and starts a new Bubble Tea program for the TUI.
func NewTUIModel ¶
func NewTUIModel(numConns int, willVerify bool, batchCurrent, batchTotal int, onSkip, onQuit func()) tuiModel
NewTUIModel creates a new TUI model for the given number of connections. batchCurrent and batchTotal are 1-based; pass 0,0 when not in batch mode. onSkip is non-nil only in batch mode and is invoked when the user presses 's'. onQuit is invoked on 'q' / 'ctrl+c'; both default to no-ops if nil.
func NewTUIModelWithHistory ¶
func NewTUIModelWithHistory( numConns int, willVerify bool, batchCurrent, batchTotal int, history []BatchItemSnapshot, onSkip, onQuit func(), ) tuiModel
NewTUIModelWithHistory is the variant that lets the caller seed the per-batch-item lifecycle record. Used by RunWithTUI when the parent batch loop has accumulated skip / fail / done history before this TUI session was started.
func PrintVerifySummary ¶
PrintVerifySummary writes a styled one-line verify result to the terminal using charmbracelet/log (works after the TUI alt-screen has closed).
func ResumePrompt ¶
ResumePrompt shows an animated TUI prompt asking whether to resume a partial download. Returns true if user wants to resume, false to start fresh.
func RunExtractorTUI ¶
func RunExtractorTUI(opts ExtractorRunOptions, worker func(ExtractorSelector) error) error
RunExtractorTUI starts a Bubble Tea program using the extractor model and runs `worker` in a goroutine. The worker is expected to send Extractor* messages via the package-level Program handle. Mirrors the shape of RunWithTUI: when stdout isn't a TTY, the worker runs directly and TUI sends are no-ops (the package-level Program is nil).
`worker` is invoked with an ExtractorSelector that blocks until the user commits a format choice in the VCR's browsing mode. Workers that bypass the selector (live streams, no format table) simply don't call it. In the non-TTY fallback path the selector returns immediately with empty strings ("use defaults").
func RunWithTUI ¶
func RunWithTUI(opts RunOptions, fn func() error) error
func ShowMessage ¶
func ShowMessage(msgType MessageType, title, message string)
ShowMessage displays a styled message box and returns immediately.
Types ¶
type BatchFinishedMsg ¶
BatchFinishedMsg signals all items have run; render the final summary frame and auto-quit.
type BatchItemBeginMsg ¶
type BatchItemBeginMsg struct {
Index int // 0-based index into the batch
URL string
FileName string
}
BatchItemBeginMsg signals the start of a new item inside a persistent batch TUI program. The model resets per-item state but keeps the SAN cabinet, history, and program alive (no alt-screen toggling).
type BatchItemEndMsg ¶
type BatchItemEndMsg struct {
Index int
Status BatchItemStatus
Reason string
}
BatchItemEndMsg signals an item finished (success / fail / skip / abort). Updates the SAN bay status without quitting the program.
type BatchItemResult ¶
type BatchItemResult struct {
Status BatchItemStatus
Reason string
}
type BatchItemSnapshot ¶
type BatchItemSnapshot struct {
Label string
Status BatchItemStatus
}
type BatchItemStatus ¶
type BatchItemStatus int
const ( BatchItemQueued BatchItemStatus = iota BatchItemDone BatchItemSkipped BatchItemFailed BatchItemAborted )
type BatchRunOptions ¶
type BatchRunOptions struct {
Ctx context.Context
NumConns int
WillVerify bool
Items []BatchItemSnapshot
URLs []string
OnQuit func()
OnSkipCurrent func()
}
BatchRunOptions configures a persistent batch TUI session.
type BatchSummary ¶
BatchSummary aggregates the tally over the whole batch.
func RunBatch ¶
func RunBatch(opts BatchRunOptions, runItem func(idx int) BatchItemResult) (BatchSummary, error)
type CassetteItem ¶
type CassetteItem struct {
URL string
Title string // resolved from yt-dlp metadata; empty until probed
Channel string // populates the channel-tint sticker chip
Duration time.Duration // 00:00 until probed
Resolution string // "1080p60" — only on lush tier
Status CassetteStatus
Err string // populated on failure for the end-of-batch summary
}
CassetteItem is one row of the shelf — everything renderable about a single URL in the batch. Field renames cascade nowhere: the shelf is the only consumer.
type CassetteShelf ¶
type CassetteShelf struct {
// contains filtered or unexported fields
}
CassetteShelf is the widget. Built once at batch start, mutated via the setter methods below as the orchestrator advances.
func NewCassetteShelf ¶
func NewCassetteShelf(urls []string) *CassetteShelf
NewCassetteShelf seeds the widget from a URL list. Labels read as "tape NN" until probes resolve real titles.
func (*CassetteShelf) Items ¶
func (s *CassetteShelf) Items() []CassetteItem
Items returns a defensive copy so callers can iterate without racing concurrent mutations. Used by the end-of-batch summary.
func (*CassetteShelf) Len ¶
func (s *CassetteShelf) Len() int
Len reports how many tapes are on the shelf.
func (*CassetteShelf) SetActive ¶
func (s *CassetteShelf) SetActive(i int)
SetActive marks one cassette as the live tape. Pass -1 to indicate no tape is currently in the deck (between items, or post-batch).
func (*CassetteShelf) SetMeta ¶
func (s *CassetteShelf) SetMeta(i int, title, channel, resolution string, dur time.Duration)
SetMeta fills in metadata that arrives from yt-dlp's probe. Empty fields on the incoming item are ignored so partial probes don't blank out previously-set values.
func (*CassetteShelf) SetStatus ¶
func (s *CassetteShelf) SetStatus(i int, st CassetteStatus, errMsg string)
SetStatus updates one cassette's lifecycle state. errMsg is recorded only when the new status is CassetteFailed.
func (*CassetteShelf) Tick ¶
func (s *CassetteShelf) Tick()
Tick advances the lift animation for the active cassette and the reel-rotation frame counter. Drives both the "tape pulls out of the shelf" effect and the spinning-reel illusion.
func (*CassetteShelf) View ¶
func (s *CassetteShelf) View(termWidth int) string
View renders the shelf at the requested terminal width. Returns at most cassetteShelfRows lines. The layout is computed every call so resizes (WindowSizeMsg) reflow without ceremony.
type CassetteStatus ¶
type CassetteStatus int
CassetteStatus is the lifecycle state of one tape on the shelf.
const ( CassetteQueued CassetteStatus = iota CassetteProbing CassetteReady // probe done, waiting for the deck to swing to it CassetteLoading CassettePlaying CassetteMuxing CassetteDone CassetteSkipped CassetteFailed )
type DownloadDoneMsg ¶
type DownloadDoneMsg struct{}
DownloadDoneMsg signals the entire pipeline (download + join + optional verify) finished.
type DownloadErrorMsg ¶
type DownloadErrorMsg struct{ Err error }
DownloadErrorMsg signals a fatal download error.
type DownloadStartMsg ¶
DownloadStartMsg is sent once download metadata is known.
type ExtractorDoneMsg ¶
type ExtractorDoneMsg struct{}
ExtractorDoneMsg signals success — auto-quit countdown begins.
type ExtractorErrorMsg ¶
type ExtractorErrorMsg struct{ Err error }
ExtractorErrorMsg signals a fatal error in the extractor pipeline.
type ExtractorFormat ¶
type ExtractorFormat struct {
ID string
Ext string
Resolution string
Height int
FPS float64
VCodec string
ACodec string
TBR float64
ABR float64
Filesize int64
Note string
HasVideo bool
HasAudio bool
}
ExtractorFormat mirrors extractor.Format inside the ui package so the renderer doesn't pull a dependency cycle. Populated via the ExtractorFormatsMsg pipeline.
type ExtractorFormatsMsg ¶
type ExtractorFormatsMsg struct {
Video []ExtractorFormat
Audio []ExtractorFormat
Containers []string
IsLive bool // live streams always skip the selector
}
ExtractorFormatsMsg seeds the VCR's browsing-mode selector with the format table parsed from yt-dlp's -J output. Sent immediately after the metadata message during the probe → select handshake.
An empty Video slice means there are no separately-selectable video streams; the model then skips the browser entirely and falls through to yt-dlp's default format spec.
type ExtractorLogMsg ¶
ExtractorLogMsg adds a line to the on-screen log strip.
type ExtractorMetaMsg ¶
type ExtractorMetaMsg struct {
Title string
Channel string
Duration time.Duration
Resolution string
FPS float64
VCodec string
ACodec string
Container string
HasAudio bool
OutputFile string // hint — actual path resolved post-merge
}
ExtractorMetaMsg seeds the VCR header with metadata from yt-dlp -J.
type ExtractorOutputMsg ¶
type ExtractorOutputMsg struct{ Path string }
ExtractorOutputMsg surfaces yt-dlp's resolved output path post-merge.
type ExtractorPhaseMsg ¶
type ExtractorPhaseMsg struct {
Phase string // "downloading" | "muxing" | "done" | "error"
}
ExtractorPhaseMsg switches the active panel: VCR vs Mixer vs done.
type ExtractorProgressMsg ¶
type ExtractorProgressMsg struct {
Percent float64 // 0..100
Downloaded int64
Total int64
SpeedBPS float64
ETA time.Duration
Fragment int
FragmentN int
}
ExtractorProgressMsg pushes one progress update from yt-dlp.
type ExtractorResetDeckMsg ¶
type ExtractorResetDeckMsg struct{}
ExtractorResetDeckMsg clears the deck (progress, output path, logs) between batch items so the next tape starts fresh. The VCR returns to standby until the next ExtractorMetaMsg arrives.
type ExtractorRunOptions ¶
ExtractorRunOptions configures RunExtractorTUI.
type ExtractorSelectionMsg ¶
type ExtractorSelectionMsg struct {
Spec string
Container string
HeightCeiling int
FPSFloor int
VCodec string
ABRCeiling int
Progressive bool
}
ExtractorSelectionMsg is internal — the model emits it when the user commits a format choice in browsing mode. The runner forwards the payload to the worker goroutine via a buffered channel.
In addition to the exact format spec, the message carries adaptive descriptors (height ceiling, codec hint, audio bitrate ceiling). The batch pipeline uses those to build a yt-dlp filter expression that survives videos that lack the originally-picked format IDs.
type ExtractorSelector ¶
type ExtractorSelector func(ctx context.Context) (ExtractorSelectionMsg, error)
ExtractorSelector blocks until the user commits a format selection from the VCR's browsing mode, or until ctx is cancelled. Returns the full ExtractorSelectionMsg so callers can pull both the exact spec (for single-URL runs) and the adaptive descriptors (for batch FormatAll caching). A zero-value selection means "use the default pipeline" — happens when the source has no selectable formats or the user dismissed without picking.
type ExtractorShelfActiveMsg ¶
type ExtractorShelfActiveMsg struct {
Index int
}
ExtractorShelfActiveMsg marks one cassette as the currently-playing tape. Pass Index=-1 between items or at end-of-batch.
type ExtractorShelfMetaMsg ¶
type ExtractorShelfMetaMsg struct {
Index int
Title string
Channel string
Resolution string
Duration time.Duration
}
ExtractorShelfMetaMsg fills in the metadata for one cassette as probes resolve. Fired by the eager probe pool so spine labels populate ahead of the deck reaching that tape.
type ExtractorShelfSeedMsg ¶
type ExtractorShelfSeedMsg struct {
URLs []string
}
ExtractorShelfSeedMsg installs the cassette shelf at batch start. One CassetteItem per URL. Sent before any per-tape activity so the shelf is visible from the first frame.
type ExtractorShelfStatusMsg ¶
type ExtractorShelfStatusMsg struct {
Index int
Status CassetteStatus
Err string
}
ExtractorShelfStatusMsg updates one cassette's lifecycle state.
type ExtractorURLMsg ¶
type ExtractorURLMsg struct{ URL string }
ExtractorURLMsg updates the "source" line shown above the shelf when the active tape changes mid-batch. In single-URL mode the URL is fixed at construction time and this message is never sent.
type JoinProgressMsg ¶
type JoinProgressMsg struct{ Current int }
JoinProgressMsg carries joining progress.
type JoinStartMsg ¶
type JoinStartMsg struct{ Total int }
JoinStartMsg signals the file-joining phase started.
type MessageType ¶
type MessageType int
MessageBox renders a styled message box that fits the modem theme.
const ( MessageInfo MessageType = iota MessageWarning MessageError MessageSuccess )
type MixerAnimation ¶
type MixerAnimation struct {
// contains filtered or unexported fields
}
MixerAnimation — analog-mixer themed visualization for the post-processing (ffmpeg mux) phase. Even though we don't get true progress from yt-dlp's internal ffmpeg call, we drive a believable rolling animation: VU meters on V/A channel strips, a sweeping EQ graph, motorized fader catch-up, and a master meter that pegs as the mux finishes.
func (*MixerAnimation) Frame ¶
func (m *MixerAnimation) Frame() int
func (*MixerAnimation) Mode ¶
func (m *MixerAnimation) Mode() MixerMode
func (*MixerAnimation) SetMeta ¶
func (m *MixerAnimation) SetMeta(meta MixerMeta)
func (*MixerAnimation) SetMode ¶
func (m *MixerAnimation) SetMode(mode MixerMode)
func (*MixerAnimation) Tick ¶
func (m *MixerAnimation) Tick()
Tick advances the animation. Call once per render frame.
type MixerMeta ¶
type MixerMeta struct {
VideoCodec string // tag for video channel strip
AudioCodec string // tag for audio channel strip
Container string // master section "BUS OUT" caption (mp4 / mkv / webm)
OutputFile string // shown on the master strip
Bitrate string // optional
}
MixerMeta — labels shown on the channel strips and master section.
type PartDoneMsg ¶
type PartDoneMsg struct{ Index int }
PartDoneMsg signals a chunk finished downloading successfully.
type PartProgressMsg ¶
PartProgressMsg carries incremental progress for one chunk.
type RunOptions ¶
type RunOptions struct {
// Ctx is observed for external cancellation (e.g. SIGINT routed through
// signal.NotifyContext at main). When Ctx is cancelled, RunWithTUI
// surfaces a "stopping…" overlay and waits for fn to drain.
Ctx context.Context
// OnSkip is called when the user presses 's' (batch mode only).
OnSkip func()
// OnQuit is called when the user presses 'q' / 'ctrl+c'.
OnQuit func()
NumConns int
WillVerify bool
BatchCurrent int
BatchTotal int
BatchHistory []BatchItemSnapshot
}
RunOptions configures a TUI session.
type SkippingMsg ¶
type SkippingMsg struct{}
SkippingMsg overlays a "skipping" panel for the current batch item.
type StoppingMsg ¶
type StoppingMsg struct {
// Reason renders inside the stopping panel; e.g. "Aborted by user".
Reason string
}
StoppingMsg is sent when an external cancellation (e.g. SIGINT routed through signal.NotifyContext) has been requested. The TUI overlays a "stopping" panel until the worker goroutine reports completion.
type UI ¶
type UI interface {
Printf(format string, a ...any) (n int, err error)
Println(a ...any) (n int, err error)
Errorf(format string, a ...any) (n int, err error)
Errorln(a ...any) (n int, err error)
}
UI represents simple IO output.
type VCRAnimation ¶
type VCRAnimation struct {
// contains filtered or unexported fields
}
VCRAnimation drives the on-screen VCR. Tick() advances the animation frame; Update() pushes new download progress. The renderer is pure.
func (VCRAnimation) CurrentAudio ¶
func (v VCRAnimation) CurrentAudio() (ExtractorFormat, bool)
func (VCRAnimation) CurrentContainer ¶
func (v VCRAnimation) CurrentContainer() string
func (VCRAnimation) CurrentVideo ¶
func (v VCRAnimation) CurrentVideo() (ExtractorFormat, bool)
CurrentVideo / CurrentAudio / CurrentContainer return the selected rocker positions. Returned booleans are false when the relevant list is empty (e.g. audio-only sources have no separate audio track).
func (*VCRAnimation) CycleAudio ¶
func (v *VCRAnimation) CycleAudio(step int)
func (*VCRAnimation) CycleContainer ¶
func (v *VCRAnimation) CycleContainer(step int)
func (*VCRAnimation) CycleVideo ¶
func (v *VCRAnimation) CycleVideo(step int)
CycleVideo / CycleAudio / CycleContainer advance (or rewind, with a negative step) the corresponding selector by one. Indices wrap so the rocker switch reads as endless rather than bouncing off endstops.
func (*VCRAnimation) Frame ¶
func (v *VCRAnimation) Frame() int
func (VCRAnimation) HasFormats ¶
func (v VCRAnimation) HasFormats() bool
HasFormats reports whether the browsing UI has anything to show.
func (*VCRAnimation) Mode ¶
func (v *VCRAnimation) Mode() VCRMode
func (VCRAnimation) Selection ¶
func (v VCRAnimation) Selection() ExtractorSelectionMsg
Selection builds the full format selection (exact spec + container + adaptive descriptors) from the current rocker positions. When the chosen video format is progressive (carries its own audio), the audio selector is ignored. The adaptive descriptors let downstream callers translate the pick into a yt-dlp filter expression that survives sources lacking the exact format IDs.
func (*VCRAnimation) SetFormats ¶
func (v *VCRAnimation) SetFormats(video, audio []ExtractorFormat, containers []string)
SetFormats seeds the browsing-mode selector with the format table emitted by the extractor. Defaults are highest-quality video, first audio track, mp4 container — matching yt-dlp's bv*+ba/b heuristic so "just hit enter" produces the pre-selector behaviour.
func (*VCRAnimation) SetMeta ¶
func (v *VCRAnimation) SetMeta(m VCRMeta)
func (*VCRAnimation) SetMode ¶
func (v *VCRAnimation) SetMode(m VCRMode)
func (*VCRAnimation) Tick ¶
func (v *VCRAnimation) Tick()
Tick advances the animation. Call once per render frame (~60 Hz).
func (*VCRAnimation) Update ¶
func (v *VCRAnimation) Update(pct float64, downloaded, total int64, speedBPS float64, eta time.Duration, fragment, fragmentN int)
Update pushes new download stats. Called whenever the extractor emits a DownloadProgress event.
func (VCRAnimation) View ¶
func (v VCRAnimation) View() string
View renders the entire VCR panel as a single string.
type VCRMeta ¶
type VCRMeta struct {
Title string
Channel string
Duration time.Duration
Resolution string
FPS float64
VCodec string
ACodec string
Container string
HasAudio bool // controls whether the AUDIO meter is shown
StreamLabel string // "VIDEO" / "AUDIO" / "" — drives front-LED
}
VCRMeta — the metadata strip shown above the tape window. All fields are optional; absent values render as "—".
type VCRMode ¶
type VCRMode int
VCRMode is the operational state of the VCR panel. Mirrors the extractor.Phase but stays in the ui package so the renderer never imports extractor.
type VerifyDetails ¶
type VerifyDetails struct {
SignedBy string // user id, e.g. "Linus Torvalds <torvalds@kernel.org>"
KeyID string // long key id, e.g. "ABCDEF1234567890"
Fingerprint string // 40-hex fingerprint with spaces every 4 chars
SignedAt string // signature timestamp string
Verdict string // short verdict label rendered in the verdict row
Raw string // raw gpg output, kept for the "details" pane
}
func ParseGPGOutput ¶
func ParseGPGOutput(output string) VerifyDetails
ParseGPGOutput extracts structured fields from `gpg --verify` output so the vault's detail rows show signing identity instead of raw stderr.
Recognised lines (gpg ≥ 2.2):
gpg: Signature made Mon Jan 1 12:00:00 2024 UTC gpg: using RSA key ABCDEF1234567890ABCDEF1234567890DEADBEEF gpg: Good signature from "Linus Torvalds <torvalds@kernel.org>" [unknown] Primary key fingerprint: ABCD 1234 EF56 7890 ABCD 1234 EF56 7890 ABCD 1234 gpg: BAD signature from "Mallory <mallory@example.com>"
type VerifyDoneMsg ¶
VerifyDoneMsg signals GPG verification has completed.
type VerifyStartMsg ¶
type VerifyStartMsg struct{}
VerifyStartMsg signals GPG signature verification has begun.