package main import ( "errors" encrypt "fckeuspy-go/lib" "os" "path/filepath" "strings" "fyne.io/fyne/v2" "fyne.io/fyne/v2/app" "fyne.io/fyne/v2/container" "fyne.io/fyne/v2/dialog" "fyne.io/fyne/v2/widget" ) func NewUI() (stprageDir string, window fyne.Window) { // App + storage dir a := app.NewWithID("fckeuspy") w := a.NewWindow("Encryptor (Fyne)") prefs := a.Preferences() width := prefs.IntWithFallback("winW", 1100) height := prefs.IntWithFallback("winH", 720) w.Resize(fyne.NewSize(float32(width), float32(height))) w.SetOnClosed(func() { sz := w.Canvas().Size() prefs.SetInt("winW", int(sz.Width)) prefs.SetInt("winH", int(sz.Height)) }) // docasny bypass /* base, err := os.UserConfigDir() if err != nil { base, _ = os.UserHomeDir() } */ base := "./" //return filepath.Join(base, "fckeuspy-go"), w return filepath.Join(base, ""), w } // ShowPasswordVaultDialog zobrazí dialog pro vytvoření nebo otevření trezoru. // Zatím pouze skeleton: vrací heslo přes callback, reálné volání CreateEncryptedStore/OpenEncryptedStore mimo. func ShowPasswordVaultDialog(w fyne.Window, vaultPath string, onResult func(create bool, password string)) { // Unlock tab unlockPw := widget.NewPasswordEntry() unlockPw.SetPlaceHolder("Heslo…") unlockForm := widget.NewForm( widget.NewFormItem("Heslo", unlockPw), ) unlockContent := container.NewVBox(unlockForm) // Create tab createPw1 := widget.NewPasswordEntry() createPw1.SetPlaceHolder("Heslo…") createPw2 := widget.NewPasswordEntry() createPw2.SetPlaceHolder("Znovu heslo…") strengthBar := widget.NewProgressBar() strengthBar.Min = 0 strengthBar.Max = 100 strengthLabel := widget.NewLabel("") updateStrength := func(pw string) { score, desc := simpleScore(pw) strengthBar.SetValue(float64(score)) strengthLabel.SetText(desc) } createPw1.OnChanged = updateStrength genBtn := widget.NewButton("Generovat", func() { if v, err := encrypt.GenerateRandomPassword(20); err == nil { createPw1.SetText(v) createPw2.SetText(v) updateStrength(v) } }) meter := container.NewVBox(strengthBar, strengthLabel) topCreate := container.NewBorder(nil, nil, nil, genBtn, meter) createForm := widget.NewForm( widget.NewFormItem("Heslo", createPw1), widget.NewFormItem("Potvrzení", createPw2), ) createContent := container.NewVBox(topCreate, createForm) tabs := container.NewAppTabs( container.NewTabItem("Odemknout", unlockContent), container.NewTabItem("Vytvořit", createContent), ) tabs.SetTabLocation(container.TabLocationTop) // Výběr aktivní záložky dle existence souboru if _, err := os.Stat(vaultPath); err != nil { // neexistuje => vytvořit tabs.SelectIndex(1) } else { tabs.SelectIndex(0) } d := dialog.NewCustomConfirm("Trezor", "OK", "Zrušit", tabs, func(ok bool) { if !ok { onResult(false, "") return } sel := tabs.Selected() if sel != nil && sel.Text == "Vytvořit" { pw := createPw1.Text if pw != createPw2.Text { dialog.NewError(errors.New("Hesla se neshodují"), w).Show() return } if err := encrypt.ValidatePasswordForUI(pw); err != nil { dialog.NewError(err, w).Show() return } onResult(true, pw) return } // Unlock onResult(false, unlockPw.Text) }, w) // Větší rozměr pro lepší přehlednost d.Resize(fyne.NewSize(620, 440)) d.Show() } // simpleScore: hrubá heuristika (0-100) func simpleScore(pw string) (int, string) { l := len(pw) var u, lw, dg, sp int specials := "!@#-_+=" for _, r := range pw { switch { case r >= 'A' && r <= 'Z': u++ case r >= 'a' && r <= 'z': lw++ case r >= '0' && r <= '9': dg++ default: if strings.ContainsRune(specials, r) { sp++ } } } cats := 0 if u > 0 { cats++ } if lw > 0 { cats++ } if dg > 0 { cats++ } if sp > 0 { cats++ } score := l*4 + cats*10 if score > 100 { score = 100 } desc := "Slabé" switch { case score >= 85: desc = "Silné" case score >= 60: desc = "Dobré" case score >= 30: desc = "Střední" } return score, desc }