624 lines
20 KiB
Go
624 lines
20 KiB
Go
package gui
|
|
|
|
// startupGui.go implements the app startup pages
|
|
|
|
import "fyne.io/fyne/v2"
|
|
import "fyne.io/fyne/v2/app"
|
|
import "fyne.io/fyne/v2/widget"
|
|
import "fyne.io/fyne/v2/container"
|
|
import "fyne.io/fyne/v2/canvas"
|
|
import "fyne.io/fyne/v2/layout"
|
|
import "fyne.io/fyne/v2/dialog"
|
|
import "fyne.io/fyne/v2/theme"
|
|
|
|
import "seekia/resources/imageFiles"
|
|
|
|
import "seekia/internal/appMemory"
|
|
import "seekia/internal/badgerDatabase"
|
|
import "seekia/internal/localFilesystem"
|
|
import "seekia/internal/helpers"
|
|
import "seekia/internal/appUsers"
|
|
import "seekia/internal/mySeedPhrases"
|
|
import "seekia/internal/globalSettings"
|
|
import "seekia/internal/translation"
|
|
import "seekia/internal/imagery"
|
|
import "seekia/internal/backgroundJobs"
|
|
|
|
import "time"
|
|
import "errors"
|
|
import "slices"
|
|
|
|
func StartGui(){
|
|
|
|
app := app.New()
|
|
|
|
window := app.NewWindow("Seekia")
|
|
|
|
windowSize := fyne.NewSize(600, 600)
|
|
window.Resize(windowSize)
|
|
|
|
window.CenterOnScreen()
|
|
|
|
err := localFilesystem.InitializeAppDatastores()
|
|
if (err != nil){
|
|
|
|
getThemeObject := func()fyne.Theme{
|
|
|
|
themeObject, err := getCustomFyneTheme("Light")
|
|
if (err != nil){
|
|
return theme.LightTheme()
|
|
}
|
|
|
|
return themeObject
|
|
}
|
|
|
|
themeObject := getThemeObject()
|
|
|
|
app.Settings().SetTheme(themeObject)
|
|
|
|
errorToShow := errors.New("Seekia cannot access the filesystem: " + err.Error())
|
|
|
|
setErrorEncounteredPage_NoNavBar(window, errorToShow, false, nil)
|
|
|
|
window.ShowAndRun()
|
|
return
|
|
}
|
|
|
|
getAppTheme := func()(fyne.Theme, error){
|
|
|
|
getAppThemeName := func()(string, error){
|
|
|
|
exists, currentAppTheme, err := globalSettings.GetSetting("AppTheme")
|
|
if (err != nil){
|
|
return "", errors.New("Seekia cannot access the filesystem: " + err.Error())
|
|
}
|
|
if (exists == false){
|
|
return "Light", nil
|
|
}
|
|
return currentAppTheme, nil
|
|
}
|
|
|
|
appThemeName, err := getAppThemeName()
|
|
if (err != nil) { return nil, err }
|
|
|
|
themeObject, err := getCustomFyneTheme(appThemeName)
|
|
if (err != nil){ return nil, err }
|
|
|
|
return themeObject, nil
|
|
}
|
|
|
|
appTheme, err := getAppTheme()
|
|
if (err != nil){
|
|
|
|
getThemeObject := func()fyne.Theme{
|
|
|
|
themeObject, err := getCustomFyneTheme("Light")
|
|
if (err != nil){
|
|
return theme.LightTheme()
|
|
}
|
|
|
|
return themeObject
|
|
}
|
|
|
|
themeObject := getThemeObject()
|
|
|
|
app.Settings().SetTheme(themeObject)
|
|
|
|
setErrorEncounteredPage_NoNavBar(window, err, false, nil)
|
|
|
|
window.ShowAndRun()
|
|
return
|
|
}
|
|
|
|
app.Settings().SetTheme(appTheme)
|
|
|
|
window.SetCloseIntercept(func(){
|
|
|
|
appMemory.SetMemoryEntry("CurrentViewedPage", "Shutdown")
|
|
|
|
description1 := getBoldLabelCentered("Shutting Down...")
|
|
|
|
progressBar := getWidgetCentered(widget.NewProgressBarInfinite())
|
|
|
|
description2 := getItalicLabelCentered("Seekia is shutting down background tasks.")
|
|
|
|
emptyLabel := widget.NewLabel("")
|
|
|
|
forceCloseButton := getWidgetCentered(widget.NewButtonWithIcon("Force Close", theme.CancelIcon(), func(){
|
|
window.Close()
|
|
}))
|
|
|
|
//TODO: Show the number of background tasks we are waiting to stop, along with their names
|
|
|
|
page := container.NewVBox(layout.NewSpacer(), description1, progressBar, description2, emptyLabel, forceCloseButton, layout.NewSpacer())
|
|
|
|
stopJobsAndCloseWindowFunction := func(){
|
|
|
|
//TODO: Remove this time.Sleep once we actually have background tasks to close
|
|
time.Sleep(time.Second)
|
|
|
|
backgroundJobs.StopBackgroundJobs()
|
|
|
|
badgerDatabase.StopDatabase()
|
|
|
|
//TODO: Add peer node, peer server, manual broadcasts, manual downloads
|
|
// We should also use goroutines to start the stop function for all background tasks
|
|
// This way they can all gracefully shutdown simultaneously while we wait for them to stop
|
|
|
|
window.Close()
|
|
}
|
|
|
|
window.SetContent(page)
|
|
|
|
go stopJobsAndCloseWindowFunction()
|
|
})
|
|
|
|
//TODO: On first startup, first show Choose Language page.
|
|
// Then show page describing legal risks of Seekia, including information about countries where Tor is illegal.
|
|
// It should not be a generic warning that users will not read.
|
|
// Users should actually stop if Seekia use is illegal and puts them at risk of prosecution.
|
|
|
|
setChooseAppUserPage(window)
|
|
|
|
window.ShowAndRun()
|
|
}
|
|
|
|
|
|
func setChooseAppUserPage(window fyne.Window){
|
|
|
|
currentPage := func(){setChooseAppUserPage(window)}
|
|
|
|
logoFileBytes := imageFiles.PNG_SeekiaLogo
|
|
logoGoImage, err := imagery.ConvertPNGImageFileBytesToGolangImage(logoFileBytes)
|
|
if (err != nil){
|
|
setErrorEncounteredPage_NoNavBar(window, err, true, currentPage)
|
|
return
|
|
}
|
|
|
|
seekiaLogo := canvas.NewImageFromImage(logoGoImage)
|
|
seekiaLogo.FillMode = canvas.ImageFillContain
|
|
logoSize := getCustomFyneSize(30)
|
|
seekiaLogo.SetMinSize(logoSize)
|
|
|
|
seekiaDescriptionLabel := getItalicLabelCentered("Be genetics aware.")
|
|
|
|
selectLanguageTitle := getBoldLabel("Language:")
|
|
|
|
currentLanguage := translation.GetMyLanguage()
|
|
selectLanguageButton := getWidgetCentered(widget.NewButton(currentLanguage, func(){
|
|
|
|
setSelectLanguagePage(window, false, currentPage)
|
|
}))
|
|
|
|
selectLanguageRow := container.NewHBox(layout.NewSpacer(), selectLanguageTitle, selectLanguageButton, layout.NewSpacer())
|
|
|
|
spacerA := widget.NewLabel("")
|
|
spacerB := widget.NewLabel("")
|
|
|
|
page := container.NewVBox(spacerA, spacerB, seekiaLogo, seekiaDescriptionLabel, widget.NewSeparator(), selectLanguageRow, widget.NewSeparator())
|
|
|
|
allUsersList, err := appUsers.GetAppUsersList()
|
|
if (err != nil){
|
|
setErrorEncounteredPage_NoNavBar(window, err, true, currentPage)
|
|
return
|
|
}
|
|
|
|
if (len(allUsersList) != 0){
|
|
|
|
selectUserLabel := getBoldLabelCentered("Select User:")
|
|
page.Add(selectUserLabel)
|
|
|
|
userButtonsGrid := container.NewGridWithColumns(1)
|
|
|
|
for _, userName := range allUsersList{
|
|
|
|
selectUserButton := widget.NewButtonWithIcon(userName, theme.AccountIcon(), func(){
|
|
|
|
setLoadingScreen(window, translate("Starting Up"), translate("Loading..."))
|
|
|
|
err := appUsers.SignInToAppUser(userName, true)
|
|
if (err != nil){
|
|
setErrorEncounteredPage_NoNavBar(window, err, true, currentPage)
|
|
return
|
|
}
|
|
|
|
setHomePage(window)
|
|
})
|
|
|
|
selectUserButton.Importance = widget.HighImportance
|
|
|
|
userButtonsGrid.Add(selectUserButton)
|
|
}
|
|
|
|
userButtonsGridCentered := getContainerCentered(userButtonsGrid)
|
|
page.Add(userButtonsGridCentered)
|
|
|
|
page.Add(widget.NewSeparator())
|
|
}
|
|
|
|
createUserButton := widget.NewButtonWithIcon("Create User", theme.ContentAddIcon(), func(){
|
|
setCreateAppUserPage(window, currentPage, currentPage)
|
|
})
|
|
|
|
if (len(allUsersList) == 0){
|
|
|
|
createUserButtonCentered := getWidgetCentered(createUserButton)
|
|
|
|
page.Add(createUserButtonCentered)
|
|
} else {
|
|
|
|
renameUserButton := widget.NewButtonWithIcon("Rename User", theme.DocumentCreateIcon(), func(){
|
|
setRenameAppUserPage(window, currentPage, currentPage)
|
|
})
|
|
|
|
deleteUserButton := widget.NewButtonWithIcon("Delete User", theme.DeleteIcon(), func(){
|
|
setDeleteAppUserPage(window, currentPage, currentPage)
|
|
})
|
|
|
|
userActionButtonsGrid := getContainerCentered(container.NewGridWithColumns(1, createUserButton, renameUserButton, deleteUserButton))
|
|
|
|
page.Add(userActionButtonsGrid)
|
|
page.Add(widget.NewSeparator())
|
|
}
|
|
|
|
page.Add(layout.NewSpacer())
|
|
|
|
pageScrollable := container.NewVScroll(page)
|
|
|
|
window.SetContent(pageScrollable)
|
|
}
|
|
|
|
|
|
func setCreateAppUserPage(window fyne.Window, previousPage func(), afterCreatePage func()){
|
|
|
|
currentPage := func(){setCreateAppUserPage(window, previousPage, afterCreatePage)}
|
|
|
|
title := getPageTitleCentered("Create User")
|
|
|
|
backButton := getBackButtonCentered(previousPage)
|
|
|
|
userHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
|
|
setAppUserExplainerPage(window, currentPage)
|
|
})
|
|
description1 := getBoldLabel("Create a Seekia user.")
|
|
|
|
description1Row := container.NewHBox(layout.NewSpacer(), description1, userHelpButton, layout.NewSpacer())
|
|
|
|
description2 := widget.NewLabel("This name will not be shared publicly.")
|
|
|
|
nameEntry := widget.NewEntry()
|
|
nameEntry.PlaceHolder = "Enter name..."
|
|
|
|
nameEntryBoxed := getWidgetBoxed(nameEntry)
|
|
|
|
description2WithEntry := getContainerCentered(container.NewGridWithColumns(1, description2, nameEntryBoxed))
|
|
|
|
createUserButton := getWidgetCentered(widget.NewButtonWithIcon("Create", theme.ConfirmIcon(), func(){
|
|
|
|
newUserName := nameEntry.Text
|
|
|
|
if (newUserName == ""){
|
|
dialogTitle := translate("User Name Is Empty")
|
|
dialogMessageA := getLabelCentered(translate("The user name is empty."))
|
|
dialogMessageB := getLabelCentered(translate("Enter a name."))
|
|
dialogContent := container.NewVBox(dialogMessageA, dialogMessageB)
|
|
dialog.ShowCustom(dialogTitle, translate("Close"), dialogContent, window)
|
|
return
|
|
}
|
|
|
|
if (len(newUserName) > 30){
|
|
dialogTitle := translate("User Name Is Too Long")
|
|
dialogMessageA := getLabelCentered(translate("The user name is too long."))
|
|
dialogMessageB := getLabelCentered(translate("It cannot exceed 30 characters."))
|
|
dialogContent := container.NewVBox(dialogMessageA, dialogMessageB)
|
|
dialog.ShowCustom(dialogTitle, translate("Close"), dialogContent, window)
|
|
return
|
|
}
|
|
|
|
isAllowed := appUsers.VerifyAppUserNameCharactersAreAllowed(newUserName)
|
|
if (isAllowed == false){
|
|
dialogTitle := translate("User Name Is Not Allowed")
|
|
dialogMessageA := getLabelCentered(translate("The user name is not allowed."))
|
|
dialogMessageB := getLabelCentered(translate("It must contain only numbers and letters."))
|
|
dialogMessageC := getLabelCentered(translate("It cannot contain any spaces."))
|
|
dialogContent := container.NewVBox(dialogMessageA, dialogMessageB, dialogMessageC)
|
|
dialog.ShowCustom(dialogTitle, translate("Close"), dialogContent, window)
|
|
return
|
|
}
|
|
|
|
alreadyExists, err := appUsers.CreateAppUser(newUserName)
|
|
if (err != nil) {
|
|
setErrorEncounteredPage_NoNavBar(window, err, true, currentPage)
|
|
return
|
|
}
|
|
if (alreadyExists == true){
|
|
dialogTitle := translate("User Name Is A Duplicate.")
|
|
dialogMessageA := getLabelCentered(translate("You already have a user with this name."))
|
|
dialogMessageB := getLabelCentered(translate("Enter a unique name."))
|
|
dialogContent := container.NewVBox(dialogMessageA, dialogMessageB)
|
|
dialog.ShowCustom(dialogTitle, translate("Close"), dialogContent, window)
|
|
return
|
|
}
|
|
|
|
afterCreatePage()
|
|
}))
|
|
|
|
page := container.NewVBox(title, backButton, widget.NewSeparator(), description1Row, description2WithEntry, createUserButton)
|
|
|
|
window.SetContent(page)
|
|
}
|
|
|
|
func setAppUserExplainerPage(window fyne.Window, previousPage func()){
|
|
|
|
title := getPageTitleCentered("Help - App User")
|
|
|
|
backButton := getBackButtonCentered(previousPage)
|
|
|
|
description1 := getBoldLabelCentered("To use Seekia, you must create an app user.")
|
|
description2 := getLabelCentered("Each app user has its own data folder.")
|
|
description3 := getLabelCentered("Each user can create their own Mate, Host, and Moderator identity.")
|
|
description4 := getLabelCentered("This allows you to create multiple identities and switch between them.")
|
|
description5 := getLabelCentered("For example, you could operate 2 moderator identities and switch between them.")
|
|
description6 := getLabelCentered("Most users will only need to create 1 user.")
|
|
description7 := getLabelCentered("Your user names are never uploaded or shared anywhere.")
|
|
description8 := getLabelCentered("You must export each user's data when transferring to a new device.")
|
|
|
|
page := container.NewVBox(title, backButton, widget.NewSeparator(), description1, description2, description3, description4, description5, description6, description7, description8)
|
|
|
|
window.SetContent(page)
|
|
}
|
|
|
|
func setRenameAppUserPage(window fyne.Window, previousPage func(), afterRenamePage func()){
|
|
|
|
currentPage := func(){setRenameAppUserPage(window, previousPage, afterRenamePage)}
|
|
|
|
title := getPageTitleCentered("Rename User")
|
|
|
|
backButton := getBackButtonCentered(previousPage)
|
|
|
|
allUsersList, err := appUsers.GetAppUsersList()
|
|
if (err != nil){
|
|
setErrorEncounteredPage_NoNavBar(window, err, true, previousPage)
|
|
return
|
|
}
|
|
|
|
if (len(allUsersList) == 0){
|
|
setErrorEncounteredPage_NoNavBar(window, errors.New("setRenameAppUserPage called when no users exist."), true, previousPage)
|
|
return
|
|
}
|
|
|
|
selectUserLabel := getBoldLabelCentered("Select User:")
|
|
|
|
userSelector := widget.NewSelect(allUsersList, nil)
|
|
userSelector.PlaceHolder = "Select user..."
|
|
|
|
userSelectorCentered := getWidgetCentered(userSelector)
|
|
|
|
enterNewNameLabel := getBoldLabel("Enter New Name:")
|
|
|
|
newNameEntry := widget.NewEntry()
|
|
newNameEntry.SetPlaceHolder("Enter new name...")
|
|
|
|
newNameEntryBoxed := getWidgetBoxed(newNameEntry)
|
|
|
|
newNameEntryWithLabel := getContainerCentered(container.NewGridWithColumns(1, enterNewNameLabel, newNameEntryBoxed))
|
|
|
|
renameButton := getWidgetCentered(widget.NewButtonWithIcon("Rename", theme.ConfirmIcon(), func(){
|
|
|
|
currentUserNameSelectedIndex := userSelector.SelectedIndex()
|
|
if (currentUserNameSelectedIndex == -1){
|
|
dialogTitle := translate("No User Selected")
|
|
dialogMessageA := getLabelCentered(translate("No user is selected."))
|
|
dialogMessageB := getLabelCentered(translate("Select the user you want to rename."))
|
|
dialogContent := container.NewVBox(dialogMessageA, dialogMessageB)
|
|
dialog.ShowCustom(dialogTitle, translate("Close"), dialogContent, window)
|
|
return
|
|
}
|
|
|
|
currentUserName := userSelector.Selected
|
|
|
|
newUserName := newNameEntry.Text
|
|
|
|
if (newUserName == ""){
|
|
dialogTitle := translate("User Name Is Empty")
|
|
dialogMessageA := getLabelCentered(translate("The user name is empty."))
|
|
dialogMessageB := getLabelCentered(translate("Enter a name."))
|
|
dialogContent := container.NewVBox(dialogMessageA, dialogMessageB)
|
|
dialog.ShowCustom(dialogTitle, translate("Close"), dialogContent, window)
|
|
return
|
|
}
|
|
|
|
if (len(newUserName) > 30){
|
|
dialogTitle := translate("User Name Is Too Long")
|
|
dialogMessageA := getLabelCentered(translate("The user name is too long."))
|
|
dialogMessageB := getLabelCentered(translate("It cannot exceed 30 characters."))
|
|
dialogContent := container.NewVBox(dialogMessageA, dialogMessageB)
|
|
dialog.ShowCustom(dialogTitle, translate("Close"), dialogContent, window)
|
|
return
|
|
}
|
|
|
|
isAllowed := appUsers.VerifyAppUserNameCharactersAreAllowed(newUserName)
|
|
if (isAllowed == false){
|
|
dialogTitle := translate("User Name Is Not Allowed")
|
|
dialogMessageA := getLabelCentered(translate("The user name is not allowed."))
|
|
dialogMessageB := getLabelCentered(translate("It must contain only numbers and letters."))
|
|
dialogContent := container.NewVBox(dialogMessageA, dialogMessageB)
|
|
dialog.ShowCustom(dialogTitle, translate("Close"), dialogContent, window)
|
|
return
|
|
}
|
|
|
|
alreadyExists := slices.Contains(allUsersList, newUserName)
|
|
if (alreadyExists == true){
|
|
dialogTitle := translate("User Name Is A Duplicate.")
|
|
dialogMessageA := getLabelCentered(translate("You already have a user with this name."))
|
|
dialogMessageB := getLabelCentered(translate("Enter a unique name."))
|
|
dialogContent := container.NewVBox(dialogMessageA, dialogMessageB)
|
|
dialog.ShowCustom(dialogTitle, translate("Close"), dialogContent, window)
|
|
return
|
|
}
|
|
|
|
setLoadingScreen(window, translate("Rename User"), translate("Renaming User..."))
|
|
|
|
userFound, err := appUsers.RenameAppUser(currentUserName, newUserName)
|
|
if (err != nil){
|
|
setErrorEncounteredPage_NoNavBar(window, err, true, currentPage)
|
|
return
|
|
}
|
|
if (userFound == false){
|
|
setErrorEncounteredPage_NoNavBar(window, errors.New("App user not found after being found already."), true, currentPage)
|
|
return
|
|
}
|
|
|
|
afterRenamePage()
|
|
}))
|
|
|
|
page := container.NewVBox(title, backButton, widget.NewSeparator(), selectUserLabel, userSelectorCentered, newNameEntryWithLabel, renameButton)
|
|
|
|
window.SetContent(page)
|
|
}
|
|
|
|
|
|
func setDeleteAppUserPage(window fyne.Window, previousPage func(), afterDeletePage func()){
|
|
|
|
currentPage := func(){setDeleteAppUserPage(window, previousPage, afterDeletePage)}
|
|
|
|
title := getPageTitleCentered("Delete User")
|
|
|
|
backButton := getBackButtonCentered(previousPage)
|
|
|
|
description := getBoldLabelCentered("Choose the user to delete.")
|
|
|
|
allUsersList, err := appUsers.GetAppUsersList()
|
|
if (err != nil){
|
|
setErrorEncounteredPage_NoNavBar(window, err, true, previousPage)
|
|
return
|
|
}
|
|
|
|
if (len(allUsersList) == 0){
|
|
setErrorEncounteredPage_NoNavBar(window, errors.New("setDeleteAppUserPage called when no users exist."), true, previousPage)
|
|
return
|
|
}
|
|
|
|
userButtonsGrid := container.NewGridWithColumns(1)
|
|
|
|
for _, userName := range allUsersList{
|
|
|
|
selectUserButton := widget.NewButtonWithIcon(userName, theme.AccountIcon(), func(){
|
|
setConfirmDeleteAppUserPage(window, userName, currentPage, afterDeletePage)
|
|
})
|
|
|
|
userButtonsGrid.Add(selectUserButton)
|
|
}
|
|
|
|
userButtonsGridCentered := getContainerCentered(userButtonsGrid)
|
|
|
|
page := container.NewVBox(title, backButton, widget.NewSeparator(), description, widget.NewSeparator(), userButtonsGridCentered)
|
|
|
|
window.SetContent(page)
|
|
}
|
|
|
|
func setConfirmDeleteAppUserPage(window fyne.Window, userName string, previousPage func(), afterDeletePage func()){
|
|
|
|
setLoadingScreen(window, translate("Delete User"), translate("Loading Delete User Page..."))
|
|
|
|
currentPage := func(){setConfirmDeleteAppUserPage(window, userName, previousPage, afterDeletePage)}
|
|
|
|
title := getPageTitleCentered("Delete User")
|
|
|
|
backButton := getBackButtonCentered(previousPage)
|
|
|
|
// We sign in to the user to see if there are any user identities
|
|
|
|
getNumberOfUserIdentities := func()(int, error){
|
|
|
|
err := appUsers.SignInToAppUser(userName, false)
|
|
if (err != nil){ return 0, err }
|
|
|
|
numberOfIdentities := 0
|
|
|
|
mateIdentityExists, _, err := mySeedPhrases.GetMySeedPhrase("Mate")
|
|
if (err != nil) { return 0, err }
|
|
if (mateIdentityExists == true){
|
|
numberOfIdentities += 1
|
|
}
|
|
|
|
hostIdentityExists, _, err := mySeedPhrases.GetMySeedPhrase("Host")
|
|
if (err != nil) { return 0, err }
|
|
if (hostIdentityExists == true){
|
|
numberOfIdentities += 1
|
|
}
|
|
|
|
moderatorIdentityExists, _, err := mySeedPhrases.GetMySeedPhrase("Moderator")
|
|
if (err != nil) { return 0, err }
|
|
if (moderatorIdentityExists == true){
|
|
numberOfIdentities += 1
|
|
}
|
|
|
|
err = appUsers.SignOutOfAppUser()
|
|
if (err != nil){ return 0, err }
|
|
|
|
return numberOfIdentities, nil
|
|
}
|
|
|
|
numberOfIdentities, err := getNumberOfUserIdentities()
|
|
if (err != nil) {
|
|
setErrorEncounteredPage_NoNavBar(window, err, true, previousPage)
|
|
return
|
|
}
|
|
if (numberOfIdentities != 0){
|
|
|
|
getNumberOfIdentitiesDescription := func()string{
|
|
if (numberOfIdentities == 1){
|
|
return "This user has 1 identity."
|
|
}
|
|
|
|
numberOfIdentitiesString := helpers.ConvertIntToString(numberOfIdentities)
|
|
|
|
return "This user has " + numberOfIdentitiesString + " identities."
|
|
}
|
|
|
|
numberOfIdentitiesDescription := getNumberOfIdentitiesDescription()
|
|
|
|
description1 := getBoldLabelCentered(numberOfIdentitiesDescription)
|
|
description2 := getLabelCentered("You must delete all user identities before deleting the user.")
|
|
description3 := getLabelCentered("Delete your identities on the Settings - My Data - Delete Identity page.")
|
|
|
|
page := container.NewVBox(title, backButton, widget.NewSeparator(), description1, description2, description3)
|
|
window.SetContent(page)
|
|
return
|
|
}
|
|
|
|
description1 := getBoldLabelCentered("Are you sure you want to delete this user?")
|
|
|
|
nameLabel := widget.NewLabel("Name:")
|
|
userNameLabel := getBoldLabel(userName)
|
|
|
|
userNameRow := container.NewHBox(layout.NewSpacer(), nameLabel, userNameLabel, layout.NewSpacer())
|
|
|
|
description2 := getLabelCentered("This will delete all of your user data.")
|
|
description3 := getLabelCentered("This includes your desires, genetic analyses, genomes, and settings.")
|
|
description4 := getLabelCentered("Export your data on the Settings - My Data - Export Data page to retain your data.")
|
|
|
|
deleteButton := getWidgetCentered(widget.NewButtonWithIcon("Delete", theme.DeleteIcon(), func(){
|
|
|
|
setLoadingScreen(window, translate("Delete User"), translate("Deleting User..."))
|
|
|
|
userExists, err := appUsers.DeleteAppUser(userName)
|
|
if (err != nil){
|
|
setErrorEncounteredPage_NoNavBar(window, err, true, currentPage)
|
|
return
|
|
}
|
|
if (userExists == false){
|
|
setErrorEncounteredPage_NoNavBar(window, errors.New("setConfirmDeleteAppUserPage called when user does not exist."), true, currentPage)
|
|
return
|
|
}
|
|
afterDeletePage()
|
|
}))
|
|
|
|
page := container.NewVBox(title, backButton, widget.NewSeparator(), description1, userNameRow, description2, description3, description4, deleteButton)
|
|
|
|
window.SetContent(page)
|
|
}
|
|
|
|
|
|
|