seekia/gui/desiresGui_General.go

2268 lines
84 KiB
Go
Raw Normal View History

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(){
2024-08-11 14:31:40 +02:00
newDesiredLanguagesList, _ := helpers.DeleteAllMatchingItemsFromList(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(){
2024-08-11 14:31:40 +02:00
newDesiredCountriesList, _ := helpers.DeleteAllMatchingItemsFromList(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(){
2024-08-11 14:31:40 +02:00
newDesiredTermsList, _ := helpers.DeleteAllMatchingItemsFromList(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
}
2024-08-11 14:31:40 +02:00
newAttributeList, _ := helpers.DeleteAllMatchingItemsFromList(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)
}