Files
iceking2nd 969600b6ee feat(ui): 接入 vendor 真实图标库 + 图标选择器
- assets/icons/ 共 80+ 张真实品牌图标嵌入 UI 包
- entry 新增 IconKey 字段,持久化到 config.Entry.IconName
- iconPickerDialog 网格布局图标选择器
- Add 完成后自动弹出图标选择器,Skip 则用 vendor 占位图
- ⋯ 菜单新增 "Change icon..." 项
- vendorIconFor 解析顺序:catalog → vendor 占位 → qr 兜底
2026-06-12 09:41:30 +08:00

51 lines
1.6 KiB
Go

package ui
import (
"fmt"
"git.wxccs.org/iceking2nd/winauth-go/internal/authenticator"
"git.wxccs.org/iceking2nd/winauth-go/internal/config"
)
// entryFromAuthenticator builds a serializable config.Entry from an
// in-memory authenticator plus its display name. The vendor string is
// derived from the authenticator's Name() (which already returns
// "google" / "microsoft" / "okta" / "hotp" / "battlenet" / "steam").
func entryFromAuthenticator(name string, a authenticator.Authenticator, hotkey, iconKey string) config.Entry {
return config.Entry{
Name: name,
Vendor: a.Name(),
IconName: iconKey,
SecretRaw: a.SecretData(),
Hotkey: hotkey,
}
}
// buildAuthenticator is the reverse of entryFromAuthenticator: it picks
// the right concrete type based on vendor, then asks it to parse the
// stored secret blob.
func buildAuthenticator(e config.Entry) (authenticator.Authenticator, error) {
const fn = "internal.ui.buildAuthenticator"
var a authenticator.Authenticator
switch e.Vendor {
case "google", "":
a = authenticator.NewGoogleAuthenticator()
case "microsoft":
a = authenticator.NewMicrosoftAuthenticator()
case "okta":
a = authenticator.NewOktaVerifyAuthenticator()
case "hotp":
a = authenticator.NewHOTPAuthenticator()
case "battlenet":
a = authenticator.NewBattleNetAuthenticator()
case "steam":
a = authenticator.NewSteamAuthenticator()
default:
return nil, fmt.Errorf("%s: unknown vendor %q", fn, e.Vendor)
}
if err := a.SetSecretData(e.SecretRaw); err != nil {
return nil, fmt.Errorf("%s: decode entry %q: %w", fn, e.Name, err)
}
return a, nil
}