LazyRun v1.0.0: shortcut maker untuk executable dan PWA
- Fungsi A: shortcut dari file executable (ELF/AppImage/script) - Fungsi B: shortcut PWA/URL dengan deteksi browser (native, /opt, Flatpak) - Checkbox Menu Aplikasi / Desktop, desktop-only pakai NoDisplay=true - List + uninstall + deteksi shortcut yang file .desktop-nya hilang - Metadata ~/.config/lazyrun/shortcuts.json, refresh cache XDG/KDE - AppImage + zsync update info via build.sh
This commit is contained in:
1 parent
9cd5a1f82d
commit
da31f7d7d7
31 files changed
+2916
No files matched your search
@@ -0,0 +1,141 @@
|
||||
package ui
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/container"
|
||||
"fyne.io/fyne/v2/dialog"
|
||||
"fyne.io/fyne/v2/widget"
|
||||
|
||||
"lazyrun/internal/browser"
|
||||
"lazyrun/internal/shortcut"
|
||||
"lazyrun/internal/store"
|
||||
)
|
||||
|
||||
func (ui *app) showWebAppDialog() {
|
||||
if len(ui.browsers) == 0 {
|
||||
dialog.ShowInformation(T("err_title"), T("no_browser"), ui.win)
|
||||
return
|
||||
}
|
||||
|
||||
var iconPath string
|
||||
var nameTouched, filling bool
|
||||
|
||||
urlEntry := widget.NewEntry()
|
||||
urlEntry.SetPlaceHolder("https://web.whatsapp.com")
|
||||
nameEntry := widget.NewEntry()
|
||||
iconLabel := widget.NewLabel(T("icon_auto"))
|
||||
picker := widget.NewSelect(browserNames(ui.browsers), nil)
|
||||
picker.SetSelected(ui.browsers[0].Name)
|
||||
menu := widget.NewCheck(T("check_menu"), nil)
|
||||
menu.SetChecked(true)
|
||||
desktop := widget.NewCheck(T("check_desktop"), nil)
|
||||
desktop.SetChecked(true)
|
||||
|
||||
nameEntry.OnChanged = func(string) {
|
||||
if !filling {
|
||||
nameTouched = true
|
||||
}
|
||||
}
|
||||
urlEntry.OnChanged = func(value string) {
|
||||
if nameTouched {
|
||||
return
|
||||
}
|
||||
if host := hostOf(value); host != "" {
|
||||
filling = true
|
||||
nameEntry.SetText(host)
|
||||
filling = false
|
||||
}
|
||||
}
|
||||
|
||||
browseIcon := widget.NewButton(T("browse"), func() {
|
||||
pickFile(ui.win, imageFilter, func(path string) {
|
||||
iconPath = path
|
||||
iconLabel.SetText(filepath.Base(path))
|
||||
})
|
||||
})
|
||||
|
||||
var d *dialog.CustomDialog
|
||||
install := widget.NewButton(T("install"), func() {
|
||||
switch {
|
||||
case strings.TrimSpace(urlEntry.Text) == "":
|
||||
dialog.ShowInformation(T("err_title"), T("need_url"), ui.win)
|
||||
return
|
||||
case strings.TrimSpace(nameEntry.Text) == "":
|
||||
dialog.ShowInformation(T("err_title"), T("need_name"), ui.win)
|
||||
return
|
||||
case !menu.Checked && !desktop.Checked:
|
||||
dialog.ShowInformation(T("err_title"), T("need_target"), ui.win)
|
||||
return
|
||||
}
|
||||
b := ui.browsers[indexOf(ui.browsers, picker.Selected)]
|
||||
opts := shortcut.WebOptions{
|
||||
URL: urlEntry.Text,
|
||||
Name: nameEntry.Text,
|
||||
Browser: shortcut.BrowserArg{Name: b.Name, Exec: b.Exec, Firefox: b.Kind == browser.Firefox},
|
||||
IconPath: iconPath,
|
||||
Menu: menu.Checked,
|
||||
Desktop: desktop.Checked,
|
||||
}
|
||||
ui.install(
|
||||
func() (store.Shortcut, error) { return shortcut.InstallWebApp(opts) },
|
||||
func(sc store.Shortcut, err error) { ui.added(sc, err, d.Hide) },
|
||||
)
|
||||
})
|
||||
install.Importance = widget.HighImportance
|
||||
|
||||
form := widget.NewForm(
|
||||
widget.NewFormItem(T("field_url"), urlEntry),
|
||||
widget.NewFormItem(T("field_name"), nameEntry),
|
||||
widget.NewFormItem(T("field_browser"), picker),
|
||||
widget.NewFormItem(T("field_icon"), container.NewBorder(nil, nil, nil, browseIcon, iconLabel)),
|
||||
)
|
||||
content := container.NewVBox(
|
||||
form,
|
||||
widget.NewSeparator(),
|
||||
heading(T("section_location")),
|
||||
menu,
|
||||
desktop,
|
||||
container.NewHBox(spacer(), widget.NewButton(T("cancel"), func() { d.Hide() }), install),
|
||||
)
|
||||
|
||||
d = dialog.NewCustom(T("new_web_title"), "", content, ui.win)
|
||||
d.Resize(fyne.NewSize(520, 440))
|
||||
d.Show()
|
||||
}
|
||||
|
||||
func browserNames(list []browser.Browser) []string {
|
||||
names := make([]string, len(list))
|
||||
for i, b := range list {
|
||||
names[i] = b.Name
|
||||
}
|
||||
return names
|
||||
}
|
||||
|
||||
func indexOf(list []browser.Browser, name string) int {
|
||||
for i, b := range list {
|
||||
if b.Name == name {
|
||||
return i
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// hostOf mengambil hostname dari URL yang mungkin ditulis tanpa skema.
|
||||
func hostOf(raw string) string {
|
||||
raw = strings.TrimSpace(raw)
|
||||
if raw == "" {
|
||||
return ""
|
||||
}
|
||||
if !strings.Contains(raw, "://") {
|
||||
raw = "https://" + raw
|
||||
}
|
||||
u, err := url.Parse(raw)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return u.Hostname()
|
||||
}
|
||||
Reference in new issue
Block a user