loading_skeleton.go RawHistoryFolder
1package component
2
3import (
4 "github.com/bnema/dumber/internal/ui/layout"
5 "github.com/jwijenbergh/puregotk/v4/gtk"
6)
7
8// LoadingSkeleton displays a themed loading placeholder.
9// It is intended to be embedded as an overlay while primary content is loading.
10// Shows a faded app logo and spinner.
11type LoadingSkeleton struct {
12 container layout.BoxWidget
13 content layout.BoxWidget
14 spinner layout.SpinnerWidget
15 logo layout.ImageWidget
16}
17
18const (
19 loadingSkeletonSpacing = 6
20 loadingSkeletonLogoSize = 512
21)
22
23func NewLoadingSkeleton(factory layout.WidgetFactory) *LoadingSkeleton {
24 container := factory.NewBox(layout.OrientationVertical, 0)
25 container.SetHexpand(true)
26 container.SetVexpand(true)
27 container.SetHalign(gtk.AlignFillValue)
28 container.SetValign(gtk.AlignFillValue)
29 container.SetCanFocus(false)
30 container.SetCanTarget(false)
31 container.AddCssClass("loading-skeleton")
32
33 content := factory.NewBox(layout.OrientationVertical, loadingSkeletonSpacing)
34 content.SetHalign(gtk.AlignCenterValue)
35 content.SetValign(gtk.AlignCenterValue)
36 content.SetCanFocus(false)
37 content.SetCanTarget(false)
38 content.AddCssClass("loading-skeleton-content")
39
40 spinner := factory.NewSpinner()
41 spinner.SetHalign(gtk.AlignCenterValue)
42 spinner.SetValign(gtk.AlignCenterValue)
43 spinner.SetCanFocus(false)
44 spinner.SetCanTarget(false)
45 spinner.SetSizeRequest(32, 32)
46 spinner.AddCssClass("loading-skeleton-spinner")
47
48 // Faded app logo
49 logo := factory.NewImage()
50 logo.SetHalign(gtk.AlignCenterValue)
51 logo.SetValign(gtk.AlignCenterValue)
52 logo.SetCanFocus(false)
53 logo.SetCanTarget(false)
54 logo.SetSizeRequest(loadingSkeletonLogoSize, loadingSkeletonLogoSize)
55 logo.SetPixelSize(loadingSkeletonLogoSize)
56 logo.AddCssClass("loading-skeleton-logo")
57
58 // Set logo texture if available
59 if logoTexture := GetLogoTexture(); logoTexture != nil {
60 logo.SetFromPaintable(logoTexture)
61 }
62
63 // Layout: logo, spinner (vertically centered)
64 content.Append(logo)
65 content.Append(spinner)
66 container.Append(content)
67
68 ls := &LoadingSkeleton{
69 container: container,
70 content: content,
71 spinner: spinner,
72 logo: logo,
73 }
74 ls.SetVisible(true)
75 return ls
76}
77
78func (ls *LoadingSkeleton) Widget() layout.Widget {
79 if ls == nil {
80 return nil
81 }
82 return ls.container
83}
84
85func (ls *LoadingSkeleton) SetVisible(visible bool) {
86 if ls == nil || ls.container == nil {
87 return
88 }
89 ls.container.SetVisible(visible)
90 if ls.spinner != nil {
91 if visible {
92 ls.spinner.Start()
93 } else {
94 ls.spinner.Stop()
95 }
96 }
97}