969600b6ee
- assets/icons/ 共 80+ 张真实品牌图标嵌入 UI 包 - entry 新增 IconKey 字段,持久化到 config.Entry.IconName - iconPickerDialog 网格布局图标选择器 - Add 完成后自动弹出图标选择器,Skip 则用 vendor 占位图 - ⋯ 菜单新增 "Change icon..." 项 - vendorIconFor 解析顺序:catalog → vendor 占位 → qr 兜底
123 lines
3.8 KiB
Go
123 lines
3.8 KiB
Go
package ui
|
|
|
|
import (
|
|
"gioui.org/layout"
|
|
"gioui.org/unit"
|
|
"gioui.org/widget"
|
|
"gioui.org/widget/material"
|
|
|
|
"git.wxccs.org/iceking2nd/winauth-go/internal/i18n"
|
|
)
|
|
|
|
// rowAction is what the per-row ⋯ popup returns to the caller.
|
|
type rowAction int
|
|
|
|
const (
|
|
rowActionNone rowAction = iota
|
|
rowActionRename
|
|
rowActionDelete
|
|
rowActionMoveUp
|
|
rowActionMoveDown
|
|
rowActionChangeIcon
|
|
)
|
|
|
|
// rowActionMenu is the small popup opened by the ⋯ button on each entry
|
|
// row. It carries the target entry index so the caller knows which row
|
|
// the chosen action applies to. moveUp/moveDown are disabled (rendered
|
|
// but inert) when the index is at a boundary.
|
|
type rowActionMenu struct {
|
|
idx int
|
|
canMoveUp bool
|
|
canMoveDown bool
|
|
|
|
renameBtn widget.Clickable
|
|
deleteBtn widget.Clickable
|
|
moveUpBtn widget.Clickable
|
|
moveDownBtn widget.Clickable
|
|
changeIconBtn widget.Clickable
|
|
cancelBtn widget.Clickable
|
|
}
|
|
|
|
func newRowActionMenu(idx, total int) *rowActionMenu {
|
|
return &rowActionMenu{
|
|
idx: idx,
|
|
canMoveUp: idx > 0,
|
|
canMoveDown: idx < total-1,
|
|
}
|
|
}
|
|
|
|
// Pick reports the user's choice and whether the menu should close.
|
|
func (m *rowActionMenu) Pick(gtx layout.Context) (rowAction, bool) {
|
|
switch {
|
|
case m.renameBtn.Clicked(gtx):
|
|
return rowActionRename, true
|
|
case m.deleteBtn.Clicked(gtx):
|
|
return rowActionDelete, true
|
|
case m.moveUpBtn.Clicked(gtx):
|
|
if !m.canMoveUp {
|
|
return rowActionNone, false
|
|
}
|
|
return rowActionMoveUp, true
|
|
case m.moveDownBtn.Clicked(gtx):
|
|
if !m.canMoveDown {
|
|
return rowActionNone, false
|
|
}
|
|
return rowActionMoveDown, true
|
|
case m.changeIconBtn.Clicked(gtx):
|
|
return rowActionChangeIcon, true
|
|
case m.cancelBtn.Clicked(gtx):
|
|
return rowActionNone, true
|
|
}
|
|
return rowActionNone, false
|
|
}
|
|
|
|
func (m *rowActionMenu) Layout(gtx layout.Context, th *material.Theme) layout.Dimensions {
|
|
fillBackground(gtx, activePalette.ScrimBg)
|
|
|
|
row := func(btn *widget.Clickable, label string, enabled bool) layout.FlexChild {
|
|
return layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
|
return layout.Inset{Top: unit.Dp(4), Bottom: unit.Dp(4)}.Layout(gtx,
|
|
func(gtx layout.Context) layout.Dimensions {
|
|
gtx.Constraints.Min.X = gtx.Constraints.Max.X
|
|
b := material.Button(th, btn, label)
|
|
if !enabled {
|
|
// Visually dim the disabled state; Pick also
|
|
// refuses to dispatch the action so clicks
|
|
// are inert beyond the colour change.
|
|
b.Background = activePalette.RingBg
|
|
b.Color = activePalette.MutedFg
|
|
}
|
|
return b.Layout(gtx)
|
|
})
|
|
})
|
|
}
|
|
|
|
return layout.Center.Layout(gtx, func(gtx layout.Context) layout.Dimensions {
|
|
gtx.Constraints.Max.X = gtx.Dp(260)
|
|
return widget.Border{
|
|
Color: activePalette.DialogBorder,
|
|
CornerRadius: unit.Dp(4),
|
|
Width: unit.Dp(1),
|
|
}.Layout(gtx, func(gtx layout.Context) layout.Dimensions {
|
|
fillBackground(gtx, activePalette.DialogBg)
|
|
return layout.UniformInset(unit.Dp(16)).Layout(gtx, func(gtx layout.Context) layout.Dimensions {
|
|
return layout.Flex{Axis: layout.Vertical}.Layout(gtx,
|
|
layout.Rigid(material.H6(th, i18n.T("dialog_row_actions_title")).Layout),
|
|
layout.Rigid(layout.Spacer{Height: unit.Dp(12)}.Layout),
|
|
row(&m.renameBtn, i18n.T("action_rename"), true),
|
|
row(&m.deleteBtn, i18n.T("action_delete"), true),
|
|
row(&m.changeIconBtn, i18n.T("action_change_icon"), true),
|
|
row(&m.moveUpBtn, i18n.T("action_move_up"), m.canMoveUp),
|
|
row(&m.moveDownBtn, i18n.T("action_move_down"), m.canMoveDown),
|
|
layout.Rigid(layout.Spacer{Height: unit.Dp(8)}.Layout),
|
|
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
|
return layout.Flex{Axis: layout.Horizontal, Spacing: layout.SpaceStart}.Layout(gtx,
|
|
layout.Rigid(material.Button(th, &m.cancelBtn, i18n.T("btn_cancel")).Layout),
|
|
)
|
|
}),
|
|
)
|
|
})
|
|
})
|
|
})
|
|
}
|