2268 lines
84 KiB
Go
2268 lines
84 KiB
Go
|
package gui
|
||
|
|
||
|
//desiresGui_General.go implements pages to view and manage a user's General mate desires, view all their desires, and manage their download desires
|
||
|
|
||
|
import "fyne.io/fyne/v2"
|
||
|
import "fyne.io/fyne/v2/container"
|
||
|
import "fyne.io/fyne/v2/dialog"
|
||
|
import "fyne.io/fyne/v2/layout"
|
||
|
import "fyne.io/fyne/v2/theme"
|
||
|
import "fyne.io/fyne/v2/widget"
|
||
|
|
||
|
import "seekia/resources/worldLanguages"
|
||
|
import "seekia/resources/worldLocations"
|
||
|
|
||
|
import "seekia/internal/allowedText"
|
||
|
import "seekia/internal/appMemory"
|
||
|
import "seekia/internal/desires/mateDesires"
|
||
|
import "seekia/internal/desires/myLocalDesires"
|
||
|
import "seekia/internal/encoding"
|
||
|
import "seekia/internal/globalSettings"
|
||
|
import "seekia/internal/helpers"
|
||
|
import "seekia/internal/network/myMateCriteria"
|
||
|
import "seekia/internal/profiles/attributeDisplay"
|
||
|
|
||
|
import "strings"
|
||
|
import "errors"
|
||
|
import "slices"
|
||
|
|
||
|
func setDesiresPage(window fyne.Window){
|
||
|
|
||
|
appMemory.SetMemoryEntry("CurrentViewedPage", "Desires")
|
||
|
|
||
|
currentPage := func(){setDesiresPage(window)}
|
||
|
|
||
|
title := getPageTitleCentered(translate("My Mate Desires"))
|
||
|
|
||
|
description1 := getLabelCentered(translate("Select your Mate desires."))
|
||
|
description2 := getLabelCentered(translate("Your desires are used to generate your matches."))
|
||
|
description3 := getLabelCentered(translate("These desires not shared on your profile."))
|
||
|
|
||
|
generalIcon, err := getFyneImageIcon("General")
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, func(){setHomePage(window)})
|
||
|
return
|
||
|
}
|
||
|
generalButton := widget.NewButton(translate("General"), func(){
|
||
|
setChooseDesiresCategoryPage_General(window, currentPage)
|
||
|
})
|
||
|
generalButtonWithIcon := container.NewGridWithRows(2, generalIcon, generalButton)
|
||
|
|
||
|
physicalIcon, err := getFyneImageIcon("Person")
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, func(){setHomePage(window)})
|
||
|
return
|
||
|
}
|
||
|
physicalButton := widget.NewButton(translate("Physical"), func(){
|
||
|
setChooseDesiresCategoryPage_Physical(window, currentPage)
|
||
|
})
|
||
|
physicalButtonWithIcon := container.NewGridWithRows(2, physicalIcon, physicalButton)
|
||
|
|
||
|
lifestyleIcon, err := getFyneImageIcon("Lifestyle")
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, func(){setHomePage(window)})
|
||
|
return
|
||
|
}
|
||
|
lifestyleButton := widget.NewButton(translate("Lifestyle"), func(){
|
||
|
setChooseDesiresCategoryPage_Lifestyle(window, currentPage)
|
||
|
})
|
||
|
lifestyleButtonWithIcon := container.NewGridWithRows(2, lifestyleIcon, lifestyleButton)
|
||
|
|
||
|
mentalIcon, err := getFyneImageIcon("Mental")
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, func(){setHomePage(window)})
|
||
|
return
|
||
|
}
|
||
|
mentalButton := widget.NewButton(translate("Mental"), func(){
|
||
|
setChooseDesiresCategoryPage_Mental(window, currentPage)
|
||
|
})
|
||
|
mentalButtonWithIcon := container.NewGridWithRows(2, mentalIcon, mentalButton)
|
||
|
|
||
|
categoriesRow := getContainerCentered(container.NewGridWithRows(1, generalButtonWithIcon, physicalButtonWithIcon, lifestyleButtonWithIcon, mentalButtonWithIcon))
|
||
|
|
||
|
allDesiresIcon, err := getFyneImageIcon("Choice")
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, func(){setHomePage(window)})
|
||
|
return
|
||
|
}
|
||
|
|
||
|
viewAllDesiresButton := widget.NewButton("View All Desires", func(){
|
||
|
setViewAllMyDesiresPage(window, currentPage)
|
||
|
})
|
||
|
|
||
|
viewAllDesiresButtonWithIcon := container.NewGridWithRows(2, allDesiresIcon, viewAllDesiresButton)
|
||
|
|
||
|
statisticsIcon, err := getFyneImageIcon("Stats")
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, func(){setHomePage(window)})
|
||
|
return
|
||
|
}
|
||
|
|
||
|
viewAllStatisticsButton := widget.NewButton("View All Statistics", func(){
|
||
|
setViewAllMyDesireStatisticsPage(window, false, 0, 0, nil, currentPage)
|
||
|
})
|
||
|
|
||
|
viewAllStatisticsButtonWithIcon := container.NewGridWithColumns(1, statisticsIcon, viewAllStatisticsButton)
|
||
|
|
||
|
viewAllButtonsRow := getContainerCentered(container.NewGridWithRows(1, viewAllDesiresButtonWithIcon, viewAllStatisticsButtonWithIcon))
|
||
|
|
||
|
downloadDesiresIcon, err := getFyneImageIcon("Host")
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, func(){setHomePage(window)})
|
||
|
return
|
||
|
}
|
||
|
downloadDesiresButton := widget.NewButton("Download Desires", func(){
|
||
|
setManageMateDownloadDesiresPage(window, currentPage)
|
||
|
})
|
||
|
|
||
|
downloadDesiresButtonWithIcon := getContainerCentered(container.NewGridWithRows(2, downloadDesiresIcon, downloadDesiresButton))
|
||
|
|
||
|
page := container.NewVBox(title, widget.NewSeparator(), description1, description2, description3, widget.NewSeparator(), categoriesRow, widget.NewSeparator(), viewAllButtonsRow, widget.NewSeparator(), downloadDesiresButtonWithIcon)
|
||
|
|
||
|
setPageContent(page, window)
|
||
|
}
|
||
|
|
||
|
func setChooseDesiresCategoryPage_General(window fyne.Window, previousPage func()){
|
||
|
|
||
|
currentPage := func(){setChooseDesiresCategoryPage_General(window, previousPage)}
|
||
|
|
||
|
title := getPageTitleCentered(translate("My Mate Desires - General"))
|
||
|
|
||
|
backButton := getBackButtonCentered(previousPage)
|
||
|
|
||
|
profileLanguageButton := widget.NewButton("Profile Language", func(){
|
||
|
setChooseDesiresPage_ProfileLanguage(window, currentPage)
|
||
|
})
|
||
|
|
||
|
distanceButton := widget.NewButton("Distance", func(){
|
||
|
setChooseDesiresPage_Distance(window, currentPage)
|
||
|
})
|
||
|
|
||
|
countryButton := widget.NewButton("Country", func(){
|
||
|
setChooseDesiresPage_Country(window, currentPage)
|
||
|
})
|
||
|
|
||
|
sexualityButton := widget.NewButton("Sexuality", func(){
|
||
|
setChooseDesiresPage_Sexuality(window, currentPage)
|
||
|
})
|
||
|
|
||
|
searchTermsButton := widget.NewButton("Search Terms", func(){
|
||
|
setChooseDesiresPage_SearchTerms(window, currentPage)
|
||
|
})
|
||
|
|
||
|
chatButton := widget.NewButton("Chat", func(){
|
||
|
setChooseDesiresPage_Chat(window, currentPage)
|
||
|
})
|
||
|
|
||
|
likedUsersButton := widget.NewButton("Liked Users", func(){
|
||
|
setChooseDesiresPage_LikedUsers(window, currentPage)
|
||
|
})
|
||
|
|
||
|
ignoredUsersButton := widget.NewButton("Ignored Users", func(){
|
||
|
setChooseDesiresPage_IgnoredUsers(window, currentPage)
|
||
|
})
|
||
|
|
||
|
contactsButton := widget.NewButton("Contacts", func(){
|
||
|
setChooseDesiresPage_Contacts(window, currentPage)
|
||
|
})
|
||
|
|
||
|
buttonsGrid := getContainerCentered(container.NewGridWithColumns(1, profileLanguageButton, distanceButton, countryButton, sexualityButton, searchTermsButton, chatButton, likedUsersButton, ignoredUsersButton, contactsButton))
|
||
|
|
||
|
buttonsGridPadded := container.NewPadded(buttonsGrid)
|
||
|
|
||
|
page := container.NewVBox(title, backButton, widget.NewSeparator(), buttonsGridPadded)
|
||
|
|
||
|
setPageContent(page, window)
|
||
|
}
|
||
|
|
||
|
|
||
|
func setChooseDesiresPage_ProfileLanguage(window fyne.Window, previousPage func()){
|
||
|
|
||
|
currentPage := func(){setChooseDesiresPage_ProfileLanguage(window, previousPage)}
|
||
|
|
||
|
title := getPageTitleCentered("My Mate Desires - General")
|
||
|
|
||
|
backButton := getBackButtonCentered(previousPage)
|
||
|
|
||
|
subtitle := getPageSubtitleCentered("Profile Language")
|
||
|
|
||
|
description1 := getLabelCentered("Choose your profile language desires.")
|
||
|
description2 := getLabelCentered("A profile language is the language that a profile is written in.")
|
||
|
description3 := getLabelCentered("Choose all of the languages you can read.")
|
||
|
|
||
|
getSelectedLanguagesSection := func()(*fyne.Container, error){
|
||
|
|
||
|
getCurrentDesiredChoicesList := func()([]string, error){
|
||
|
|
||
|
currentChoicesListExists, currentChoicesList, err := myLocalDesires.GetDesire("ProfileLanguage")
|
||
|
if (err != nil) { return nil, err }
|
||
|
if (currentChoicesListExists == false){
|
||
|
|
||
|
emptyList := make([]string, 0)
|
||
|
return emptyList, nil
|
||
|
}
|
||
|
//currentChoicesList is a "+" separated list of choices
|
||
|
// Each choice option is encoded in base64
|
||
|
currentDesiredChoicesList := strings.Split(currentChoicesList, "+")
|
||
|
|
||
|
return currentDesiredChoicesList, nil
|
||
|
}
|
||
|
|
||
|
currentDesiredChoicesList, err := getCurrentDesiredChoicesList()
|
||
|
if (err != nil) { return nil, err }
|
||
|
|
||
|
addLanguageButton := getWidgetCentered(widget.NewButtonWithIcon("Add Language", theme.ContentAddIcon(), func(){
|
||
|
|
||
|
submitLanguageFunction := func(newLanguageIdentifier int, _ string)error{
|
||
|
|
||
|
newLanguageIdentifierString := helpers.ConvertIntToString(newLanguageIdentifier)
|
||
|
|
||
|
newLanguageIdentifierBase64 := encoding.EncodeBytesToBase64String([]byte(newLanguageIdentifierString))
|
||
|
|
||
|
newLanguagesList := helpers.AddItemToStringListAndAvoidDuplicate(currentDesiredChoicesList, newLanguageIdentifierBase64)
|
||
|
|
||
|
newDesireString := strings.Join(newLanguagesList, "+")
|
||
|
|
||
|
err = myLocalDesires.SetDesire("ProfileLanguage", newDesireString)
|
||
|
if (err != nil){ return err }
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
setChooseDesiresPage_AddLanguage(window, submitLanguageFunction, currentPage, currentPage)
|
||
|
}))
|
||
|
|
||
|
if (len(currentDesiredChoicesList) == 0){
|
||
|
|
||
|
noLanguagesLabel := getBoldLabelCentered("No Languages Selected.")
|
||
|
|
||
|
selectedLanguagesSection := container.NewVBox(noLanguagesLabel, addLanguageButton)
|
||
|
|
||
|
return selectedLanguagesSection, nil
|
||
|
}
|
||
|
|
||
|
myDesiredLanguagesLabel := getItalicLabelCentered("My Desired Languages:")
|
||
|
|
||
|
languageNameColumn := container.NewVBox(widget.NewSeparator())
|
||
|
|
||
|
deleteButtonsColumn := container.NewVBox(widget.NewSeparator())
|
||
|
|
||
|
for _, languageIdentifierBase64 := range currentDesiredChoicesList{
|
||
|
|
||
|
languageIdentifierString, err := encoding.DecodeBase64StringToUnicodeString(languageIdentifierBase64)
|
||
|
if (err != nil){
|
||
|
return nil, errors.New("My current profile language desire is malformed: Contains invalid language: " + languageIdentifierBase64)
|
||
|
}
|
||
|
|
||
|
languageIdentifier, err := helpers.ConvertStringToInt(languageIdentifierString)
|
||
|
if (err != nil){
|
||
|
return nil, errors.New("My current profile language desire is malformed: Contains invalid language: " + languageIdentifierString)
|
||
|
}
|
||
|
|
||
|
languageObject, err := worldLanguages.GetLanguageObjectFromLanguageIdentifier(languageIdentifier)
|
||
|
if (err != nil){
|
||
|
return nil, errors.New("My current profile language desire is malformed: Contains unknown language identifier: " + languageIdentifierString)
|
||
|
}
|
||
|
|
||
|
languageNamesList := languageObject.NamesList
|
||
|
|
||
|
languageDescription := helpers.TranslateAndJoinStringListItems(languageNamesList, "/")
|
||
|
|
||
|
languageDescriptionTrimmed, _, err := helpers.TrimAndFlattenString(languageDescription, 20)
|
||
|
if (err != nil) { return nil, err }
|
||
|
|
||
|
languageNameLabel := getBoldLabelCentered(languageDescriptionTrimmed)
|
||
|
|
||
|
deleteLanguageButton := widget.NewButtonWithIcon("", theme.DeleteIcon(), func(){
|
||
|
|
||
|
newDesiredLanguagesList, _ := helpers.DeleteAllMatchingItemsFromStringList(currentDesiredChoicesList, languageIdentifierBase64)
|
||
|
|
||
|
if (len(newDesiredLanguagesList) == 0){
|
||
|
|
||
|
err := myLocalDesires.DeleteDesire("ProfileLanguage")
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, currentPage)
|
||
|
return
|
||
|
}
|
||
|
currentPage()
|
||
|
return
|
||
|
}
|
||
|
|
||
|
newDesireValueString := strings.Join(newDesiredLanguagesList, "+")
|
||
|
|
||
|
err := myLocalDesires.SetDesire("ProfileLanguage", newDesireValueString)
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, currentPage)
|
||
|
return
|
||
|
}
|
||
|
currentPage()
|
||
|
})
|
||
|
|
||
|
languageNameColumn.Add(languageNameLabel)
|
||
|
deleteButtonsColumn.Add(deleteLanguageButton)
|
||
|
|
||
|
languageNameColumn.Add(widget.NewSeparator())
|
||
|
deleteButtonsColumn.Add(widget.NewSeparator())
|
||
|
}
|
||
|
|
||
|
languagesGrid := container.NewHBox(layout.NewSpacer(), languageNameColumn, deleteButtonsColumn, layout.NewSpacer())
|
||
|
|
||
|
selectedLanguagesSection := container.NewVBox(addLanguageButton, widget.NewSeparator(), myDesiredLanguagesLabel, languagesGrid)
|
||
|
|
||
|
return selectedLanguagesSection, nil
|
||
|
}
|
||
|
|
||
|
selectedLanguagesSection, err := getSelectedLanguagesSection()
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, previousPage)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
filterOptionsSection, err := getDesireEditorFilterOptionsSection(window, currentPage, "ProfileLanguage", true)
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, previousPage)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
viewStatisticsButton := getWidgetCentered(widget.NewButtonWithIcon("View Statistics", theme.InfoIcon(), func(){
|
||
|
setViewMyMateDesireStatisticsPage(window, "Profile Language", "ProfileLanguage", true, "Bar", "ProfileLanguage", currentPage)
|
||
|
}))
|
||
|
|
||
|
page := container.NewVBox(title, backButton, widget.NewSeparator(), subtitle, widget.NewSeparator(), description1, description2, description3, widget.NewSeparator(), selectedLanguagesSection, widget.NewSeparator(), filterOptionsSection, widget.NewSeparator(), viewStatisticsButton)
|
||
|
|
||
|
setPageContent(page, window)
|
||
|
}
|
||
|
|
||
|
func setChooseDesiresPage_Distance(window fyne.Window, previousPage func()){
|
||
|
|
||
|
currentPage := func(){setChooseDesiresPage_Distance(window, previousPage)}
|
||
|
|
||
|
title := getPageTitleCentered(translate("My Mate Desires - General"))
|
||
|
|
||
|
backButton := getBackButtonCentered(previousPage)
|
||
|
|
||
|
subtitle := getPageSubtitleCentered(translate("Distance"))
|
||
|
|
||
|
description1 := getLabelCentered("Choose your desired user distance.")
|
||
|
description2 := getLabelCentered("You must add a primary location to your profile to calculate distance.")
|
||
|
|
||
|
metricOrImperialSwitchButton, err := getMetricImperialSwitchButton(window, currentPage)
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, previousPage)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
currentUnitsLabel := getItalicLabel("Current Units:")
|
||
|
|
||
|
currentUnitsRow := container.NewHBox(layout.NewSpacer(), currentUnitsLabel, metricOrImperialSwitchButton, layout.NewSpacer())
|
||
|
|
||
|
getMyMetricOrImperial := func()(string, error){
|
||
|
|
||
|
exists, metricOrImperial, err := globalSettings.GetSetting("MetricOrImperial")
|
||
|
if (err != nil) { return "", err }
|
||
|
if (exists == false){
|
||
|
return "Metric", nil
|
||
|
}
|
||
|
if (metricOrImperial != "Metric" && metricOrImperial != "Imperial"){
|
||
|
return "", errors.New("Malformed globalSettings: Invalid metricOrImperial: " + metricOrImperial)
|
||
|
}
|
||
|
|
||
|
return metricOrImperial, nil
|
||
|
}
|
||
|
|
||
|
myMetricOrImperial, err := getMyMetricOrImperial()
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, previousPage)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
getCurrentUnits := func()string{
|
||
|
if (myMetricOrImperial == "Metric"){
|
||
|
return "kilometers"
|
||
|
}
|
||
|
return "miles"
|
||
|
}
|
||
|
|
||
|
currentUnits := getCurrentUnits()
|
||
|
|
||
|
// Distance is normally represented in metric
|
||
|
// Metric is the standard, and Imperial is custom
|
||
|
|
||
|
getUnitsAreCustomBool := func()bool{
|
||
|
|
||
|
if (myMetricOrImperial == "Metric"){
|
||
|
return false
|
||
|
}
|
||
|
return true
|
||
|
}
|
||
|
|
||
|
unitsAreCustomBool := getUnitsAreCustomBool()
|
||
|
|
||
|
convertToMetricFunction := helpers.ConvertMilesToKilometers
|
||
|
|
||
|
convertToImperialFunction := helpers.ConvertKilometersToMiles
|
||
|
|
||
|
desireEditor, err := getDesireEditor_Numeric(window, currentPage, "Distance", 0, 20000, currentUnits, 2, unitsAreCustomBool, convertToMetricFunction, convertToImperialFunction, false, "", "", nil)
|
||
|
if (err != nil) {
|
||
|
setErrorEncounteredPage(window, err, previousPage)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
viewStatisticsButton := getWidgetCentered(widget.NewButtonWithIcon("View Statistics", theme.InfoIcon(), func(){
|
||
|
setViewMyMateDesireStatisticsPage(window, "Distance", "Distance", true, "Bar", "Distance", currentPage)
|
||
|
}))
|
||
|
|
||
|
page := container.NewVBox(title, backButton, widget.NewSeparator(), subtitle, widget.NewSeparator(), description1, description2, widget.NewSeparator(), currentUnitsRow, widget.NewSeparator(), desireEditor, widget.NewSeparator(), viewStatisticsButton)
|
||
|
|
||
|
setPageContent(page, window)
|
||
|
}
|
||
|
|
||
|
|
||
|
func setChooseDesiresPage_Country(window fyne.Window, previousPage func()){
|
||
|
|
||
|
currentPage := func(){setChooseDesiresPage_Country(window, previousPage)}
|
||
|
|
||
|
title := getPageTitleCentered("My Mate Desires - General")
|
||
|
|
||
|
backButton := getBackButtonCentered(previousPage)
|
||
|
|
||
|
subtitle := getPageSubtitleCentered("Country")
|
||
|
|
||
|
description1 := getLabelCentered("Choose your country desires.")
|
||
|
description2 := getLabelCentered("Select the countries where you want your matches to live in.")
|
||
|
description3 := getLabelCentered("Most users should only use this desire if they live near a border.")
|
||
|
description4 := getLabelCentered("Most users should only need to use the Distance desire.")
|
||
|
|
||
|
getSelectedCountriesSection := func()(*fyne.Container, error){
|
||
|
|
||
|
getCurrentDesiredChoicesList := func()([]string, error){
|
||
|
|
||
|
currentChoicesListExists, currentChoicesList, err := myLocalDesires.GetDesire("PrimaryLocationCountry")
|
||
|
if (err != nil) { return nil, err }
|
||
|
if (currentChoicesListExists == false){
|
||
|
|
||
|
emptyList := make([]string, 0)
|
||
|
return emptyList, nil
|
||
|
}
|
||
|
//currentChoicesList is a "+" separated list of choices
|
||
|
// Each choice option is encoded in base64
|
||
|
currentDesiredChoicesList := strings.Split(currentChoicesList, "+")
|
||
|
|
||
|
return currentDesiredChoicesList, nil
|
||
|
}
|
||
|
|
||
|
currentDesiredChoicesList, err := getCurrentDesiredChoicesList()
|
||
|
if (err != nil) { return nil, err }
|
||
|
|
||
|
addCountryButton := getWidgetCentered(widget.NewButtonWithIcon("Add Country", theme.ContentAddIcon(), func(){
|
||
|
|
||
|
setChooseMateDesiresPage_ChooseCountry(window, currentPage, currentPage)
|
||
|
}))
|
||
|
|
||
|
if (len(currentDesiredChoicesList) == 0){
|
||
|
|
||
|
noCountriesLabel := getBoldLabelCentered("No Countries Selected.")
|
||
|
|
||
|
selectedCountriesSection := container.NewVBox(noCountriesLabel, addCountryButton)
|
||
|
|
||
|
return selectedCountriesSection, nil
|
||
|
}
|
||
|
|
||
|
myDesiredCountriesLabel := getItalicLabelCentered("My Desired Countries:")
|
||
|
|
||
|
countryNameColumn := container.NewVBox(widget.NewSeparator())
|
||
|
|
||
|
deleteButtonsColumn := container.NewVBox(widget.NewSeparator())
|
||
|
|
||
|
for _, countryIdentifierBase64 := range currentDesiredChoicesList{
|
||
|
|
||
|
countryIdentifierString, err := encoding.DecodeBase64StringToUnicodeString(countryIdentifierBase64)
|
||
|
if (err != nil){
|
||
|
return nil, errors.New("My current profile country desire is malformed: Contains invalid country: " + countryIdentifierBase64)
|
||
|
}
|
||
|
|
||
|
countryIdentifier, err := helpers.ConvertStringToInt(countryIdentifierString)
|
||
|
if (err != nil){
|
||
|
return nil, errors.New("My current profile country desire is malformed: Contains invalid country: " + countryIdentifierString)
|
||
|
}
|
||
|
|
||
|
countryObject, err := worldLocations.GetCountryObjectFromCountryIdentifier(countryIdentifier)
|
||
|
if (err != nil){
|
||
|
return nil, errors.New("My current profile country is malformed: Contains unknown country identifier: " + countryIdentifierString)
|
||
|
}
|
||
|
|
||
|
countryNamesList := countryObject.NamesList
|
||
|
|
||
|
countryDescription := helpers.TranslateAndJoinStringListItems(countryNamesList, "/")
|
||
|
|
||
|
countryNameLabel := getBoldLabelCentered(countryDescription)
|
||
|
|
||
|
deleteCountryButton := widget.NewButtonWithIcon("", theme.DeleteIcon(), func(){
|
||
|
|
||
|
newDesiredCountriesList, _ := helpers.DeleteAllMatchingItemsFromStringList(currentDesiredChoicesList, countryIdentifierBase64)
|
||
|
|
||
|
if (len(newDesiredCountriesList) == 0){
|
||
|
|
||
|
err := myLocalDesires.DeleteDesire("PrimaryLocationCountry")
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, currentPage)
|
||
|
return
|
||
|
}
|
||
|
currentPage()
|
||
|
return
|
||
|
}
|
||
|
|
||
|
newDesireValueString := strings.Join(newDesiredCountriesList, "+")
|
||
|
|
||
|
err := myLocalDesires.SetDesire("PrimaryLocationCountry", newDesireValueString)
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, currentPage)
|
||
|
return
|
||
|
}
|
||
|
currentPage()
|
||
|
})
|
||
|
|
||
|
countryNameColumn.Add(countryNameLabel)
|
||
|
deleteButtonsColumn.Add(deleteCountryButton)
|
||
|
|
||
|
countryNameColumn.Add(widget.NewSeparator())
|
||
|
deleteButtonsColumn.Add(widget.NewSeparator())
|
||
|
}
|
||
|
|
||
|
countriesGrid := container.NewHBox(layout.NewSpacer(), countryNameColumn, deleteButtonsColumn, layout.NewSpacer())
|
||
|
|
||
|
selectedCountriesSection := container.NewVBox(addCountryButton, widget.NewSeparator(), myDesiredCountriesLabel, countriesGrid)
|
||
|
|
||
|
return selectedCountriesSection, nil
|
||
|
}
|
||
|
|
||
|
selectedCountriesSection, err := getSelectedCountriesSection()
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, previousPage)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
filterOptionsSection, err := getDesireEditorFilterOptionsSection(window, currentPage, "PrimaryLocationCountry", true)
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, previousPage)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
viewStatisticsButton := getWidgetCentered(widget.NewButtonWithIcon("View Statistics", theme.InfoIcon(), func(){
|
||
|
setViewMyMateDesireStatisticsPage(window, "Country", "PrimaryLocationCountry", true, "Donut", "PrimaryLocationCountry", currentPage)
|
||
|
}))
|
||
|
|
||
|
page := container.NewVBox(title, backButton, widget.NewSeparator(), subtitle, widget.NewSeparator(), description1, description2, description3, description4, widget.NewSeparator(), selectedCountriesSection, widget.NewSeparator(), filterOptionsSection, widget.NewSeparator(), viewStatisticsButton)
|
||
|
|
||
|
setPageContent(page, window)
|
||
|
}
|
||
|
|
||
|
func setChooseMateDesiresPage_ChooseCountry(window fyne.Window, previousPage func(), nextPage func()){
|
||
|
|
||
|
currentPage := func(){setChooseMateDesiresPage_ChooseCountry(window, previousPage, nextPage)}
|
||
|
|
||
|
title := getPageTitleCentered(translate("My Mate Desires - General"))
|
||
|
|
||
|
backButton := getBackButtonCentered(previousPage)
|
||
|
|
||
|
subtitle := getPageSubtitleCentered(translate("Add Country"))
|
||
|
|
||
|
description1 := getLabelCentered("Choose the country to add.")
|
||
|
|
||
|
allCountryObjectsList, err := worldLocations.GetAllCountryObjectsList()
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, previousPage)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
allTranslatedCountriesList := make([]string, 0, len(allCountryObjectsList))
|
||
|
|
||
|
// Map Structure: Country Description -> Country identifier
|
||
|
countryIdentifiersMap := make(map[string]int)
|
||
|
|
||
|
for _, countryObject := range allCountryObjectsList{
|
||
|
|
||
|
countryIdentifier := countryObject.Identifier
|
||
|
countryNamesList := countryObject.NamesList
|
||
|
|
||
|
countryDescription := helpers.TranslateAndJoinStringListItems(countryNamesList, "/")
|
||
|
|
||
|
countryIdentifiersMap[countryDescription] = countryIdentifier
|
||
|
allTranslatedCountriesList = append(allTranslatedCountriesList, countryDescription)
|
||
|
}
|
||
|
|
||
|
helpers.SortStringListToUnicodeOrder(allTranslatedCountriesList)
|
||
|
|
||
|
onSelectedFunction := func(selectedCountryIndex int) {
|
||
|
|
||
|
selectedCountryDescription := allTranslatedCountriesList[selectedCountryIndex]
|
||
|
|
||
|
selectedCountryIdentifier, exists := countryIdentifiersMap[selectedCountryDescription]
|
||
|
if (exists == false){
|
||
|
setErrorEncounteredPage(window, errors.New("countryIdentifiersMap missing country description."), currentPage)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
selectedCountryIdentifierString := helpers.ConvertIntToString(selectedCountryIdentifier)
|
||
|
|
||
|
newCountryIdentifierBase64 := encoding.EncodeBytesToBase64String([]byte(selectedCountryIdentifierString))
|
||
|
|
||
|
getNewDesiredAttributeList := func()([]string, error){
|
||
|
|
||
|
currentChoicesListExists, currentChoicesList, err := myLocalDesires.GetDesire("PrimaryLocationCountry")
|
||
|
if (err != nil) { return nil, err }
|
||
|
if (currentChoicesListExists == false){
|
||
|
|
||
|
newList := []string{newCountryIdentifierBase64}
|
||
|
return newList, nil
|
||
|
}
|
||
|
//currentChoicesList is a "+" separated list of choices
|
||
|
// Each choice option is encoded in base64
|
||
|
currentDesiredChoicesList := strings.Split(currentChoicesList, "+")
|
||
|
|
||
|
newCountriesList := helpers.AddItemToStringListAndAvoidDuplicate(currentDesiredChoicesList, newCountryIdentifierBase64)
|
||
|
|
||
|
return newCountriesList, nil
|
||
|
}
|
||
|
|
||
|
newDesiredAttributeList, err := getNewDesiredAttributeList()
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, currentPage)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
newDesireString := strings.Join(newDesiredAttributeList, "+")
|
||
|
|
||
|
err = myLocalDesires.SetDesire("PrimaryLocationCountry", newDesireString)
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, currentPage)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
nextPage()
|
||
|
}
|
||
|
|
||
|
widgetList, err := getFyneWidgetListFromStringList(allTranslatedCountriesList, onSelectedFunction)
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, previousPage)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
header := container.NewVBox(title, backButton, widget.NewSeparator(), subtitle, widget.NewSeparator(), description1, widget.NewSeparator())
|
||
|
|
||
|
page := container.NewBorder(header, nil, nil, nil, widgetList)
|
||
|
|
||
|
setPageContent(page, window)
|
||
|
}
|
||
|
|
||
|
func setChooseDesiresPage_Sexuality(window fyne.Window, previousPage func()){
|
||
|
|
||
|
currentPage := func(){setChooseDesiresPage_Sexuality(window, previousPage)}
|
||
|
|
||
|
title := getPageTitleCentered("My Mate Desires - General")
|
||
|
|
||
|
backButton := getBackButtonCentered(previousPage)
|
||
|
|
||
|
subtitle := getPageSubtitleCentered(translate("Sexuality"))
|
||
|
|
||
|
description1 := getLabelCentered("Choose the user sexualities that you desire.")
|
||
|
description2 := getLabelCentered("This refers to which sexes the users are interested in.")
|
||
|
description3 := getLabelCentered("For example, if you are Male, you should at least select Male.")
|
||
|
|
||
|
option1Translated := translate("Male")
|
||
|
option2Translated := translate("Female")
|
||
|
option3Translated := translate("Male And Female")
|
||
|
|
||
|
optionTitlesList := []string{option1Translated, option2Translated, option3Translated}
|
||
|
|
||
|
optionNamesMap := map[string][]string{
|
||
|
option1Translated: []string{"Male"},
|
||
|
option2Translated: []string{"Female"},
|
||
|
option3Translated: []string{"Male And Female"},
|
||
|
}
|
||
|
|
||
|
desireEditor, err := getDesireEditor_Choice(window, currentPage, "Sexuality", optionTitlesList, optionNamesMap, false, true, 1)
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, previousPage)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
viewStatisticsButton := getWidgetCentered(widget.NewButtonWithIcon("View Statistics", theme.InfoIcon(), func(){
|
||
|
setViewMyMateDesireStatisticsPage(window, "Sexuality", "Sexuality", true, "Donut", "Sexuality", currentPage)
|
||
|
}))
|
||
|
|
||
|
page := container.NewVBox(title, backButton, widget.NewSeparator(), subtitle, widget.NewSeparator(), description1, description2, description3, widget.NewSeparator(), desireEditor, widget.NewSeparator(), viewStatisticsButton)
|
||
|
|
||
|
setPageContent(page, window)
|
||
|
}
|
||
|
|
||
|
func setChooseDesiresPage_SearchTerms(window fyne.Window, previousPage func()){
|
||
|
|
||
|
currentPage := func(){setChooseDesiresPage_SearchTerms(window, previousPage)}
|
||
|
|
||
|
title := getPageTitleCentered(translate("My Mate Desires - General"))
|
||
|
|
||
|
backButton := getBackButtonCentered(previousPage)
|
||
|
|
||
|
subtitle := getPageSubtitleCentered("Search Terms")
|
||
|
|
||
|
description1 := getLabelCentered("Choose your desired search terms.")
|
||
|
description2 := getLabelCentered("Seekia will search through each user's profile for your terms.")
|
||
|
description3 := getLabelCentered("Each user's description, tags, hobbies, and beliefs will be searched.")
|
||
|
description4 := getLabelCentered("A user's profile must contain at least 1 of your terms to pass the desire.")
|
||
|
|
||
|
getSelectedSearchTermsSection := func()(*fyne.Container, error){
|
||
|
|
||
|
getCurrentDesiredChoicesList := func()([]string, error){
|
||
|
|
||
|
currentChoicesListExists, currentChoicesList, err := myLocalDesires.GetDesire("SearchTerms")
|
||
|
if (err != nil) { return nil, err }
|
||
|
if (currentChoicesListExists == false){
|
||
|
|
||
|
emptyList := make([]string, 0)
|
||
|
return emptyList, nil
|
||
|
}
|
||
|
// currentChoicesList is a "+" separated list of choices
|
||
|
// Each choice option is encoded in base64
|
||
|
currentDesiredChoicesList := strings.Split(currentChoicesList, "+")
|
||
|
|
||
|
return currentDesiredChoicesList, nil
|
||
|
}
|
||
|
|
||
|
currentDesiredChoicesList, err := getCurrentDesiredChoicesList()
|
||
|
if (err != nil) { return nil, err }
|
||
|
|
||
|
addTermEntry := widget.NewEntry()
|
||
|
addTermEntry.SetPlaceHolder("Enter term name...")
|
||
|
|
||
|
addTermButton := getWidgetCentered(widget.NewButtonWithIcon("Add Term", theme.ContentAddIcon(), func(){
|
||
|
|
||
|
newTermName := addTermEntry.Text
|
||
|
|
||
|
if (newTermName == ""){
|
||
|
return
|
||
|
}
|
||
|
isAllowed := allowedText.VerifyStringIsAllowed(newTermName)
|
||
|
if (isAllowed == false){
|
||
|
title := translate("Invalid Term Name")
|
||
|
dialogMessageA := getLabelCentered(translate("Your search term contains an invalid character."))
|
||
|
dialogMessageB := getLabelCentered(translate("It must be encoded in UTF-8."))
|
||
|
dialogMessageC := getLabelCentered(translate("Remove this character and resubmit."))
|
||
|
dialogContent := container.NewVBox(dialogMessageA, dialogMessageB, dialogMessageC)
|
||
|
dialog.ShowCustom(title, translate("Close"), dialogContent, window)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
containsTabsOrNewlines := helpers.CheckIfStringContainsTabsOrNewlines(newTermName)
|
||
|
if (containsTabsOrNewlines == true){
|
||
|
title := translate("Invalid Term Name")
|
||
|
dialogMessageA := getLabelCentered(translate("Your search term contains a tab or a newline."))
|
||
|
dialogMessageB := getLabelCentered(translate("Remove the tab or newline and resubmit."))
|
||
|
dialogContent := container.NewVBox(dialogMessageA, dialogMessageB)
|
||
|
dialog.ShowCustom(title, translate("Close"), dialogContent, window)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
termNameBase64 := encoding.EncodeBytesToBase64String([]byte(newTermName))
|
||
|
|
||
|
newDesireList := helpers.AddItemToStringListAndAvoidDuplicate(currentDesiredChoicesList, termNameBase64)
|
||
|
newDesireAttributeValue := strings.Join(newDesireList, "+")
|
||
|
|
||
|
err := myLocalDesires.SetDesire("SearchTerms", newDesireAttributeValue)
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, currentPage)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
currentPage()
|
||
|
}))
|
||
|
|
||
|
addTermRow := getContainerCentered(container.NewGridWithRows(1, addTermEntry, addTermButton))
|
||
|
|
||
|
if (len(currentDesiredChoicesList) == 0){
|
||
|
|
||
|
noTermsExistLabel := getBoldLabelCentered("No Terms Exist.")
|
||
|
|
||
|
selectedSearchTermsSection := container.NewVBox(addTermRow, widget.NewSeparator(), noTermsExistLabel)
|
||
|
|
||
|
return selectedSearchTermsSection, nil
|
||
|
}
|
||
|
|
||
|
myDesiredTermsLabel := getItalicLabelCentered("My Desired Terms:")
|
||
|
|
||
|
termNameColumn := container.NewVBox(widget.NewSeparator())
|
||
|
|
||
|
deleteButtonsColumn := container.NewVBox(widget.NewSeparator())
|
||
|
|
||
|
for _, termNameBase64 := range currentDesiredChoicesList{
|
||
|
|
||
|
termName, err := encoding.DecodeBase64StringToUnicodeString(termNameBase64)
|
||
|
if (err != nil){
|
||
|
return nil, errors.New("My current search terms desire is malformed: Contains invalid term: " + termNameBase64)
|
||
|
}
|
||
|
|
||
|
termNameLabel := getBoldLabelCentered(termName)
|
||
|
|
||
|
deleteTermButton := widget.NewButtonWithIcon("", theme.DeleteIcon(), func(){
|
||
|
|
||
|
newDesiredTermsList, _ := helpers.DeleteAllMatchingItemsFromStringList(currentDesiredChoicesList, termNameBase64)
|
||
|
|
||
|
if (len(newDesiredTermsList) == 0){
|
||
|
|
||
|
err := myLocalDesires.DeleteDesire("SearchTerms")
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, currentPage)
|
||
|
return
|
||
|
}
|
||
|
currentPage()
|
||
|
return
|
||
|
}
|
||
|
|
||
|
newDesireValueString := strings.Join(newDesiredTermsList, "+")
|
||
|
|
||
|
err := myLocalDesires.SetDesire("SearchTerms", newDesireValueString)
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, currentPage)
|
||
|
return
|
||
|
}
|
||
|
currentPage()
|
||
|
})
|
||
|
|
||
|
termNameColumn.Add(termNameLabel)
|
||
|
deleteButtonsColumn.Add(deleteTermButton)
|
||
|
|
||
|
termNameColumn.Add(widget.NewSeparator())
|
||
|
deleteButtonsColumn.Add(widget.NewSeparator())
|
||
|
}
|
||
|
|
||
|
termsGrid := container.NewHBox(layout.NewSpacer(), termNameColumn, deleteButtonsColumn, layout.NewSpacer())
|
||
|
|
||
|
selectedTermsSection := container.NewVBox(addTermRow, widget.NewSeparator(), myDesiredTermsLabel, termsGrid)
|
||
|
|
||
|
return selectedTermsSection, nil
|
||
|
}
|
||
|
|
||
|
selectedTermsSection, err := getSelectedSearchTermsSection()
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, previousPage)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
filterOptionsSection, err := getDesireEditorFilterOptionsSection(window, currentPage, "SearchTerms", false)
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, previousPage)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
viewStatisticsButton := getWidgetCentered(widget.NewButtonWithIcon("View Statistics", theme.InfoIcon(), func(){
|
||
|
setViewMyMateDesireStatisticsPage(window, "Search Terms", "SearchTerms", true, "Bar", "SearchTermsCount", currentPage)
|
||
|
}))
|
||
|
|
||
|
page := container.NewVBox(title, backButton, widget.NewSeparator(), subtitle, widget.NewSeparator(), description1, description2, description3, description4, widget.NewSeparator(), selectedTermsSection, widget.NewSeparator(), filterOptionsSection, widget.NewSeparator(), viewStatisticsButton)
|
||
|
|
||
|
setPageContent(page, window)
|
||
|
}
|
||
|
|
||
|
func setChooseDesiresPage_Chat(window fyne.Window, previousPage func()){
|
||
|
|
||
|
currentPage := func(){setChooseDesiresPage_Chat(window, previousPage)}
|
||
|
|
||
|
title := getPageTitleCentered(translate("My Mate Desires - General"))
|
||
|
|
||
|
backButton := getBackButtonCentered(previousPage)
|
||
|
|
||
|
subtitle := getPageSubtitleCentered("Chat Desires")
|
||
|
|
||
|
description1 := getLabelCentered("Choose your chat desires.")
|
||
|
|
||
|
hasMessagedMeButton := widget.NewButton("Has Messaged Me", func(){
|
||
|
setChooseDesiresPage_HasMessagedMe(window, currentPage)
|
||
|
})
|
||
|
|
||
|
iHaveMessagedButton := widget.NewButton("I Have Messaged", func(){
|
||
|
setChooseDesiresPage_IHaveMessaged(window, currentPage)
|
||
|
})
|
||
|
|
||
|
hasRejectedMeButton := widget.NewButton("Has Rejected Me", func(){
|
||
|
setChooseDesiresPage_HasRejectedMe(window, currentPage)
|
||
|
})
|
||
|
|
||
|
hasAnsweredQuestionnaireButton := widget.NewButton("Has Answered Questionnaire", func(){
|
||
|
//TODO
|
||
|
// We need to include the functionality to only show users who responded in a specified way
|
||
|
// For example, if the user's question is: Do you like french fries?, and the user has 2 options: Yes/No,
|
||
|
// the user should be able to filter users who answered with yes/no
|
||
|
showUnderConstructionDialog(window)
|
||
|
})
|
||
|
|
||
|
buttonsGrid := getContainerCentered(container.NewGridWithColumns(1, hasMessagedMeButton, iHaveMessagedButton, hasRejectedMeButton, hasAnsweredQuestionnaireButton))
|
||
|
|
||
|
page := container.NewVBox(title, backButton, widget.NewSeparator(), subtitle, widget.NewSeparator(), description1, widget.NewSeparator(), buttonsGrid)
|
||
|
|
||
|
setPageContent(page, window)
|
||
|
}
|
||
|
|
||
|
func setChooseDesiresPage_HasMessagedMe(window fyne.Window, previousPage func()){
|
||
|
|
||
|
currentPage := func(){setChooseDesiresPage_HasMessagedMe(window, previousPage)}
|
||
|
|
||
|
title := getPageTitleCentered("My Mate Desires - General")
|
||
|
|
||
|
backButton := getBackButtonCentered(previousPage)
|
||
|
|
||
|
subtitle := getPageSubtitleCentered("Has Messaged Me")
|
||
|
|
||
|
description1 := getLabelCentered("Use this desire to show or hide users who have messaged you.")
|
||
|
description2 := getLabelCentered("Select the kind of users to include in your matches.")
|
||
|
|
||
|
//TODO: Change this to HasGreetedMe? Currently, a user who has rejected us will be included by this desire
|
||
|
|
||
|
option1Translated := translate("Has Messaged Me")
|
||
|
option2Translated := translate("Has Not Messaged Me")
|
||
|
|
||
|
optionTitlesList := []string{option1Translated, option2Translated}
|
||
|
|
||
|
optionNamesMap := map[string][]string{
|
||
|
option1Translated: []string{"Yes"},
|
||
|
option2Translated: []string{"No"},
|
||
|
}
|
||
|
|
||
|
desireEditor, err := getDesireEditor_Choice(window, currentPage, "HasMessagedMe", optionTitlesList, optionNamesMap, false, false, 1)
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, previousPage)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
viewStatisticsButton := getWidgetCentered(widget.NewButtonWithIcon("View Statistics", theme.InfoIcon(), func(){
|
||
|
setViewMyMateDesireStatisticsPage(window, "Has Messaged Me", "HasMessagedMe", true, "Donut", "HasMessagedMe", currentPage)
|
||
|
}))
|
||
|
|
||
|
page := container.NewVBox(title, backButton, widget.NewSeparator(), subtitle, widget.NewSeparator(), description1, description2, widget.NewSeparator(), desireEditor, widget.NewSeparator(), viewStatisticsButton)
|
||
|
|
||
|
setPageContent(page, window)
|
||
|
}
|
||
|
|
||
|
func setChooseDesiresPage_IHaveMessaged(window fyne.Window, previousPage func()){
|
||
|
|
||
|
currentPage := func(){setChooseDesiresPage_IHaveMessaged(window, previousPage)}
|
||
|
|
||
|
title := getPageTitleCentered("My Mate Desires - General")
|
||
|
|
||
|
backButton := getBackButtonCentered(previousPage)
|
||
|
|
||
|
subtitle := getPageSubtitleCentered("I Have Messaged")
|
||
|
|
||
|
description1 := getLabelCentered("Use this desire to show or hide users whom you have messaged.")
|
||
|
description2 := getLabelCentered("Select the kind of users to include in your matches.")
|
||
|
|
||
|
option1Translated := translate("I Have Messaged")
|
||
|
option2Translated := translate("I Have Not Messaged")
|
||
|
|
||
|
optionTitlesList := []string{option1Translated, option2Translated}
|
||
|
|
||
|
optionNamesMap := map[string][]string{
|
||
|
option1Translated: []string{"Yes"},
|
||
|
option2Translated: []string{"No"},
|
||
|
}
|
||
|
|
||
|
desireEditor, err := getDesireEditor_Choice(window, currentPage, "IHaveMessaged", optionTitlesList, optionNamesMap, false, false, 1)
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, previousPage)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
viewStatisticsButton := getWidgetCentered(widget.NewButtonWithIcon("View Statistics", theme.InfoIcon(), func(){
|
||
|
setViewMyMateDesireStatisticsPage(window, "I Have Messaged", "IHaveMessaged", true, "Donut", "IHaveMessaged", currentPage)
|
||
|
}))
|
||
|
|
||
|
page := container.NewVBox(title, backButton, widget.NewSeparator(), subtitle, widget.NewSeparator(), description1, description2, widget.NewSeparator(), desireEditor, widget.NewSeparator(), viewStatisticsButton)
|
||
|
|
||
|
setPageContent(page, window)
|
||
|
}
|
||
|
|
||
|
|
||
|
func setChooseDesiresPage_HasRejectedMe(window fyne.Window, previousPage func()){
|
||
|
|
||
|
currentPage := func(){setChooseDesiresPage_HasRejectedMe(window, previousPage)}
|
||
|
|
||
|
title := getPageTitleCentered(translate("My Mate Desires - General"))
|
||
|
|
||
|
backButton := getBackButtonCentered(previousPage)
|
||
|
|
||
|
subtitle := getPageSubtitleCentered("Has Rejected Me")
|
||
|
|
||
|
description1 := getLabelCentered("Use this desire to show or hide users who have rejected you.")
|
||
|
description2 := getLabelCentered("These are users who sent you a message that they are not interested.")
|
||
|
description3 := getLabelCentered("Select the kind of users to include in your matches.")
|
||
|
|
||
|
option1Translated := translate("Has Rejected Me")
|
||
|
option2Translated := translate("Has Not Rejected Me")
|
||
|
|
||
|
optionTitlesList := []string{option1Translated, option2Translated}
|
||
|
|
||
|
optionNamesMap := map[string][]string{
|
||
|
option1Translated: []string{"Yes"},
|
||
|
option2Translated: []string{"No"},
|
||
|
}
|
||
|
|
||
|
desireEditor, err := getDesireEditor_Choice(window, currentPage, "HasRejectedMe", optionTitlesList, optionNamesMap, false, false, 1)
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, previousPage)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
viewStatisticsButton := getWidgetCentered(widget.NewButtonWithIcon("View Statistics", theme.InfoIcon(), func(){
|
||
|
setViewMyMateDesireStatisticsPage(window, "Has Rejected Me", "HasRejectedMe", true, "Donut", "HasRejectedMe", currentPage)
|
||
|
}))
|
||
|
|
||
|
page := container.NewVBox(title, backButton, widget.NewSeparator(), subtitle, widget.NewSeparator(), description1, description2, description3, widget.NewSeparator(), desireEditor, widget.NewSeparator(), viewStatisticsButton)
|
||
|
|
||
|
setPageContent(page, window)
|
||
|
}
|
||
|
|
||
|
func setChooseDesiresPage_LikedUsers(window fyne.Window, previousPage func()){
|
||
|
|
||
|
currentPage := func(){setChooseDesiresPage_LikedUsers(window, previousPage)}
|
||
|
|
||
|
title := getPageTitleCentered(translate("My Mate Desires - General"))
|
||
|
|
||
|
backButton := getBackButtonCentered(previousPage)
|
||
|
|
||
|
subtitle := getPageSubtitleCentered("Liked Users")
|
||
|
|
||
|
description1 := getLabelCentered("Use this desire to show or hide liked users.")
|
||
|
description2 := getLabelCentered("A liked user is a user that you have added to your likes.")
|
||
|
description3 := getLabelCentered("Select the kind of users to include in your matches.")
|
||
|
|
||
|
option1Translated := translate("Liked")
|
||
|
option2Translated := translate("Not Liked")
|
||
|
|
||
|
optionTitlesList := []string{option1Translated, option2Translated}
|
||
|
|
||
|
optionNamesMap := map[string][]string{
|
||
|
option1Translated: []string{"Yes"},
|
||
|
option2Translated: []string{"No"},
|
||
|
}
|
||
|
|
||
|
desireEditor, err := getDesireEditor_Choice(window, currentPage, "IsLiked", optionTitlesList, optionNamesMap, false, false, 1)
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, previousPage)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
viewStatisticsButton := getWidgetCentered(widget.NewButtonWithIcon("View Statistics", theme.InfoIcon(), func(){
|
||
|
setViewMyMateDesireStatisticsPage(window, "Is Liked", "IsLiked", true, "Donut", "IsLiked", currentPage)
|
||
|
}))
|
||
|
|
||
|
page := container.NewVBox(title, backButton, widget.NewSeparator(), subtitle, widget.NewSeparator(), description1, description2, description3, widget.NewSeparator(), desireEditor, widget.NewSeparator(), viewStatisticsButton)
|
||
|
|
||
|
setPageContent(page, window)
|
||
|
}
|
||
|
|
||
|
func setChooseDesiresPage_IgnoredUsers(window fyne.Window, previousPage func()){
|
||
|
|
||
|
currentPage := func(){setChooseDesiresPage_IgnoredUsers(window, previousPage)}
|
||
|
|
||
|
title := getPageTitleCentered(translate("My Mate Desires - General"))
|
||
|
|
||
|
backButton := getBackButtonCentered(previousPage)
|
||
|
|
||
|
subtitle := getPageSubtitleCentered("Ignored Users")
|
||
|
|
||
|
description1 := getLabelCentered("Use this desire to show or hide ignored users.")
|
||
|
description2 := getLabelCentered("An Ignored user is a user that you have ignored.")
|
||
|
description3 := getLabelCentered("Select the kind of users to include in your matches.")
|
||
|
|
||
|
option1Translated := translate("Ignored")
|
||
|
option2Translated := translate("Not Ignored")
|
||
|
|
||
|
optionTitlesList := []string{option1Translated, option2Translated}
|
||
|
|
||
|
optionNamesMap := map[string][]string{
|
||
|
option1Translated: []string{"Yes"},
|
||
|
option2Translated: []string{"No"},
|
||
|
}
|
||
|
|
||
|
desireEditor, err := getDesireEditor_Choice(window, currentPage, "IsIgnored", optionTitlesList, optionNamesMap, false, false, 1)
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, previousPage)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
viewStatisticsButton := getWidgetCentered(widget.NewButtonWithIcon("View Statistics", theme.InfoIcon(), func(){
|
||
|
setViewMyMateDesireStatisticsPage(window, "Is Ignored", "IsIgnored", true, "Donut", "IsIgnored", currentPage)
|
||
|
}))
|
||
|
|
||
|
page := container.NewVBox(title, backButton, widget.NewSeparator(), subtitle, widget.NewSeparator(), description1, description2, description3, widget.NewSeparator(), desireEditor, widget.NewSeparator(), viewStatisticsButton)
|
||
|
|
||
|
setPageContent(page, window)
|
||
|
}
|
||
|
|
||
|
|
||
|
func setChooseDesiresPage_Contacts(window fyne.Window, previousPage func()){
|
||
|
|
||
|
currentPage := func(){setChooseDesiresPage_Contacts(window, previousPage)}
|
||
|
|
||
|
title := getPageTitleCentered(translate("My Mate Desires - General"))
|
||
|
|
||
|
backButton := getBackButtonCentered(previousPage)
|
||
|
|
||
|
subtitle := getPageSubtitleCentered("Contacts")
|
||
|
|
||
|
description1 := getLabelCentered("Use this desire to show or hide your contacts.")
|
||
|
description2 := getLabelCentered("These are users you have added to your contacts.")
|
||
|
description3 := getLabelCentered("Select the kind of users to include in your matches.")
|
||
|
|
||
|
option1Translated := translate("Is My Contact")
|
||
|
option2Translated := translate("Is Not My Contact")
|
||
|
|
||
|
optionTitlesList := []string{option1Translated, option2Translated}
|
||
|
|
||
|
optionNamesMap := map[string][]string{
|
||
|
option1Translated: []string{"Yes"},
|
||
|
option2Translated: []string{"No"},
|
||
|
}
|
||
|
|
||
|
desireEditor, err := getDesireEditor_Choice(window, currentPage, "IsMyContact", optionTitlesList, optionNamesMap, false, false, 1)
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, previousPage)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
viewStatisticsButton := getWidgetCentered(widget.NewButtonWithIcon("View Statistics", theme.InfoIcon(), func(){
|
||
|
setViewMyMateDesireStatisticsPage(window, "Is My Contact", "IsMyContact", true, "Donut", "IsMyContact", currentPage)
|
||
|
}))
|
||
|
|
||
|
page := container.NewVBox(title, backButton, widget.NewSeparator(), subtitle, widget.NewSeparator(), description1, description2, description3, widget.NewSeparator(), desireEditor, widget.NewSeparator(), viewStatisticsButton)
|
||
|
|
||
|
setPageContent(page, window)
|
||
|
}
|
||
|
|
||
|
|
||
|
// This function provides the editor to edit a choice desire
|
||
|
// A choice desire is one where there are a some canonical choices available, and the potential for an "Other" choice
|
||
|
// Inputs:
|
||
|
// -fyne.Window
|
||
|
// -func(): Current page
|
||
|
// -string: Desire name
|
||
|
// -[]string: Option titles list: What each check will show. Example: "1/5", "2/5", "3/5", "4/5", "5/5")
|
||
|
// -map[string][]string: Option Title -> Option Names list (Example ("1/5" -> "1", "2/5" -> "2"...)
|
||
|
// -bool: Show other choice: True if we want to show the "Other" option
|
||
|
// -bool: Show the "Require Response" button (false for attributes which do not allow that option)
|
||
|
// -int: Number of columns for the grid
|
||
|
// Outputs:
|
||
|
// -*fyne.Container
|
||
|
// -error
|
||
|
func getDesireEditor_Choice(window fyne.Window, currentPage func(), desireName string, optionTitlesList []string, optionsNamesMap map[string][]string, showOtherChoice bool, showRequireResponseButton bool, numberOfGridColumns int)(*fyne.Container, error){
|
||
|
|
||
|
getCurrentDesiredChoicesList := func()([]string, error){
|
||
|
|
||
|
currentChoicesListExists, currentChoicesList, err := myLocalDesires.GetDesire(desireName)
|
||
|
if (err != nil) { return nil, err }
|
||
|
if (currentChoicesListExists == false){
|
||
|
|
||
|
emptyList := make([]string, 0)
|
||
|
return emptyList, nil
|
||
|
}
|
||
|
//currentChoicesList is a "+" separated list of choices
|
||
|
// Each choice option is encoded in base64 (Except for "Other")
|
||
|
currentDesiredChoicesList := strings.Split(currentChoicesList, "+")
|
||
|
|
||
|
return currentDesiredChoicesList, nil
|
||
|
}
|
||
|
|
||
|
currentDesiredChoicesList, err := getCurrentDesiredChoicesList()
|
||
|
if (err != nil) { return nil, err }
|
||
|
|
||
|
selectButtonsGrid := container.NewGridWithColumns(numberOfGridColumns)
|
||
|
|
||
|
for _, optionTitle := range optionTitlesList{
|
||
|
|
||
|
optionNamesList, exists := optionsNamesMap[optionTitle]
|
||
|
if (exists == false){
|
||
|
return nil, errors.New("getDesireEditor_Choice called with optionsNamesMap missing optionTitle: " + optionTitle)
|
||
|
}
|
||
|
|
||
|
optionBase64NamesList := make([]string, 0, len(optionNamesList))
|
||
|
|
||
|
for _, optionName := range optionNamesList{
|
||
|
|
||
|
optionNameBase64 := encoding.EncodeBytesToBase64String([]byte(optionName))
|
||
|
|
||
|
optionBase64NamesList = append(optionBase64NamesList, optionNameBase64)
|
||
|
}
|
||
|
|
||
|
handleSelectFunction := func(selection bool){
|
||
|
|
||
|
//Outputs:
|
||
|
// -[]string: New desire attribute list (list of base64 option names)
|
||
|
getNewDesireAttributeList := func()[]string{
|
||
|
|
||
|
if (selection == false){
|
||
|
if (len(currentDesiredChoicesList) == 0){
|
||
|
// This should not happen, because the option was already selected
|
||
|
// The list should have had at least 1 item before
|
||
|
emptyList := make([]string, 0)
|
||
|
return emptyList
|
||
|
}
|
||
|
|
||
|
newAttributeList := make([]string, 0)
|
||
|
|
||
|
for _, optionNameBase64 := range currentDesiredChoicesList{
|
||
|
// We see if this option name belongs to the current optionTitle
|
||
|
// If it does, we remove it from our selected attributes list
|
||
|
shouldDelete := slices.Contains(optionBase64NamesList, optionNameBase64)
|
||
|
if (shouldDelete == false){
|
||
|
newAttributeList = append(newAttributeList, optionNameBase64)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return newAttributeList
|
||
|
}
|
||
|
//selection == true
|
||
|
|
||
|
newDesiredChoicesList := slices.Concat(currentDesiredChoicesList, optionBase64NamesList)
|
||
|
|
||
|
duplicatesRemovedList := helpers.RemoveDuplicatesFromStringList(newDesiredChoicesList)
|
||
|
|
||
|
return duplicatesRemovedList
|
||
|
}
|
||
|
|
||
|
newDesireAttributeList := getNewDesireAttributeList()
|
||
|
if (len(newDesireAttributeList) == 0){
|
||
|
|
||
|
err := myLocalDesires.DeleteDesire(desireName)
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, currentPage)
|
||
|
return
|
||
|
}
|
||
|
currentPage()
|
||
|
return
|
||
|
}
|
||
|
|
||
|
newDesireAttribute := strings.Join(newDesireAttributeList, "+")
|
||
|
|
||
|
err := myLocalDesires.SetDesire(desireName, newDesireAttribute)
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, currentPage)
|
||
|
return
|
||
|
}
|
||
|
currentPage()
|
||
|
}
|
||
|
|
||
|
optionSelectCheck := widget.NewCheck(optionTitle, handleSelectFunction)
|
||
|
|
||
|
getChoiceIsSelectedBool := func()bool{
|
||
|
|
||
|
// Every option name associated with this choice must be selected for this choice to be considered selected
|
||
|
|
||
|
for _, optionNameBase64 := range optionBase64NamesList{
|
||
|
listContainsItem := slices.Contains(currentDesiredChoicesList, optionNameBase64)
|
||
|
if (listContainsItem == false){
|
||
|
return false
|
||
|
}
|
||
|
}
|
||
|
return true
|
||
|
}
|
||
|
choiceIsSelected := getChoiceIsSelectedBool()
|
||
|
if (choiceIsSelected == true){
|
||
|
optionSelectCheck.Checked = true
|
||
|
}
|
||
|
|
||
|
selectButtonsGrid.Add(optionSelectCheck)
|
||
|
}
|
||
|
|
||
|
if (showOtherChoice == true){
|
||
|
|
||
|
handleOtherSelectFunction := func(selection bool){
|
||
|
|
||
|
//Outputs:
|
||
|
// -[]string: New desire attribute list (list of base64 option names)
|
||
|
getNewDesireAttributeList := func()[]string{
|
||
|
|
||
|
if (selection == false){
|
||
|
if (len(currentDesiredChoicesList) == 0){
|
||
|
// This should not happen, because "Other" had to have been selected for it to be deselected
|
||
|
emptyList := make([]string, 0)
|
||
|
return emptyList
|
||
|
}
|
||
|
|
||
|
newAttributeList, _ := helpers.DeleteAllMatchingItemsFromStringList(currentDesiredChoicesList, "Other")
|
||
|
|
||
|
return newAttributeList
|
||
|
}
|
||
|
//selection == true
|
||
|
|
||
|
newAttributeList := helpers.AddItemToStringListAndAvoidDuplicate(currentDesiredChoicesList, "Other")
|
||
|
|
||
|
return newAttributeList
|
||
|
}
|
||
|
|
||
|
newDesireAttributeList := getNewDesireAttributeList()
|
||
|
if (len(newDesireAttributeList) == 0){
|
||
|
|
||
|
err := myLocalDesires.DeleteDesire(desireName)
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, currentPage)
|
||
|
return
|
||
|
}
|
||
|
currentPage()
|
||
|
return
|
||
|
}
|
||
|
newDesireAttribute := strings.Join(newDesireAttributeList, "+")
|
||
|
|
||
|
err := myLocalDesires.SetDesire(desireName, newDesireAttribute)
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, currentPage)
|
||
|
return
|
||
|
}
|
||
|
currentPage()
|
||
|
}
|
||
|
|
||
|
otherSelectCheck := widget.NewCheck("Other", handleOtherSelectFunction)
|
||
|
|
||
|
otherIsSelected := slices.Contains(currentDesiredChoicesList, "Other")
|
||
|
if (otherIsSelected == true){
|
||
|
otherSelectCheck.Checked = true
|
||
|
}
|
||
|
|
||
|
selectButtonsGrid.Add(otherSelectCheck)
|
||
|
}
|
||
|
|
||
|
selectButtonsGridCentered := getContainerCentered(selectButtonsGrid)
|
||
|
|
||
|
filterOptionsSection, err := getDesireEditorFilterOptionsSection(window, currentPage, desireName, showRequireResponseButton)
|
||
|
if (err != nil){ return nil, err }
|
||
|
|
||
|
desireEditor := container.NewVBox(selectButtonsGridCentered, widget.NewSeparator(), filterOptionsSection)
|
||
|
|
||
|
return desireEditor, nil
|
||
|
}
|
||
|
|
||
|
// This function provides the editor to edit a numeric attribute
|
||
|
// The user can choose a minimum and maximum allowed value
|
||
|
// Units are shown for each minimum/maximum value, and a secondary row of alternate units can optionally be shown
|
||
|
func getDesireEditor_Numeric(
|
||
|
window fyne.Window,
|
||
|
currentPage func(),
|
||
|
desireName string,
|
||
|
minimumAllowed int64,
|
||
|
maximumAllowed int64,
|
||
|
currentUnits string,
|
||
|
unitsRoundingPrecision int,
|
||
|
unitsAreCustom bool, // This will be true if we need to convert the shown units
|
||
|
convertToStandardFunction func(float64)(float64, error),
|
||
|
convertToCustomFunction func(float64)(float64, error),
|
||
|
showSecondaryForm bool, // Secondary form is an alternate representation of the bound. Example: Offspring variants
|
||
|
secondaryFormTitle string,
|
||
|
secondaryFormPrefix string, // A prefix to add to the secondary form representation. Example: "~" for offspring variants
|
||
|
getSecondaryFormFunction func(float64)(float64, error))(*fyne.Container, error){
|
||
|
|
||
|
getBoundColumn := func(minimumOrMaximum string)(*fyne.Container, error){
|
||
|
|
||
|
if (minimumOrMaximum != "Minimum" && minimumOrMaximum != "Maximum"){
|
||
|
return nil, errors.New("getBoundColumn called with invalid minimumOrMaximum: " + minimumOrMaximum)
|
||
|
}
|
||
|
|
||
|
desireBoundName := desireName + "_" + minimumOrMaximum
|
||
|
|
||
|
boundLabel := getBoldLabelCentered(minimumOrMaximum)
|
||
|
|
||
|
myBoundExists, myCurrentBound, err := myLocalDesires.GetDesire(desireBoundName)
|
||
|
if (err != nil) { return nil, err }
|
||
|
|
||
|
getMyBoundSection := func()(*fyne.Container, error){
|
||
|
|
||
|
if (myBoundExists == false){
|
||
|
noneLabel := getBoldItalicLabelCentered(translate("None"))
|
||
|
|
||
|
if (showSecondaryForm == false){
|
||
|
return noneLabel, nil
|
||
|
}
|
||
|
|
||
|
noneLabel2 := getBoldItalicLabelCentered(translate("None"))
|
||
|
|
||
|
secondaryFormTitle := getItalicLabelCentered(secondaryFormTitle + ":")
|
||
|
|
||
|
myBoundSection := container.NewVBox(noneLabel, widget.NewSeparator(), secondaryFormTitle, noneLabel2)
|
||
|
|
||
|
return myBoundSection, nil
|
||
|
}
|
||
|
|
||
|
// This will convert the bound if unitsAreCustom is true
|
||
|
getMyCurrentBound := func()(float64, error){
|
||
|
|
||
|
myBoundFloat64, err := helpers.ConvertStringToFloat64(myCurrentBound)
|
||
|
if (err != nil){
|
||
|
return 0, errors.New("My " + desireName + " desire malformed: not float64: " + myCurrentBound)
|
||
|
}
|
||
|
|
||
|
if (unitsAreCustom == false){
|
||
|
return myBoundFloat64, nil
|
||
|
}
|
||
|
|
||
|
myBoundCustom, err := convertToCustomFunction(myBoundFloat64)
|
||
|
if (err != nil){
|
||
|
return 0, errors.New("My " + desireName + " desire malformed: is negative: " + myCurrentBound)
|
||
|
}
|
||
|
|
||
|
return myBoundCustom, nil
|
||
|
}
|
||
|
|
||
|
myCurrentBound, err := getMyCurrentBound()
|
||
|
if (err != nil){ return nil, err }
|
||
|
|
||
|
myCurrentBoundString := helpers.ConvertFloat64ToStringRounded(myCurrentBound, unitsRoundingPrecision)
|
||
|
|
||
|
myBoundLabelText := myCurrentBoundString + " " + translate(currentUnits)
|
||
|
myBoundLabel := getBoldLabelCentered(myBoundLabelText)
|
||
|
|
||
|
if (showSecondaryForm == false){
|
||
|
|
||
|
return myBoundLabel, nil
|
||
|
}
|
||
|
|
||
|
secondaryFormBound, err := getSecondaryFormFunction(myCurrentBound)
|
||
|
if (err != nil){ return nil, err }
|
||
|
|
||
|
secondaryFormBoundString := helpers.ConvertFloat64ToStringRounded(secondaryFormBound, unitsRoundingPrecision)
|
||
|
|
||
|
secondaryFormTitle := getItalicLabelCentered(secondaryFormTitle + ":")
|
||
|
|
||
|
mySecondaryFormBoundLabelText := secondaryFormPrefix + secondaryFormBoundString + " " + translate(currentUnits)
|
||
|
mySecondaryFormBoundLabel := getBoldItalicLabelCentered(mySecondaryFormBoundLabelText)
|
||
|
|
||
|
myBoundSection := container.NewVBox(myBoundLabel, widget.NewSeparator(), secondaryFormTitle, mySecondaryFormBoundLabel)
|
||
|
|
||
|
return myBoundSection, nil
|
||
|
}
|
||
|
|
||
|
myBoundSection, err := getMyBoundSection()
|
||
|
if (err != nil) { return nil, err }
|
||
|
|
||
|
minimumOrMaximumLowercase := strings.ToLower(minimumOrMaximum)
|
||
|
|
||
|
boundEntry := widget.NewEntry()
|
||
|
|
||
|
if (myBoundExists == true){
|
||
|
|
||
|
getMyCurrentBoundString := func()(string, error){
|
||
|
|
||
|
myCurrentBoundFloat64, err := helpers.ConvertStringToFloat64(myCurrentBound)
|
||
|
if (err != nil) {
|
||
|
return "", errors.New("My desires malformed: Contains invalid numeric desire: " + desireName)
|
||
|
}
|
||
|
if (myCurrentBoundFloat64 < float64(minimumAllowed) || myCurrentBoundFloat64 > float64(maximumAllowed)) {
|
||
|
return "", errors.New("My desires malformed: Contains invalid numeric desire: " + desireName)
|
||
|
}
|
||
|
|
||
|
if (unitsAreCustom == false){
|
||
|
myCurrentBoundRounded := helpers.ConvertFloat64ToStringRounded(myCurrentBoundFloat64, unitsRoundingPrecision)
|
||
|
return myCurrentBoundRounded, nil
|
||
|
}
|
||
|
|
||
|
myCurrentBoundCustom, err := convertToCustomFunction(myCurrentBoundFloat64)
|
||
|
if (err != nil){
|
||
|
return "", errors.New("My desires malformed: Contains invalid numeric desire: " + desireName)
|
||
|
}
|
||
|
|
||
|
myCurrentBoundCustomString := helpers.ConvertFloat64ToStringRounded(myCurrentBoundCustom, unitsRoundingPrecision)
|
||
|
|
||
|
return myCurrentBoundCustomString, nil
|
||
|
}
|
||
|
|
||
|
myCurrentBoundString, err := getMyCurrentBoundString()
|
||
|
if (err != nil) { return nil, err }
|
||
|
|
||
|
boundEntry.SetText(myCurrentBoundString)
|
||
|
|
||
|
} else {
|
||
|
boundEntry.SetPlaceHolder(translate("Enter " + minimumOrMaximumLowercase + "..."))
|
||
|
}
|
||
|
|
||
|
saveBoundButton := widget.NewButtonWithIcon(translate("Save"), theme.ConfirmIcon(), func(){
|
||
|
|
||
|
newBound := boundEntry.Text
|
||
|
|
||
|
if (newBound == ""){
|
||
|
|
||
|
err := myLocalDesires.DeleteDesire(desireBoundName)
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, currentPage)
|
||
|
return
|
||
|
}
|
||
|
currentPage()
|
||
|
return
|
||
|
}
|
||
|
|
||
|
//TODO: If min is greater than max, or max is greater than min, show dialog and don't allow change
|
||
|
|
||
|
newBoundFloat64, err := helpers.ConvertStringToFloat64(newBound)
|
||
|
if (err != nil){
|
||
|
|
||
|
title := translate("Invalid Bound")
|
||
|
dialogMessage := getLabelCentered(translate("Your bound must be a number."))
|
||
|
dialogContent := container.NewVBox(dialogMessage)
|
||
|
dialog.ShowCustom(title, translate("Close"), dialogContent, window)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
getNewDesireBoundConverted := func()(float64, error){
|
||
|
|
||
|
if (unitsAreCustom == false){
|
||
|
return newBoundFloat64, nil
|
||
|
}
|
||
|
|
||
|
boundInStandardUnits, err := convertToStandardFunction(newBoundFloat64)
|
||
|
if (err != nil){
|
||
|
return 0, errors.New("Invalid new numeric bound: " + err.Error())
|
||
|
}
|
||
|
|
||
|
return boundInStandardUnits, nil
|
||
|
}
|
||
|
|
||
|
newDesireBoundConverted, err := getNewDesireBoundConverted()
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, currentPage)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
if (newDesireBoundConverted < float64(minimumAllowed) || newDesireBoundConverted > float64(maximumAllowed)){
|
||
|
|
||
|
minimumAllowedString := helpers.ConvertInt64ToString(minimumAllowed)
|
||
|
maximumAllowedString := helpers.ConvertInt64ToString(maximumAllowed)
|
||
|
|
||
|
dialogTitle := translate("Invalid Desire")
|
||
|
dialogMessage := getLabelCentered(translate("Your " + minimumOrMaximumLowercase + " must be a number between " + minimumAllowedString + " and " + maximumAllowedString + "."))
|
||
|
dialogContent := container.NewVBox(dialogMessage)
|
||
|
dialog.ShowCustom(dialogTitle, translate("Close"), dialogContent, window)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
newDesireBoundString := helpers.ConvertFloat64ToStringRounded(newDesireBoundConverted, unitsRoundingPrecision)
|
||
|
|
||
|
err = myLocalDesires.SetDesire(desireBoundName, newDesireBoundString)
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, currentPage)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
currentPage()
|
||
|
})
|
||
|
|
||
|
saveBoundButtonWithEntry := container.NewGridWithRows(1, boundEntry, saveBoundButton)
|
||
|
|
||
|
deleteBoundButton := widget.NewButtonWithIcon(translate("No Preference"), theme.CancelIcon(), func(){
|
||
|
|
||
|
if (myBoundExists == false){
|
||
|
return
|
||
|
}
|
||
|
|
||
|
err := myLocalDesires.DeleteDesire(desireBoundName)
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, currentPage)
|
||
|
return
|
||
|
}
|
||
|
currentPage()
|
||
|
})
|
||
|
|
||
|
boundColumn := getContainerCentered(container.NewVBox(boundLabel, widget.NewSeparator(), myBoundSection, widget.NewSeparator(), saveBoundButtonWithEntry, deleteBoundButton))
|
||
|
return boundColumn, nil
|
||
|
}
|
||
|
|
||
|
minimumColumn, err := getBoundColumn("Minimum")
|
||
|
if (err != nil){ return nil, err }
|
||
|
|
||
|
maximumColumn, err := getBoundColumn("Maximum")
|
||
|
if (err != nil){ return nil, err }
|
||
|
|
||
|
boundColumns := getContainerCentered(container.NewGridWithRows(1, minimumColumn, maximumColumn))
|
||
|
|
||
|
filterOptionsSection, err := getDesireEditorFilterOptionsSection(window, currentPage, desireName, true)
|
||
|
if (err != nil){ return nil, err }
|
||
|
|
||
|
editorContent := container.NewVBox(boundColumns, widget.NewSeparator(), filterOptionsSection)
|
||
|
|
||
|
return editorContent, nil
|
||
|
}
|
||
|
|
||
|
func getDesireEditorFilterOptionsSection(window fyne.Window, currentPage func(), desireName string, showRequireResponseButton bool)(*fyne.Container, error){
|
||
|
|
||
|
configureFiltersDescription := widget.NewLabel("Configure your desire filter options.")
|
||
|
|
||
|
desireFilterOptionsHelpButton := widget.NewButtonWithIcon("", theme.QuestionIcon(), func(){
|
||
|
setDesireFilterOptionsExplainerPage(window, currentPage)
|
||
|
})
|
||
|
|
||
|
desireFilterOptionsDescriptionRow := container.NewHBox(layout.NewSpacer(), configureFiltersDescription, desireFilterOptionsHelpButton, layout.NewSpacer())
|
||
|
|
||
|
getFilterAllButton := func()(fyne.Widget, error){
|
||
|
|
||
|
filterAllExists, currentFilterAllResponse, err := myLocalDesires.GetDesire(desireName + "_FilterAll")
|
||
|
if (err != nil) { return nil, err }
|
||
|
|
||
|
if (filterAllExists == true && currentFilterAllResponse == "Yes"){
|
||
|
button := widget.NewButtonWithIcon(translate("Filter All"), theme.CheckButtonCheckedIcon(), func(){
|
||
|
_ = myLocalDesires.SetDesire(desireName + "_FilterAll", "No")
|
||
|
currentPage()
|
||
|
})
|
||
|
return button, nil
|
||
|
}
|
||
|
button := widget.NewButtonWithIcon(translate("Filter All"), theme.CheckButtonIcon(), func(){
|
||
|
_ = myLocalDesires.SetDesire(desireName + "_FilterAll", "Yes")
|
||
|
currentPage()
|
||
|
})
|
||
|
return button, nil
|
||
|
}
|
||
|
|
||
|
filterAllButton, err := getFilterAllButton()
|
||
|
if (err != nil) { return nil, err }
|
||
|
|
||
|
if (showRequireResponseButton == false){
|
||
|
|
||
|
filterAllButtonCentered := getWidgetCentered(filterAllButton)
|
||
|
|
||
|
filterOptionsSection := container.NewVBox(desireFilterOptionsDescriptionRow, filterAllButtonCentered)
|
||
|
|
||
|
return filterOptionsSection, nil
|
||
|
}
|
||
|
|
||
|
getRequireResponseButton := func()(fyne.Widget, error){
|
||
|
|
||
|
requireResponseExists, currentRequireResponse, err := myLocalDesires.GetDesire(desireName + "_RequireResponse")
|
||
|
if (err != nil) { return nil, err }
|
||
|
|
||
|
if (requireResponseExists == true && currentRequireResponse == "Yes"){
|
||
|
button := widget.NewButtonWithIcon(translate("Require Response"), theme.CheckButtonCheckedIcon(), func(){
|
||
|
_ = myLocalDesires.SetDesire(desireName + "_RequireResponse", "No")
|
||
|
currentPage()
|
||
|
})
|
||
|
return button, nil
|
||
|
}
|
||
|
button := widget.NewButtonWithIcon(translate("Require Response"), theme.CheckButtonIcon(), func(){
|
||
|
_ = myLocalDesires.SetDesire(desireName + "_RequireResponse", "Yes")
|
||
|
currentPage()
|
||
|
})
|
||
|
return button, nil
|
||
|
}
|
||
|
|
||
|
requireResponseButton, err := getRequireResponseButton()
|
||
|
if (err != nil) { return nil, err }
|
||
|
|
||
|
filterSettingsButtonsGrid := getContainerCentered(container.NewGridWithColumns(1, filterAllButton, requireResponseButton))
|
||
|
|
||
|
filterOptionsSection := container.NewVBox(desireFilterOptionsDescriptionRow, filterSettingsButtonsGrid)
|
||
|
|
||
|
return filterOptionsSection, nil
|
||
|
}
|
||
|
|
||
|
|
||
|
// This is a page to view all of a user's desires
|
||
|
func setViewAllMyDesiresPage(window fyne.Window, previousPage func()){
|
||
|
|
||
|
setLoadingScreen(window, "My Mate Desires", "Loading My Mate Desires...")
|
||
|
|
||
|
appMemory.SetMemoryEntry("CurrentViewedPage", "ViewAllMyDesires")
|
||
|
|
||
|
currentPage := func(){setViewAllMyDesiresPage(window, previousPage)}
|
||
|
|
||
|
title := getPageTitleCentered("My Mate Desires")
|
||
|
|
||
|
backButton := getBackButtonCentered(previousPage)
|
||
|
|
||
|
description := getLabelCentered("Below are all of your mate desires.")
|
||
|
|
||
|
getAllDesiresGrid := func()(*fyne.Container, error){
|
||
|
|
||
|
desireButtonsColumn := container.NewVBox(widget.NewSeparator())
|
||
|
desireNameAndDataColumn := container.NewVBox(widget.NewSeparator())
|
||
|
filterOptionChecksColumn := container.NewVBox(widget.NewSeparator())
|
||
|
|
||
|
getFilterOptionCheck := func(desireName string, optionType string)(fyne.Widget, error){
|
||
|
|
||
|
if (optionType != "FilterAll" && optionType != "RequireResponse"){
|
||
|
return nil, errors.New("getFilterOptionCheck called with invalid optionType: " + optionType)
|
||
|
}
|
||
|
|
||
|
filterOptionDesireName := desireName + "_" + optionType
|
||
|
|
||
|
getOptionTitle := func()string{
|
||
|
|
||
|
if (optionType == "FilterAll"){
|
||
|
result := translate("Filter All")
|
||
|
return result
|
||
|
}
|
||
|
|
||
|
result := translate("Require Response")
|
||
|
return result
|
||
|
}
|
||
|
|
||
|
optionTitle := getOptionTitle()
|
||
|
|
||
|
filterOptionCheck := widget.NewCheck(optionTitle, func(newSelection bool){
|
||
|
|
||
|
newSelectionString := helpers.ConvertBoolToYesOrNoString(newSelection)
|
||
|
_ = myLocalDesires.SetDesire(filterOptionDesireName, newSelectionString)
|
||
|
})
|
||
|
|
||
|
exists, currentValue, err := myLocalDesires.GetDesire(filterOptionDesireName)
|
||
|
if (err != nil) { return nil, err }
|
||
|
if (exists == true && currentValue == "Yes"){
|
||
|
filterOptionCheck.Checked = true
|
||
|
}
|
||
|
|
||
|
return filterOptionCheck, nil
|
||
|
}
|
||
|
|
||
|
addDesireRow_Numerical := func(desireTitle string, desireName string, editPage func(), barOrDonutChart string, attributeName string)error{
|
||
|
|
||
|
editDesireButton := widget.NewButtonWithIcon("Edit", theme.DocumentCreateIcon(), editPage)
|
||
|
|
||
|
desireTitleLabel := getBoldLabelCentered(desireTitle)
|
||
|
|
||
|
getDesireValueLabel := func() (*fyne.Container, error){
|
||
|
|
||
|
minimumExists, desireMinimum, err := myLocalDesires.GetDesire(desireName + "_Minimum")
|
||
|
if (err != nil) { return nil, err }
|
||
|
|
||
|
maximumExists, desireMaximum, err := myLocalDesires.GetDesire(desireName + "_Maximum")
|
||
|
if (err != nil) { return nil, err }
|
||
|
|
||
|
if (minimumExists == false && maximumExists == false){
|
||
|
noPreferenceLabel := getItalicLabelCentered("No Preference")
|
||
|
return noPreferenceLabel, nil
|
||
|
}
|
||
|
|
||
|
// We may have to format the desire value
|
||
|
// For example: converting distance units from kilometers to miles
|
||
|
|
||
|
_, attributeIsNumerical, formatDesireValuesFunction, desireValueUnits, _, err := attributeDisplay.GetProfileAttributeDisplayInfo(attributeName)
|
||
|
if (err != nil) { return nil, err }
|
||
|
if (attributeIsNumerical == false){
|
||
|
return nil, errors.New("addDesireRow_Numerical called with non-numerical attribute: " + attributeName)
|
||
|
}
|
||
|
|
||
|
getDesireRangeFormatted := func()(string, error){
|
||
|
|
||
|
if (minimumExists == true && maximumExists == false){
|
||
|
|
||
|
desireMinimumFormatted, err := formatDesireValuesFunction(desireMinimum)
|
||
|
if (err != nil) { return "", err }
|
||
|
|
||
|
result := desireMinimumFormatted + "+"
|
||
|
|
||
|
return result, nil
|
||
|
}
|
||
|
if (minimumExists == false && maximumExists == true){
|
||
|
|
||
|
desireMaximumFormatted, err := formatDesireValuesFunction(desireMaximum)
|
||
|
if (err != nil) { return "", err }
|
||
|
|
||
|
result := "<" + desireMaximumFormatted
|
||
|
|
||
|
return result, nil
|
||
|
}
|
||
|
|
||
|
desireMinimumFormatted, err := formatDesireValuesFunction(desireMinimum)
|
||
|
if (err != nil) { return "", err }
|
||
|
|
||
|
desireMaximumFormatted, err := formatDesireValuesFunction(desireMaximum)
|
||
|
if (err != nil) { return "", err }
|
||
|
|
||
|
result := desireMinimumFormatted + " - " + desireMaximumFormatted
|
||
|
|
||
|
return result, nil
|
||
|
}
|
||
|
|
||
|
desireRangeFormatted, err := getDesireRangeFormatted()
|
||
|
if (err != nil) { return nil, err }
|
||
|
|
||
|
labelText := desireRangeFormatted + desireValueUnits
|
||
|
|
||
|
minMaxLabel := getBoldItalicLabelCentered(labelText)
|
||
|
|
||
|
return minMaxLabel, nil
|
||
|
}
|
||
|
|
||
|
desireValueLabel, err := getDesireValueLabel()
|
||
|
if (err != nil) { return err }
|
||
|
|
||
|
filterAllCheck, err := getFilterOptionCheck(desireName, "FilterAll")
|
||
|
if (err != nil) { return err }
|
||
|
|
||
|
requireResponseCheck, err := getFilterOptionCheck(desireName, "RequireResponse")
|
||
|
if (err != nil) { return err }
|
||
|
|
||
|
viewStatisticsButton := widget.NewButtonWithIcon("Stats", theme.InfoIcon(), func(){
|
||
|
|
||
|
setViewMyMateDesireStatisticsPage(window, desireTitle, desireName, true, barOrDonutChart, attributeName, currentPage)
|
||
|
})
|
||
|
|
||
|
desireButtonsColumn.Add(editDesireButton)
|
||
|
desireButtonsColumn.Add(viewStatisticsButton)
|
||
|
|
||
|
desireNameAndDataColumn.Add(desireTitleLabel)
|
||
|
desireNameAndDataColumn.Add(desireValueLabel)
|
||
|
|
||
|
filterOptionChecksColumn.Add(filterAllCheck)
|
||
|
filterOptionChecksColumn.Add(requireResponseCheck)
|
||
|
|
||
|
desireButtonsColumn.Add(widget.NewSeparator())
|
||
|
desireNameAndDataColumn.Add(widget.NewSeparator())
|
||
|
filterOptionChecksColumn.Add(widget.NewSeparator())
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
addDesireRow_Choice := func(desireTitle string, desireName string, editPage func(), barOrDonutChart string, attributeName string)error{
|
||
|
|
||
|
editDesireButton := widget.NewButtonWithIcon("Edit", theme.DocumentCreateIcon(), editPage)
|
||
|
|
||
|
desireTitleLabel := getBoldLabelCentered(desireTitle)
|
||
|
|
||
|
getChoiceValueLabel := func()(*fyne.Container, error){
|
||
|
|
||
|
desireExists, desireChoicesList, err := myLocalDesires.GetDesire(desireName)
|
||
|
if (err != nil) { return nil, err }
|
||
|
|
||
|
if (desireExists == false){
|
||
|
noPreferenceLabel := getItalicLabelCentered(translate("No Preference"))
|
||
|
return noPreferenceLabel, nil
|
||
|
}
|
||
|
|
||
|
|
||
|
// We may have to format the desired choices for readability
|
||
|
// For example: Converting "1" -> "1/6"
|
||
|
|
||
|
_, _, formatDesireValuesFunction, desireValueUnits, _, err := attributeDisplay.GetProfileAttributeDisplayInfo(attributeName)
|
||
|
if (err != nil) { return nil, err }
|
||
|
|
||
|
getLabelText := func()(string, error){
|
||
|
|
||
|
base64ChoicesList := strings.Split(desireChoicesList, "+")
|
||
|
|
||
|
choicesList := make([]string, 0, len(base64ChoicesList))
|
||
|
|
||
|
for _, base64Choice := range base64ChoicesList{
|
||
|
|
||
|
choiceString, err := encoding.DecodeBase64StringToUnicodeString(base64Choice)
|
||
|
if (err != nil) {
|
||
|
return "", errors.New("My Desire choices list is malformed: Contains non-base64 choice: " + base64Choice)
|
||
|
}
|
||
|
|
||
|
choiceFormatted, err := formatDesireValuesFunction(choiceString)
|
||
|
if (err != nil) { return "", err }
|
||
|
|
||
|
choiceFormattedWithUnits := choiceFormatted + desireValueUnits
|
||
|
|
||
|
choicesList = append(choicesList, choiceFormattedWithUnits)
|
||
|
}
|
||
|
|
||
|
choicesListJoined := strings.Join(choicesList, ", ")
|
||
|
choicesListTrimmed, _, err := helpers.TrimAndFlattenString(choicesListJoined, 35)
|
||
|
if (err != nil) { return "", err }
|
||
|
|
||
|
return choicesListTrimmed, nil
|
||
|
}
|
||
|
|
||
|
labelText, err := getLabelText()
|
||
|
if (err != nil) { return nil, err }
|
||
|
|
||
|
desireValueLabel := getBoldItalicLabelCentered(labelText)
|
||
|
|
||
|
return desireValueLabel, nil
|
||
|
}
|
||
|
|
||
|
choiceValueLabel, err := getChoiceValueLabel()
|
||
|
if (err != nil) { return err }
|
||
|
|
||
|
filterAllCheck, err := getFilterOptionCheck(desireName, "FilterAll")
|
||
|
if (err != nil) { return err }
|
||
|
|
||
|
requireResponseCheck, err := getFilterOptionCheck(desireName, "RequireResponse")
|
||
|
if (err != nil) { return err }
|
||
|
|
||
|
viewStatisticsButton := widget.NewButtonWithIcon("Stats", theme.InfoIcon(), func(){
|
||
|
|
||
|
setViewMyMateDesireStatisticsPage(window, desireTitle, desireName, true, barOrDonutChart, attributeName, currentPage)
|
||
|
})
|
||
|
|
||
|
desireButtonsColumn.Add(editDesireButton)
|
||
|
desireButtonsColumn.Add(viewStatisticsButton)
|
||
|
|
||
|
desireNameAndDataColumn.Add(desireTitleLabel)
|
||
|
desireNameAndDataColumn.Add(choiceValueLabel)
|
||
|
|
||
|
filterOptionChecksColumn.Add(filterAllCheck)
|
||
|
filterOptionChecksColumn.Add(requireResponseCheck)
|
||
|
|
||
|
desireButtonsColumn.Add(widget.NewSeparator())
|
||
|
desireNameAndDataColumn.Add(widget.NewSeparator())
|
||
|
filterOptionChecksColumn.Add(widget.NewSeparator())
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// This function is used for desires which are not choice/numerical, so their value cannot be displayed automatically
|
||
|
//TODO: Add a function to format the desire value to something readable
|
||
|
addDesireRow_Custom := func(desireTitle string, desireName string, editPage func())error{
|
||
|
|
||
|
editDesireButton := widget.NewButtonWithIcon("Edit", theme.DocumentCreateIcon(), editPage)
|
||
|
|
||
|
desireTitleLabel := getBoldLabelCentered(desireTitle)
|
||
|
|
||
|
getDesireValueLabel := func() (*fyne.Container, error){
|
||
|
|
||
|
desireExists, _, err := myLocalDesires.GetDesire(desireName)
|
||
|
if (err != nil) { return nil, err }
|
||
|
if (desireExists == false){
|
||
|
noPreferenceLabel := getItalicLabelCentered("No Preference")
|
||
|
return noPreferenceLabel, nil
|
||
|
}
|
||
|
|
||
|
customLabel := getBoldItalicLabelCentered("Custom")
|
||
|
|
||
|
return customLabel, nil
|
||
|
}
|
||
|
|
||
|
desireValueLabel, err := getDesireValueLabel()
|
||
|
if (err != nil) { return err }
|
||
|
|
||
|
filterAllCheck, err := getFilterOptionCheck(desireName, "FilterAll")
|
||
|
if (err != nil) { return err }
|
||
|
|
||
|
requireResponseCheck, err := getFilterOptionCheck(desireName, "RequireResponse")
|
||
|
if (err != nil) { return err }
|
||
|
|
||
|
desireButtonsColumn.Add(editDesireButton)
|
||
|
desireButtonsColumn.Add(widget.NewLabel(""))
|
||
|
|
||
|
desireNameAndDataColumn.Add(desireTitleLabel)
|
||
|
desireNameAndDataColumn.Add(desireValueLabel)
|
||
|
|
||
|
filterOptionChecksColumn.Add(filterAllCheck)
|
||
|
filterOptionChecksColumn.Add(requireResponseCheck)
|
||
|
|
||
|
desireButtonsColumn.Add(widget.NewSeparator())
|
||
|
desireNameAndDataColumn.Add(widget.NewSeparator())
|
||
|
filterOptionChecksColumn.Add(widget.NewSeparator())
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
editAgeDesirePage := func(){setChooseDesiresPage_Age(window, currentPage)}
|
||
|
err := addDesireRow_Numerical("Age", "Age", editAgeDesirePage, "Bar", "Age")
|
||
|
if (err != nil){ return nil, err }
|
||
|
|
||
|
editHeightDesirePage := func(){setChooseDesiresPage_Height(window, currentPage)}
|
||
|
err = addDesireRow_Numerical("Height", "Height", editHeightDesirePage, "Bar", "Height")
|
||
|
if (err != nil){ return nil, err }
|
||
|
|
||
|
editWealthDesirePage := func(){setChooseDesiresPage_Wealth(window, currentPage)}
|
||
|
err = addDesireRow_Numerical("Wealth", "Wealth", editWealthDesirePage, "Bar", "WealthInGold")
|
||
|
if (err != nil){ return nil, err }
|
||
|
|
||
|
editSexDesirePage := func(){setChooseDesiresPage_Sex(window, currentPage)}
|
||
|
err = addDesireRow_Choice("Sex", "Sex", editSexDesirePage, "Donut", "Sex")
|
||
|
if (err != nil){ return nil, err }
|
||
|
|
||
|
editProfileLanguageDesirePage := func(){setChooseDesiresPage_ProfileLanguage(window, currentPage)}
|
||
|
err = addDesireRow_Choice("Profile Language", "ProfileLanguage", editProfileLanguageDesirePage, "Bar", "ProfileLanguage")
|
||
|
if (err != nil){ return nil, err }
|
||
|
|
||
|
editCountryDesirePage := func(){setChooseDesiresPage_Country(window, currentPage)}
|
||
|
err = addDesireRow_Choice("Country", "PrimaryLocationCountry", editCountryDesirePage, "Donut", "PrimaryLocationCountry")
|
||
|
if (err != nil){ return nil, err }
|
||
|
|
||
|
editSearchTermsDesirePage := func(){setChooseDesiresPage_SearchTerms(window, currentPage)}
|
||
|
err = addDesireRow_Choice("Search Terms", "SearchTerms", editSearchTermsDesirePage, "Donut", "SearchTermsCount")
|
||
|
if (err != nil){ return nil, err }
|
||
|
|
||
|
editHasMessagedMeDesirePage := func(){setChooseDesiresPage_HasMessagedMe(window, currentPage)}
|
||
|
err = addDesireRow_Choice("Has Messaged Me", "HasMessagedMe", editHasMessagedMeDesirePage, "Donut", "HasMessagedMe")
|
||
|
if (err != nil){ return nil, err }
|
||
|
|
||
|
editIHaveMessagedDesirePage := func(){setChooseDesiresPage_IHaveMessaged(window, currentPage)}
|
||
|
err = addDesireRow_Choice("I Have Messaged", "IHaveMessaged", editIHaveMessagedDesirePage, "Donut", "IHaveMessaged")
|
||
|
if (err != nil){ return nil, err }
|
||
|
|
||
|
editHasRejectedMeDesirePage := func(){setChooseDesiresPage_HasRejectedMe(window, currentPage)}
|
||
|
err = addDesireRow_Choice("Has Rejected Me", "HasRejectedMe", editHasRejectedMeDesirePage, "Donut", "HasRejectedMe")
|
||
|
if (err != nil){ return nil, err }
|
||
|
|
||
|
editIsLikedDesirePage := func(){setChooseDesiresPage_LikedUsers(window, currentPage)}
|
||
|
err = addDesireRow_Choice("Is Liked", "IsLiked", editIsLikedDesirePage, "Donut", "IsLiked")
|
||
|
if (err != nil){ return nil, err }
|
||
|
|
||
|
editIsIgnoredDesirePage := func(){setChooseDesiresPage_IgnoredUsers(window, currentPage)}
|
||
|
err = addDesireRow_Choice("Is Ignored", "IsIgnored", editIsIgnoredDesirePage, "Donut", "IsIgnored")
|
||
|
if (err != nil){ return nil, err }
|
||
|
|
||
|
editIsMyContactDesirePage := func(){setChooseDesiresPage_Contacts(window, currentPage)}
|
||
|
err = addDesireRow_Choice("Is My Contact", "IsMyContact", editIsMyContactDesirePage, "Donut", "IsMyContact")
|
||
|
if (err != nil){ return nil, err }
|
||
|
|
||
|
editDistanceDesirePage := func(){setChooseDesiresPage_Distance(window, currentPage)}
|
||
|
err = addDesireRow_Numerical("Distance", "Distance", editDistanceDesirePage, "Bar", "Distance")
|
||
|
if (err != nil){ return nil, err }
|
||
|
|
||
|
editSexualityDesirePage := func(){setChooseDesiresPage_Sexuality(window, currentPage)}
|
||
|
err = addDesireRow_Choice("Sexuality", "Sexuality", editSexualityDesirePage, "Donut", "Sexuality")
|
||
|
if (err != nil){ return nil, err }
|
||
|
|
||
|
editBodyFatDesirePage := func(){setChooseDesiresPage_BodyFat(window, currentPage)}
|
||
|
err = addDesireRow_Choice("Body Fat", "BodyFat", editBodyFatDesirePage, "Donut", "BodyFat")
|
||
|
if (err != nil){ return nil, err }
|
||
|
|
||
|
editBodyMuscleDesirePage := func(){setChooseDesiresPage_BodyMuscle(window, currentPage)}
|
||
|
err = addDesireRow_Choice("Body Muscle", "BodyMuscle", editBodyMuscleDesirePage, "Donut", "BodyMuscle")
|
||
|
if (err != nil){ return nil, err }
|
||
|
|
||
|
editEyeColorDesirePage := func(){setChooseDesiresPage_EyeColor(window, currentPage)}
|
||
|
err = addDesireRow_Choice("Eye Color", "EyeColor", editEyeColorDesirePage, "Donut", "EyeColor")
|
||
|
if (err != nil){ return nil, err }
|
||
|
|
||
|
editSkinColorDesirePage := func(){setChooseDesiresPage_SkinColor(window, currentPage)}
|
||
|
err = addDesireRow_Choice("Skin Color", "SkinColor", editSkinColorDesirePage, "Donut", "SkinColor")
|
||
|
if (err != nil){ return nil, err }
|
||
|
|
||
|
editHairColorDesirePage := func(){setChooseDesiresPage_HairColor(window, currentPage)}
|
||
|
err = addDesireRow_Choice("Hair Color", "HairColor", editHairColorDesirePage, "Donut", "HairColor")
|
||
|
if (err != nil){ return nil, err }
|
||
|
|
||
|
editHairTextureDesirePage := func(){setChooseDesiresPage_HairTexture(window, currentPage)}
|
||
|
err = addDesireRow_Choice("Hair Texture", "HairTexture", editHairTextureDesirePage, "Donut", "HairTexture")
|
||
|
if (err != nil){ return nil, err }
|
||
|
|
||
|
editHasHIVDesirePage := func(){setChooseDesiresPage_Infections(window, currentPage)}
|
||
|
err = addDesireRow_Choice("Has HIV", "HasHIV", editHasHIVDesirePage, "Donut", "HasHIV")
|
||
|
if (err != nil){ return nil, err }
|
||
|
|
||
|
editHasGenitalHerpesDesirePage := func(){setChooseDesiresPage_Infections(window, currentPage)}
|
||
|
err = addDesireRow_Choice("Has Genital Herpes", "HasGenitalHerpes", editHasGenitalHerpesDesirePage, "Donut", "HasGenitalHerpes")
|
||
|
if (err != nil){ return nil, err }
|
||
|
|
||
|
foodNamesList := []string{
|
||
|
"Fruit",
|
||
|
"Vegetables",
|
||
|
"Nuts",
|
||
|
"Grains",
|
||
|
"Dairy",
|
||
|
"Seafood",
|
||
|
"Beef",
|
||
|
"Pork",
|
||
|
"Poultry",
|
||
|
"Eggs",
|
||
|
"Beans",
|
||
|
}
|
||
|
|
||
|
for _, foodName := range foodNamesList{
|
||
|
|
||
|
foodRatingDesireTitle := foodName + " Rating"
|
||
|
foodRatingDesireName := foodName + "Rating"
|
||
|
|
||
|
editFoodRatingDesirePage := func(){setChooseDesiresPage_FoodRating(window, foodName, currentPage)}
|
||
|
err = addDesireRow_Choice(foodRatingDesireTitle, foodRatingDesireName, editFoodRatingDesirePage, "Bar", foodRatingDesireName)
|
||
|
if (err != nil){ return nil, err }
|
||
|
}
|
||
|
|
||
|
editFameDesirePage := func(){setChooseDesiresPage_Fame(window, currentPage)}
|
||
|
err = addDesireRow_Choice("Fame", "Fame", editFameDesirePage, "Bar", "Fame")
|
||
|
if (err != nil){ return nil, err }
|
||
|
|
||
|
editAlcoholFrequencyDesirePage := func(){setChooseDesiresPage_DrugFrequency(window, "Alcohol", currentPage)}
|
||
|
err = addDesireRow_Choice("Alcohol Frequency", "AlcoholFrequency", editAlcoholFrequencyDesirePage, "Bar", "AlcoholFrequency")
|
||
|
if (err != nil){ return nil, err }
|
||
|
|
||
|
editTobaccoFrequencyDesirePage := func(){setChooseDesiresPage_DrugFrequency(window, "Tobacco", currentPage)}
|
||
|
err = addDesireRow_Choice("Tobacco Frequency", "TobaccoFrequency", editTobaccoFrequencyDesirePage, "Bar", "TobaccoFrequency")
|
||
|
if (err != nil){ return nil, err }
|
||
|
|
||
|
editCannabisFrequencyDesirePage := func(){setChooseDesiresPage_DrugFrequency(window, "Cannabis", currentPage)}
|
||
|
err = addDesireRow_Choice("Cannabis Frequency", "CannabisFrequency", editCannabisFrequencyDesirePage, "Bar", "CannabisFrequency")
|
||
|
if (err != nil){ return nil, err }
|
||
|
|
||
|
editGenderIdentityDesirePage := func(){setChooseDesiresPage_GenderIdentity(window, currentPage)}
|
||
|
err = addDesireRow_Choice("Gender Identity", "GenderIdentity", editGenderIdentityDesirePage, "Donut", "GenderIdentity")
|
||
|
if (err != nil){ return nil, err }
|
||
|
|
||
|
editPetsRatingDesirePage := func(){setChooseDesiresPage_Pets(window, currentPage)}
|
||
|
err = addDesireRow_Choice("Pets Rating", "PetsRating", editPetsRatingDesirePage, "Bar", "PetsRating")
|
||
|
if (err != nil){ return nil, err }
|
||
|
|
||
|
editDogsRatingDesirePage := func(){setChooseDesiresPage_Pets(window, currentPage)}
|
||
|
err = addDesireRow_Choice("Dogs Rating", "DogsRating", editDogsRatingDesirePage, "Bar", "DogsRating")
|
||
|
if (err != nil){ return nil, err }
|
||
|
|
||
|
editCatsRatingDesirePage := func(){setChooseDesiresPage_Pets(window, currentPage)}
|
||
|
err = addDesireRow_Choice("Cats Rating", "CatsRating", editCatsRatingDesirePage, "Bar", "CatsRating")
|
||
|
if (err != nil){ return nil, err }
|
||
|
|
||
|
editOffspringProbabilityOfAnyMonogenicDiseaseDesirePage := func(){setChooseDesiresPage_MonogenicDiseases(window, currentPage)}
|
||
|
err = addDesireRow_Numerical("Offspring Probability Of Any Monogenic Disease", "OffspringProbabilityOfAnyMonogenicDisease", editOffspringProbabilityOfAnyMonogenicDiseaseDesirePage, "Donut", "OffspringProbabilityOfAnyMonogenicDisease")
|
||
|
if (err != nil){ return nil, err }
|
||
|
|
||
|
edit23andMeMaternalHaplogroupDesirePage := func(){setChooseDesiresPage_23andMe_Haplogroup(window, "Maternal", currentPage)}
|
||
|
err = addDesireRow_Choice("23andMe Maternal Haplogroup", "23andMe_MaternalHaplogroup", edit23andMeMaternalHaplogroupDesirePage, "Bar", "23andMe_MaternalHaplogroup")
|
||
|
if (err != nil){ return nil, err }
|
||
|
|
||
|
edit23andMePaternalHaplogroupDesirePage := func(){setChooseDesiresPage_23andMe_Haplogroup(window, "Paternal", currentPage)}
|
||
|
err = addDesireRow_Choice("23andMe Paternal Haplogroup", "23andMe_PaternalHaplogroup", edit23andMePaternalHaplogroupDesirePage, "Bar", "23andMe_PaternalHaplogroup")
|
||
|
if (err != nil){ return nil, err }
|
||
|
|
||
|
edit23andMeNeanderthalVariantsDesirePage := func(){setChooseDesiresPage_23andMe_NeanderthalVariants(window, currentPage)}
|
||
|
err = addDesireRow_Numerical("23andMe Neanderthal Variants", "23andMe_NeanderthalVariants", edit23andMeNeanderthalVariantsDesirePage, "Donut", "23andMe_NeanderthalVariants")
|
||
|
if (err != nil){ return nil, err }
|
||
|
|
||
|
edit23andMeAncestryCompositionDesirePage := func(){setChooseDesiresPage_23andMe_AncestryComposition(window, "User", currentPage)}
|
||
|
err = addDesireRow_Custom("23andMe Ancestry Composition", "23andMe_AncestryComposition", edit23andMeAncestryCompositionDesirePage)
|
||
|
if (err != nil){ return nil, err }
|
||
|
|
||
|
editLanguageDesirePage := func(){setChooseDesiresPage_Language(window, currentPage)}
|
||
|
err = addDesireRow_Custom("Language", "Language", editLanguageDesirePage)
|
||
|
if (err != nil){ return nil, err }
|
||
|
|
||
|
allDesiresGrid := container.NewHBox(layout.NewSpacer(), widget.NewSeparator(), desireButtonsColumn, widget.NewSeparator(), desireNameAndDataColumn, widget.NewSeparator(), filterOptionChecksColumn, widget.NewSeparator(), layout.NewSpacer())
|
||
|
|
||
|
return allDesiresGrid, nil
|
||
|
}
|
||
|
|
||
|
allDesiresGrid, err := getAllDesiresGrid()
|
||
|
if (err != nil) {
|
||
|
setErrorEncounteredPage(window, err, previousPage)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
page := container.NewVBox(title, backButton, widget.NewSeparator(), description, widget.NewSeparator(), allDesiresGrid)
|
||
|
|
||
|
setPageContent(page, window)
|
||
|
}
|
||
|
|
||
|
|
||
|
func setManageMateDownloadDesiresPage(window fyne.Window, previousPage func()){
|
||
|
|
||
|
currentPage := func(){setManageMateDownloadDesiresPage(window, previousPage)}
|
||
|
|
||
|
title := getPageTitleCentered("My Mate Download Desires")
|
||
|
|
||
|
backButton := getBackButtonCentered(previousPage)
|
||
|
|
||
|
subtitle := getPageSubtitleCentered("My Mate Download Desires")
|
||
|
|
||
|
description1 := getLabelCentered("Seekia downloads mate profiles from network hosts.")
|
||
|
description2 := getLabelCentered("These are servers run by volunteers.")
|
||
|
description3 := getLabelCentered("Your download desires are shared to hosts when you download profiles.")
|
||
|
description4 := getLabelCentered("These desires limit the profiles you download.")
|
||
|
description5 := getLabelCentered("You can choose how much information to share.")
|
||
|
description6 := getLabelCentered("The more desires you share, the less time it will take to download profiles.")
|
||
|
description7 := getLabelCentered("The hosts could be tracking this information, so more desires will reduce your privacy.")
|
||
|
description8 := getLabelCentered("All profiles are downloaded over the Tor anonymity network.")
|
||
|
|
||
|
chooseDesiresButton := getWidgetCentered(widget.NewButtonWithIcon("Choose Desires", theme.NavigateNextIcon(), func(){
|
||
|
setChooseMateDownloadDesiresPage(window, currentPage)
|
||
|
}))
|
||
|
|
||
|
page := container.NewVBox(title, backButton, widget.NewSeparator(), subtitle, widget.NewSeparator(), description1, description2, description3, description4, description5, description6, description7, description8, chooseDesiresButton)
|
||
|
|
||
|
setPageContent(page, window)
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
func setChooseMateDownloadDesiresPage(window fyne.Window, previousPage func()){
|
||
|
|
||
|
setLoadingScreen(window, "Choose Mate Download Desires", "Loading Download Desires...")
|
||
|
|
||
|
currentPage := func(){setChooseMateDownloadDesiresPage(window, previousPage)}
|
||
|
|
||
|
title := getPageTitleCentered("Choose Mate Download Desires")
|
||
|
|
||
|
backButton := getBackButtonCentered(previousPage)
|
||
|
|
||
|
description1 := getLabelCentered("You will share the selected desires with Hosts when you download profiles.")
|
||
|
description2 := getLabelCentered("These desires will not be displayed on your profile.")
|
||
|
description3 := getLabelCentered("Each desire will only be shared if you have enabled Filter All or Require Response")
|
||
|
description4 := getLabelCentered("Select each desire you are comfortable sharing with hosts.")
|
||
|
|
||
|
//TODO: Add Help buttons to explain this better
|
||
|
// User should understand that the hosts will not necessarily know who they are.
|
||
|
// They will make requests over Tor, and their requestor fingerprint will be defined by these desires
|
||
|
// Each shared desire will increase the entropy of a requestor's fingerprint
|
||
|
// Most requestors will probably have a very unique fingerprint
|
||
|
//
|
||
|
// The challenge for malicious hosts will be to link a requestor fingerprint to a requestor's mate identity
|
||
|
// This may be difficult or easy, depending on how similar the requestor's desires are to their own profile
|
||
|
|
||
|
getDesiresGrid := func()(*fyne.Container, error){
|
||
|
|
||
|
desireTitlesColumn := container.NewVBox()
|
||
|
desireSelectChecksColumn := container.NewVBox()
|
||
|
|
||
|
desireNameLabel := getItalicLabelCentered("Desire Name:")
|
||
|
shareDesireLabel := getItalicLabelCentered("Share Desire?")
|
||
|
|
||
|
desireTitlesColumn.Add(desireNameLabel)
|
||
|
desireSelectChecksColumn.Add(shareDesireLabel)
|
||
|
|
||
|
desireTitlesColumn.Add(widget.NewSeparator())
|
||
|
desireSelectChecksColumn.Add(widget.NewSeparator())
|
||
|
|
||
|
allMyDownloadDesiresList := myMateCriteria.GetAllMyMateDownloadDesiresList()
|
||
|
|
||
|
for _, desireName := range allMyDownloadDesiresList{
|
||
|
|
||
|
desireTitle, err := mateDesires.GetDesireTitleFromDesireName(desireName)
|
||
|
if (err != nil) { return nil, err }
|
||
|
|
||
|
desireTitleLabel := getBoldLabelCentered(translate(desireTitle))
|
||
|
|
||
|
getDesireSelectCheck := func()(fyne.Widget, error){
|
||
|
|
||
|
selectCheck := widget.NewCheck("", func(selected bool){
|
||
|
|
||
|
err := myMateCriteria.SetShareMyDesireStatus(desireName, selected)
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, currentPage)
|
||
|
return
|
||
|
}
|
||
|
})
|
||
|
|
||
|
isSelected, err := myMateCriteria.GetShareMyDesireStatus(desireName)
|
||
|
if (err != nil){ return nil, err }
|
||
|
if (isSelected == true){
|
||
|
selectCheck.Checked = true
|
||
|
}
|
||
|
|
||
|
return selectCheck, nil
|
||
|
}
|
||
|
|
||
|
desireSelectCheck, err := getDesireSelectCheck()
|
||
|
if (err != nil) { return nil, err }
|
||
|
|
||
|
desireSelectCheckCentered := getWidgetCentered(desireSelectCheck)
|
||
|
|
||
|
desireTitlesColumn.Add(desireTitleLabel)
|
||
|
desireSelectChecksColumn.Add(desireSelectCheckCentered)
|
||
|
|
||
|
desireTitlesColumn.Add(widget.NewSeparator())
|
||
|
desireSelectChecksColumn.Add(widget.NewSeparator())
|
||
|
}
|
||
|
|
||
|
desiresGrid := container.NewHBox(layout.NewSpacer(), desireTitlesColumn, desireSelectChecksColumn, layout.NewSpacer())
|
||
|
|
||
|
return desiresGrid, nil
|
||
|
}
|
||
|
|
||
|
desiresGrid, err := getDesiresGrid()
|
||
|
if (err != nil){
|
||
|
setErrorEncounteredPage(window, err, previousPage)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
page := container.NewVBox(title, backButton, widget.NewSeparator(), description1, description2, description3, description4, widget.NewSeparator(), desiresGrid)
|
||
|
|
||
|
setPageContent(page, window)
|
||
|
}
|
||
|
|
||
|
|