修改logo,修改配置页面的窗口
This commit is contained in:
@@ -35,8 +35,12 @@ app: build
|
|||||||
else echo " (no icon.icns found, skipping icon)"; fi
|
else echo " (no icon.icns found, skipping icon)"; fi
|
||||||
@echo "Built $(APP_BUNDLE)"
|
@echo "Built $(APP_BUNDLE)"
|
||||||
|
|
||||||
## icon: generate icon.icns from resources/icon.png
|
## icon: generate icon.icns from resources/icon.png (or resources/logo.svg)
|
||||||
icon:
|
icon:
|
||||||
|
@if [ -f resources/logo.svg ] && [ ! -f resources/icon.png -o resources/logo.svg -nt resources/icon.png ]; then \
|
||||||
|
echo "Converting resources/logo.svg -> resources/icon.png"; \
|
||||||
|
sips -z 1024 1024 -s format png resources/logo.svg --out resources/icon.png >/dev/null 2>&1; \
|
||||||
|
fi
|
||||||
@if [ ! -f resources/icon.png ]; then echo "resources/icon.png not found"; exit 1; fi
|
@if [ ! -f resources/icon.png ]; then echo "resources/icon.png not found"; exit 1; fi
|
||||||
mkdir -p resources/icon.iconset
|
mkdir -p resources/icon.iconset
|
||||||
@for size in 16 32 64 128 256 512 1024; do \
|
@for size in 16 32 64 128 256 512 1024; do \
|
||||||
|
|||||||
+6
-4
@@ -20,10 +20,11 @@ import (
|
|||||||
|
|
||||||
// App is the GUI application controller.
|
// App is the GUI application controller.
|
||||||
type App struct {
|
type App struct {
|
||||||
fyneApp fyne.App
|
fyneApp fyne.App
|
||||||
db *db.Store
|
db *db.Store
|
||||||
kc keychain.Store
|
kc keychain.Store
|
||||||
window fyne.Window
|
window fyne.Window
|
||||||
|
profileWindow fyne.Window
|
||||||
|
|
||||||
// UI widgets
|
// UI widgets
|
||||||
profileSelect *widget.Select
|
profileSelect *widget.Select
|
||||||
@@ -96,6 +97,7 @@ func Run() {
|
|||||||
|
|
||||||
a.window.SetCloseIntercept(func() {
|
a.window.SetCloseIntercept(func() {
|
||||||
if cfg.CloseToTray {
|
if cfg.CloseToTray {
|
||||||
|
hideDockIcon()
|
||||||
a.window.Hide()
|
a.window.Hide()
|
||||||
} else {
|
} else {
|
||||||
a.fyneApp.Quit()
|
a.fyneApp.Quit()
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
//go:build darwin
|
||||||
|
|
||||||
|
package ui
|
||||||
|
|
||||||
|
/*
|
||||||
|
#cgo LDFLAGS: -framework Cocoa
|
||||||
|
#include <objc/objc.h>
|
||||||
|
#include <objc/runtime.h>
|
||||||
|
#include <objc/message.h>
|
||||||
|
|
||||||
|
static void setDockIconVisible(int visible) {
|
||||||
|
Class cls = objc_getClass("NSApplication");
|
||||||
|
id app = ((id (*)(Class, SEL))objc_msgSend)(cls, sel_getUid("sharedApplication"));
|
||||||
|
((void (*)(id, SEL, long))objc_msgSend)(app, sel_getUid("setActivationPolicy:"), visible ? 0 : 1);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
func showDockIcon() { C.setDockIconVisible(1) }
|
||||||
|
func hideDockIcon() { C.setDockIconVisible(0) }
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
//go:build !darwin
|
||||||
|
|
||||||
|
package ui
|
||||||
|
|
||||||
|
func showDockIcon() {}
|
||||||
|
func hideDockIcon() {}
|
||||||
+27
-10
@@ -8,7 +8,6 @@ import (
|
|||||||
|
|
||||||
"fyne.io/fyne/v2"
|
"fyne.io/fyne/v2"
|
||||||
"fyne.io/fyne/v2/container"
|
"fyne.io/fyne/v2/container"
|
||||||
"fyne.io/fyne/v2/dialog"
|
|
||||||
"fyne.io/fyne/v2/widget"
|
"fyne.io/fyne/v2/widget"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -46,9 +45,15 @@ func selectedCode(codes []string, idx int) string {
|
|||||||
return codes[idx]
|
return codes[idx]
|
||||||
}
|
}
|
||||||
|
|
||||||
// showProfileDialog displays an add/edit dialog for a server profile.
|
// showProfileDialog opens a separate window for editing a server profile.
|
||||||
// If editing is nil, a new profile is created.
|
// If editing is nil, a new profile is created. If a profile window is
|
||||||
|
// already open, it is brought to the front instead of opening a second one.
|
||||||
func (a *App) showProfileDialog(editing *model.ServerProfile) {
|
func (a *App) showProfileDialog(editing *model.ServerProfile) {
|
||||||
|
if a.profileWindow != nil {
|
||||||
|
a.profileWindow.RequestFocus()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
isNew := editing == nil
|
isNew := editing == nil
|
||||||
|
|
||||||
nameEntry := widget.NewEntry()
|
nameEntry := widget.NewEntry()
|
||||||
@@ -88,18 +93,30 @@ func (a *App) showProfileDialog(editing *model.ServerProfile) {
|
|||||||
widget.NewLabel(i18n.T("FieldMTUOverride")), mtuEntry,
|
widget.NewLabel(i18n.T("FieldMTUOverride")), mtuEntry,
|
||||||
)
|
)
|
||||||
|
|
||||||
d := dialog.NewCustomConfirm(i18n.T("DlgProfileTitle"), i18n.T("BtnSave"), i18n.T("BtnCancel"), form, func(save bool) {
|
profileWin := a.fyneApp.NewWindow(i18n.T("DlgProfileTitle"))
|
||||||
if !save {
|
a.profileWindow = profileWin
|
||||||
return
|
|
||||||
}
|
profileWin.SetOnClosed(func() {
|
||||||
|
a.profileWindow = nil
|
||||||
|
})
|
||||||
|
|
||||||
|
saveBtn := widget.NewButton(i18n.T("BtnSave"), func() {
|
||||||
a.saveProfile(editing, nameEntry.Text, serverEntry.Text,
|
a.saveProfile(editing, nameEntry.Text, serverEntry.Text,
|
||||||
userEntry.Text, passEntry.Text,
|
userEntry.Text, passEntry.Text,
|
||||||
selectedCode(authCodes, authSelect.SelectedIndex()),
|
selectedCode(authCodes, authSelect.SelectedIndex()),
|
||||||
selectedCode(routeCodes, routeSelect.SelectedIndex()),
|
selectedCode(routeCodes, routeSelect.SelectedIndex()),
|
||||||
cidrEntry.Text, mtuEntry.Text, isNew)
|
cidrEntry.Text, mtuEntry.Text, isNew)
|
||||||
}, a.window)
|
profileWin.Close()
|
||||||
d.Resize(fyne.NewSize(400, 500))
|
})
|
||||||
d.Show()
|
saveBtn.Importance = widget.HighImportance
|
||||||
|
|
||||||
|
cancelBtn := widget.NewButton(i18n.T("BtnCancel"), func() {
|
||||||
|
profileWin.Close()
|
||||||
|
})
|
||||||
|
|
||||||
|
profileWin.SetContent(container.NewBorder(nil, container.NewHBox(saveBtn, cancelBtn), nil, nil, container.NewScroll(form)))
|
||||||
|
profileWin.Resize(fyne.NewSize(460, 560))
|
||||||
|
profileWin.Show()
|
||||||
}
|
}
|
||||||
|
|
||||||
// saveProfile creates or updates a profile and stores credentials.
|
// saveProfile creates or updates a profile and stores credentials.
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 1.5 KiB |
@@ -1,12 +1,16 @@
|
|||||||
package ui
|
package ui
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
_ "embed"
|
||||||
"lmvpn/internal/i18n"
|
"lmvpn/internal/i18n"
|
||||||
|
|
||||||
"fyne.io/fyne/v2"
|
"fyne.io/fyne/v2"
|
||||||
"fyne.io/fyne/v2/driver/desktop"
|
"fyne.io/fyne/v2/driver/desktop"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
//go:embed tray-icon.png
|
||||||
|
var trayIconBytes []byte
|
||||||
|
|
||||||
// setupTray configures the system tray menu (desktop only).
|
// setupTray configures the system tray menu (desktop only).
|
||||||
func (a *App) setupTray() {
|
func (a *App) setupTray() {
|
||||||
deskApp, ok := a.fyneApp.(desktop.App)
|
deskApp, ok := a.fyneApp.(desktop.App)
|
||||||
@@ -44,6 +48,7 @@ func (a *App) setupTray() {
|
|||||||
|
|
||||||
menu := fyne.NewMenu(i18n.T("WindowTitle"),
|
menu := fyne.NewMenu(i18n.T("WindowTitle"),
|
||||||
fyne.NewMenuItem(i18n.T("TrayShowWindow"), func() {
|
fyne.NewMenuItem(i18n.T("TrayShowWindow"), func() {
|
||||||
|
showDockIcon()
|
||||||
a.window.Show()
|
a.window.Show()
|
||||||
a.window.RequestFocus()
|
a.window.RequestFocus()
|
||||||
}),
|
}),
|
||||||
@@ -62,4 +67,6 @@ func (a *App) setupTray() {
|
|||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
deskApp.SetSystemTrayMenu(menu)
|
deskApp.SetSystemTrayMenu(menu)
|
||||||
|
trayIcon := fyne.NewStaticResource("tray-icon.png", trayIconBytes)
|
||||||
|
deskApp.SetSystemTrayIcon(trayIcon)
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 51 KiB |
@@ -0,0 +1,20 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200" viewBox="0 0 200 200">
|
||||||
|
<rect width="200" height="200" fill="#ffffff"/>
|
||||||
|
<g transform="translate(10, 2)">
|
||||||
|
<rect id="pot1" x="70" y="160" width="40" height="40" rx="20" ry="20" fill="#33BEFF"/>
|
||||||
|
<rect id="pot2" x="150" y="130" width="40" height="40" rx="20" ry="20" fill="#33BEFF"/>
|
||||||
|
<g id="shield">
|
||||||
|
<path d="M 72 50 L 108 50 L 108 74 Q 108 88 90 96 Q 72 88 72 74 Z" fill="#33BEFF"/>
|
||||||
|
<path d="M 86.5 66 A 3.5 3.5 0 1 1 93.5 66 L 91 80 L 89 80 Z" fill="#ffffff"/>
|
||||||
|
</g>
|
||||||
|
<rect id="line1" x="132" y="60" width="14" height="120" rx="7" ry="7" fill="#33BEFF" transform="rotate(-45 139 120)"/>
|
||||||
|
<rect id="line2" x="105" y="105" width="14" height="80" rx="7" ry="7" fill="#33BEFF" transform="rotate(30 112 145)"/>
|
||||||
|
<rect id="line3" x="45" y="80" width="14" height="50" rx="7" ry="7" fill="#B1B1B1" transform="rotate(45 52 105)"/>
|
||||||
|
<rect id="line4" x="30" y="45" width="14" height="50" rx="7" ry="7" fill="#B1B1B1" transform="rotate(90 37 70)"/>
|
||||||
|
<rect id="line5" x="43" y="8" width="14" height="50" rx="7" ry="7" fill="#B1B1B1" transform="rotate(135 50 33)"/>
|
||||||
|
<rect id="line6" x="81" y="-8" width="14" height="50" rx="7" ry="7" fill="#B1B1B1"/>
|
||||||
|
<rect id="line7" x="120" y="6" width="14" height="50" rx="7" ry="7" fill="#B1B1B1" transform="rotate(45 127 31)"/>
|
||||||
|
<rect id="line8" x="135" y="45" width="14" height="50" rx="7" ry="7" fill="#B1B1B1" transform="rotate(90 142 70)"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.5 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.5 KiB |
@@ -0,0 +1,19 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200" viewBox="0 0 200 200">
|
||||||
|
<g transform="translate(10, 2)">
|
||||||
|
<rect id="pot1" x="70" y="160" width="40" height="40" rx="20" ry="20" fill="#33BEFF"/>
|
||||||
|
<rect id="pot2" x="150" y="130" width="40" height="40" rx="20" ry="20" fill="#33BEFF"/>
|
||||||
|
<g id="shield">
|
||||||
|
<path d="M 72 50 L 108 50 L 108 74 Q 108 88 90 96 Q 72 88 72 74 Z" fill="#33BEFF"/>
|
||||||
|
<path d="M 86.5 66 A 3.5 3.5 0 1 1 93.5 66 L 91 80 L 89 80 Z" fill="#ffffff"/>
|
||||||
|
</g>
|
||||||
|
<rect id="line1" x="132" y="60" width="14" height="120" rx="7" ry="7" fill="#33BEFF" transform="rotate(-45 139 120)"/>
|
||||||
|
<rect id="line2" x="105" y="105" width="14" height="80" rx="7" ry="7" fill="#33BEFF" transform="rotate(30 112 145)"/>
|
||||||
|
<rect id="line3" x="45" y="80" width="14" height="50" rx="7" ry="7" fill="#B1B1B1" transform="rotate(45 52 105)"/>
|
||||||
|
<rect id="line4" x="30" y="45" width="14" height="50" rx="7" ry="7" fill="#B1B1B1" transform="rotate(90 37 70)"/>
|
||||||
|
<rect id="line5" x="43" y="8" width="14" height="50" rx="7" ry="7" fill="#B1B1B1" transform="rotate(135 50 33)"/>
|
||||||
|
<rect id="line6" x="81" y="-8" width="14" height="50" rx="7" ry="7" fill="#B1B1B1"/>
|
||||||
|
<rect id="line7" x="120" y="6" width="14" height="50" rx="7" ry="7" fill="#B1B1B1" transform="rotate(45 127 31)"/>
|
||||||
|
<rect id="line8" x="135" y="45" width="14" height="50" rx="7" ry="7" fill="#B1B1B1" transform="rotate(90 142 70)"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.5 KiB |
Reference in New Issue
Block a user