Skip to content

Commit caab380

Browse files
authored
feat(launcher): show welcome page (#6234)
feat(launcher): add welcome window Signed-off-by: Ettore Di Giacinto <[email protected]>
1 parent 8a3a362 commit caab380

File tree

5 files changed

+150
-0
lines changed

5 files changed

+150
-0
lines changed

cmd/launcher/internal/launcher.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ type Config struct {
3131
StartOnBoot bool `json:"start_on_boot"`
3232
LogLevel string `json:"log_level"`
3333
EnvironmentVars map[string]string `json:"environment_vars"`
34+
ShowWelcome *bool `json:"show_welcome"`
3435
}
3536

3637
// Launcher represents the main launcher application
@@ -148,6 +149,13 @@ func (l *Launcher) Initialize() error {
148149
log.Printf("Initializing empty EnvironmentVars map")
149150
}
150151

152+
// Set default welcome window preference
153+
if l.config.ShowWelcome == nil {
154+
true := true
155+
l.config.ShowWelcome = &true
156+
log.Printf("Setting default ShowWelcome: true")
157+
}
158+
151159
// Create directories
152160
os.MkdirAll(l.config.ModelsPath, 0755)
153161
os.MkdirAll(l.config.BackendsPath, 0755)

cmd/launcher/internal/launcher_test.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,14 @@ var _ = Describe("Launcher", func() {
4848
config := launcherInstance.GetConfig()
4949
Expect(config.ModelsPath).ToNot(BeEmpty())
5050
Expect(config.BackendsPath).ToNot(BeEmpty())
51+
})
52+
53+
It("should set default ShowWelcome to true", func() {
54+
err := launcherInstance.Initialize()
55+
Expect(err).ToNot(HaveOccurred())
56+
57+
config := launcherInstance.GetConfig()
58+
Expect(config.ShowWelcome).To(BeTrue())
5159
Expect(config.Address).To(Equal("127.0.0.1:8080"))
5260
Expect(config.LogLevel).To(Equal("info"))
5361
})

cmd/launcher/internal/systray_manager.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,9 @@ func (sm *SystrayManager) recreateMenu() {
177177
fyne.NewMenuItem("Settings", func() {
178178
sm.showSettings()
179179
}),
180+
fyne.NewMenuItem("Show Welcome Window", func() {
181+
sm.showWelcomeWindow()
182+
}),
180183
fyne.NewMenuItem("Open Data Folder", func() {
181184
sm.openDataFolder()
182185
}),
@@ -243,6 +246,13 @@ func (sm *SystrayManager) showSettings() {
243246
sm.window.RequestFocus()
244247
}
245248

249+
// showWelcomeWindow shows the welcome window
250+
func (sm *SystrayManager) showWelcomeWindow() {
251+
if sm.launcher.GetUI() != nil {
252+
sm.launcher.GetUI().ShowWelcomeWindow()
253+
}
254+
}
255+
246256
// openDataFolder opens the data folder in file manager
247257
func (sm *SystrayManager) openDataFolder() {
248258
dataPath := sm.launcher.GetDataPath()

cmd/launcher/internal/ui.go

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -675,3 +675,121 @@ func (ui *LauncherUI) UpdateRunningState(isRunning bool) {
675675
}
676676
})
677677
}
678+
679+
// ShowWelcomeWindow displays the welcome window with helpful information
680+
func (ui *LauncherUI) ShowWelcomeWindow() {
681+
if ui.launcher == nil || ui.launcher.window == nil {
682+
log.Printf("Cannot show welcome window: launcher or window is nil")
683+
return
684+
}
685+
686+
fyne.DoAndWait(func() {
687+
// Create welcome window
688+
welcomeWindow := ui.launcher.app.NewWindow("Welcome to LocalAI Launcher")
689+
welcomeWindow.Resize(fyne.NewSize(600, 500))
690+
welcomeWindow.CenterOnScreen()
691+
welcomeWindow.SetCloseIntercept(func() {
692+
welcomeWindow.Close()
693+
})
694+
695+
// Title
696+
titleLabel := widget.NewLabel("Welcome to LocalAI Launcher!")
697+
titleLabel.TextStyle = fyne.TextStyle{Bold: true}
698+
titleLabel.Alignment = fyne.TextAlignCenter
699+
700+
// Welcome message
701+
welcomeText := `LocalAI Launcher makes it easy to run LocalAI on your system.
702+
703+
What you can do:
704+
• Start and stop LocalAI server
705+
• Configure models and backends paths
706+
• Set environment variables
707+
• Check for updates automatically
708+
• Access LocalAI WebUI when running
709+
710+
Getting Started:
711+
1. Configure your models and backends paths
712+
2. Click "Start LocalAI" to begin
713+
3. Use "Open WebUI" to access the interface
714+
4. Check the system tray for quick access`
715+
716+
welcomeLabel := widget.NewLabel(welcomeText)
717+
welcomeLabel.Wrapping = fyne.TextWrapWord
718+
719+
// Useful links section
720+
linksTitle := widget.NewLabel("Useful Links:")
721+
linksTitle.TextStyle = fyne.TextStyle{Bold: true}
722+
723+
// Create link buttons
724+
docsButton := widget.NewButton("📚 Documentation", func() {
725+
ui.openURL("https://localai.io/docs/")
726+
})
727+
728+
githubButton := widget.NewButton("🐙 GitHub Repository", func() {
729+
ui.openURL("https://github.com/mudler/LocalAI")
730+
})
731+
732+
modelsButton := widget.NewButton("🤖 Model Gallery", func() {
733+
ui.openURL("https://localai.io/models/")
734+
})
735+
736+
communityButton := widget.NewButton("💬 Community", func() {
737+
ui.openURL("https://discord.gg/XgwjKptP7Z")
738+
})
739+
740+
// Checkbox to disable welcome window
741+
dontShowAgainCheck := widget.NewCheck("Don't show this welcome window again", func(checked bool) {
742+
if ui.launcher != nil {
743+
config := ui.launcher.GetConfig()
744+
v := !checked
745+
config.ShowWelcome = &v
746+
ui.launcher.SetConfig(config)
747+
}
748+
})
749+
750+
config := ui.launcher.GetConfig()
751+
if config.ShowWelcome != nil {
752+
dontShowAgainCheck.SetChecked(*config.ShowWelcome)
753+
}
754+
755+
// Close button
756+
closeButton := widget.NewButton("Get Started", func() {
757+
welcomeWindow.Close()
758+
})
759+
closeButton.Importance = widget.HighImportance
760+
761+
// Layout
762+
linksContainer := container.NewVBox(
763+
linksTitle,
764+
docsButton,
765+
githubButton,
766+
modelsButton,
767+
communityButton,
768+
)
769+
770+
content := container.NewVBox(
771+
titleLabel,
772+
widget.NewSeparator(),
773+
welcomeLabel,
774+
widget.NewSeparator(),
775+
linksContainer,
776+
widget.NewSeparator(),
777+
dontShowAgainCheck,
778+
widget.NewSeparator(),
779+
closeButton,
780+
)
781+
782+
welcomeWindow.SetContent(content)
783+
welcomeWindow.Show()
784+
})
785+
}
786+
787+
// openURL opens a URL in the default browser
788+
func (ui *LauncherUI) openURL(urlString string) {
789+
parsedURL, err := url.Parse(urlString)
790+
if err != nil {
791+
log.Printf("Failed to parse URL %s: %v", urlString, err)
792+
return
793+
}
794+
fyne.CurrentApp().OpenURL(parsedURL)
795+
}

cmd/launcher/main.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,12 @@ func main() {
5555
// Load configuration into UI
5656
launcher.GetUI().LoadConfiguration()
5757
launcher.GetUI().UpdateStatus("Ready")
58+
59+
// Show welcome window if configured to do so
60+
config := launcher.GetConfig()
61+
if *config.ShowWelcome {
62+
launcher.GetUI().ShowWelcomeWindow()
63+
}
5864
}
5965
}()
6066

0 commit comments

Comments
 (0)