2159 lines
74 KiB
Go
2159 lines
74 KiB
Go
package gui
|
|
|
|
// matchesGui.go implements pages to view a user's mate matches
|
|
|
|
import "fyne.io/fyne/v2"
|
|
import "fyne.io/fyne/v2/canvas"
|
|
import "fyne.io/fyne/v2/container"
|
|
import "fyne.io/fyne/v2/data/binding"
|
|
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/internal/appMemory"
|
|
import "seekia/internal/badgerDatabase"
|
|
import "seekia/internal/desires/mateDesires"
|
|
import "seekia/internal/desires/myLocalDesires"
|
|
import "seekia/internal/desires/myMateDesires"
|
|
import "seekia/internal/encoding"
|
|
import "seekia/internal/helpers"
|
|
import "seekia/internal/identity"
|
|
import "seekia/internal/imagery"
|
|
import "seekia/internal/myBlockedUsers"
|
|
import "seekia/internal/myIdentity"
|
|
import "seekia/internal/myIgnoredUsers"
|
|
import "seekia/internal/myLikedUsers"
|
|
import "seekia/internal/myMatches"
|
|
import "seekia/internal/myMatchScore"
|
|
import "seekia/internal/mySettings"
|
|
import "seekia/internal/network/appNetworkType/getAppNetworkType"
|
|
import "seekia/internal/profiles/attributeDisplay"
|
|
import "seekia/internal/profiles/viewableProfiles"
|
|
|
|
import "strings"
|
|
import "time"
|
|
import "errors"
|
|
import "slices"
|
|
import "sync"
|
|
|
|
|
|
func setMatchesPage(window fyne.Window){
|
|
|
|
appMemory.SetMemoryEntry("CurrentViewedPage", "Matches")
|
|
|
|
checkIfPageHasChangedFunction := func()bool{
|
|
exists, currentViewedPage := appMemory.GetMemoryEntry("CurrentViewedPage")
|
|
if (exists == false || currentViewedPage != "Matches"){
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
currentPage := func(){setMatchesPage(window)}
|
|
|
|
title := getPageTitleCentered("My Matches")
|
|
|
|
desiresIcon, err := getFyneImageIcon("Desires")
|
|
if (err != nil){
|
|
setErrorEncounteredPage(window, err, func(){setHomePage(window)})
|
|
return
|
|
}
|
|
|
|
statsIcon, err := getFyneImageIcon("Stats")
|
|
if (err != nil){
|
|
setErrorEncounteredPage(window, err, func(){setHomePage(window)})
|
|
return
|
|
}
|
|
|
|
matchScoreIcon, err := getFyneImageIcon("MatchScore")
|
|
if (err != nil){
|
|
setErrorEncounteredPage(window, err, func(){setHomePage(window)})
|
|
return
|
|
}
|
|
|
|
customizeIcon, err := getFyneImageIcon("Info")
|
|
if (err != nil){
|
|
setErrorEncounteredPage(window, err, func(){setHomePage(window)})
|
|
return
|
|
}
|
|
|
|
desiresButton := widget.NewButton(translate("Desires"), func(){
|
|
setViewAllMyDesiresPage(window, currentPage)
|
|
})
|
|
desiresButtonWithIcon := container.NewGridWithColumns(1, desiresIcon, desiresButton)
|
|
|
|
customizeButton := widget.NewButton("Customize", func(){
|
|
setCustomizeMatchDisplayPage(window, currentPage)
|
|
})
|
|
customizeButtonWithIcon := container.NewGridWithColumns(1, customizeIcon, customizeButton)
|
|
|
|
matchScoreButton := widget.NewButton(translate("Score"), func(){
|
|
setConfigureMatchScorePage(window, currentPage)
|
|
})
|
|
matchScoreButtonWithIcon := container.NewGridWithColumns(1, matchScoreIcon, matchScoreButton)
|
|
|
|
statsButton := widget.NewButton(translate("Stats"), func(){
|
|
setMyMatchStatisticsPage(window, currentPage)
|
|
})
|
|
statsButtonWithIcon := container.NewGridWithColumns(1, statsIcon, statsButton)
|
|
|
|
buttonsRow := getContainerCentered(container.NewGridWithRows(1, matchScoreButtonWithIcon, desiresButtonWithIcon, statsButtonWithIcon, customizeButtonWithIcon))
|
|
|
|
currentSortByAttribute, err := myMatches.GetMatchesSortByAttribute()
|
|
if (err != nil) {
|
|
setErrorEncounteredPage(window, err, func(){setHomePage(window)})
|
|
return
|
|
}
|
|
|
|
sortingByLabel := getBoldLabel(translate("Sorting By:"))
|
|
|
|
sortByAttributeTitle, _, _, _, _, err := attributeDisplay.GetProfileAttributeDisplayInfo(currentSortByAttribute)
|
|
if (err != nil){
|
|
setErrorEncounteredPage(window, err, func(){setHomePage(window)})
|
|
return
|
|
}
|
|
|
|
sortByButton := widget.NewButton(translate(sortByAttributeTitle), func(){
|
|
setSelectMatchesSortByAttributePage(window, currentPage)
|
|
})
|
|
|
|
getSortDirectionButtonWithIcon := func()(fyne.Widget, error){
|
|
|
|
currentSortDirection, err := myMatches.GetMatchesSortDirection()
|
|
if (err != nil) { return nil, err }
|
|
|
|
if (currentSortDirection == "Ascending"){
|
|
ascendingButton := widget.NewButtonWithIcon(translate("Ascending"), theme.MoveUpIcon(), func(){
|
|
appMemory.SetMemoryEntry("StopBuildMatchesYesNo", "Yes")
|
|
_ = mySettings.SetSetting("MatchesSortDirection", "Descending")
|
|
_ = mySettings.SetSetting("MatchesSortedStatus", "No")
|
|
_ = mySettings.SetSetting("MatchesViewIndex", "0")
|
|
currentPage()
|
|
})
|
|
|
|
return ascendingButton, nil
|
|
}
|
|
|
|
descendingButton := widget.NewButtonWithIcon(translate("Descending"), theme.MoveDownIcon(), func(){
|
|
appMemory.SetMemoryEntry("StopBuildMatchesYesNo", "Yes")
|
|
_ = mySettings.SetSetting("MatchesSortDirection", "Ascending")
|
|
_ = mySettings.SetSetting("MatchesSortedStatus", "No")
|
|
_ = mySettings.SetSetting("MatchesViewIndex", "0")
|
|
|
|
currentPage()
|
|
})
|
|
|
|
return descendingButton, nil
|
|
}
|
|
|
|
sortDirectionButton, err := getSortDirectionButtonWithIcon()
|
|
if (err != nil) {
|
|
setErrorEncounteredPage(window, err, func(){setHomePage(window)})
|
|
return
|
|
}
|
|
|
|
sortByRow := container.NewHBox(layout.NewSpacer(), sortingByLabel, sortByButton, sortDirectionButton, layout.NewSpacer())
|
|
|
|
appNetworkType, err := getAppNetworkType.GetAppNetworkType()
|
|
if (err != nil) {
|
|
setErrorEncounteredPage(window, err, func(){setHomePage(window)})
|
|
return
|
|
}
|
|
|
|
matchesReady, err := myMatches.GetMatchesReadyStatus(appNetworkType)
|
|
if (err != nil) {
|
|
setErrorEncounteredPage(window, err, func(){setHomePage(window)})
|
|
return
|
|
}
|
|
|
|
if (matchesReady == false){
|
|
|
|
progressPercentageBinding := binding.NewFloat()
|
|
sortingProgressBinding := binding.NewString()
|
|
|
|
startUpdateMatchesAndProgressBarFunction := func(){
|
|
|
|
err := myMatches.StartUpdatingMyMatches(appNetworkType)
|
|
if (err != nil) {
|
|
setErrorEncounteredPage(window, err, currentPage)
|
|
return
|
|
}
|
|
|
|
sortingProgressBindingSet := false
|
|
|
|
var encounteredError error
|
|
|
|
for {
|
|
|
|
pageHasChanged := checkIfPageHasChangedFunction()
|
|
if (pageHasChanged == true){
|
|
appMemory.SetMemoryEntry("StopBuildMatchesYesNo", "Yes")
|
|
return
|
|
}
|
|
|
|
buildEncounteredError, errorEncounteredString, buildIsStopped, matchesAreReady, currentPercentageProgress, err := myMatches.GetMyMatchesBuildStatus(appNetworkType)
|
|
if (err != nil){
|
|
encounteredError = err
|
|
break
|
|
}
|
|
if (buildEncounteredError == true){
|
|
encounteredError = errors.New(errorEncounteredString)
|
|
break
|
|
}
|
|
|
|
if (buildIsStopped == true){
|
|
return
|
|
}
|
|
|
|
if (matchesAreReady == true){
|
|
progressPercentageBinding.Set(1)
|
|
|
|
// We wait so that the loading bar will appear complete.
|
|
time.Sleep(100 * time.Millisecond)
|
|
|
|
currentPage()
|
|
return
|
|
}
|
|
|
|
progressPercentageBinding.Set(currentPercentageProgress)
|
|
|
|
if (currentPercentageProgress >= .50 && sortingProgressBindingSet == false){
|
|
|
|
numberOfMatches, err := myMatches.GetNumberOfGeneratedMatches()
|
|
if (err != nil) {
|
|
encounteredError = err
|
|
break
|
|
}
|
|
if (numberOfMatches != 0){
|
|
numberOfMatchesString := helpers.ConvertIntToString(numberOfMatches)
|
|
sortingProgressBinding.Set("Sorting " + numberOfMatchesString + " Matches...")
|
|
}
|
|
sortingProgressBindingSet = true
|
|
}
|
|
|
|
time.Sleep(100 * time.Millisecond)
|
|
}
|
|
// This will only be reached if an error occurred
|
|
errorToShow := errors.New("Error encountered while generating matches: " + encounteredError.Error())
|
|
setErrorEncounteredPage(window, errorToShow, currentPage)
|
|
}
|
|
|
|
loadingLabel := getBoldLabelCentered("Loading Matches...")
|
|
|
|
loadingBar := getWidgetCentered(widget.NewProgressBarWithData(progressPercentageBinding))
|
|
|
|
loadingDetailsLabel := widget.NewLabelWithData(sortingProgressBinding)
|
|
loadingDetailsLabel.TextStyle = getFyneTextStyle_Italic()
|
|
loadingDetailsLabelCentered := getWidgetCentered(loadingDetailsLabel)
|
|
|
|
page := container.NewVBox(title, widget.NewSeparator(), buttonsRow, widget.NewSeparator(), sortByRow, widget.NewSeparator(), loadingLabel, loadingBar, loadingDetailsLabelCentered)
|
|
|
|
setPageContent(page, window)
|
|
|
|
go startUpdateMatchesAndProgressBarFunction()
|
|
|
|
return
|
|
}
|
|
|
|
getSplashContainer := func()(*fyne.Container, error){
|
|
|
|
getRefreshResultsButtonText := func()(string, error){
|
|
needsRefresh, err := myMatches.CheckIfMyMatchesNeedRefresh()
|
|
if (err != nil) { return "", err }
|
|
|
|
if (needsRefresh == false){
|
|
return "Refresh Results", nil
|
|
}
|
|
return "Refresh Results - Updates Available!", nil
|
|
}
|
|
|
|
refreshButtonText, err := getRefreshResultsButtonText()
|
|
if (err != nil){ return nil, err }
|
|
|
|
refreshResultsButton := getWidgetCentered(widget.NewButtonWithIcon(refreshButtonText, theme.ViewRefreshIcon(), func(){
|
|
_ = mySettings.SetSetting("MatchesGeneratedStatus", "No")
|
|
_ = mySettings.SetSetting("MatchesViewIndex", "0")
|
|
currentPage()
|
|
}))
|
|
|
|
matchesReady, currentMatchesList, err := myMatches.GetMyMatchesList(appNetworkType)
|
|
if (err != nil) { return nil, err }
|
|
if (matchesReady == false){
|
|
// This should not happen, as matches were found to be ready already.
|
|
return nil, errors.New("Matches not ready after being ready already.")
|
|
}
|
|
|
|
if (len(currentMatchesList) == 0){
|
|
|
|
noMatchesFoundLabel := getBoldLabelCentered("No Matches Found")
|
|
|
|
description1 := getLabelCentered("Edit your desires to find more matches.")
|
|
description2 := getLabelCentered("View your desire statistics to see which desires are reducing your matches.")
|
|
|
|
viewDesireStatisticsButton := getWidgetCentered(widget.NewButtonWithIcon("View Desire Statistics", theme.VisibilityIcon(), func(){
|
|
setMyMatchStatisticsPage(window, currentPage)
|
|
}))
|
|
|
|
noMatchesFoundContainer := container.NewVBox(noMatchesFoundLabel, refreshResultsButton, widget.NewSeparator(), description1, description2, viewDesireStatisticsButton)
|
|
|
|
return noMatchesFoundContainer, nil
|
|
}
|
|
|
|
numberOfMatches := len(currentMatchesList)
|
|
|
|
numberOfMatchesString := helpers.ConvertIntToString(numberOfMatches)
|
|
|
|
getNumberOfMatchesFoundText := func()string{
|
|
if (numberOfMatches == 1){
|
|
result := translate("1 Match Found")
|
|
return result
|
|
}
|
|
|
|
result := numberOfMatchesString + " " + translate("Matches Found")
|
|
|
|
return result
|
|
}
|
|
|
|
numberOfMatchesFoundText := getNumberOfMatchesFoundText()
|
|
|
|
numberOfMatchesFoundLabel := getBoldLabelCentered(numberOfMatchesFoundText)
|
|
|
|
getBeginRestartContinueButtons := func()(*fyne.Container, error){
|
|
|
|
getMatchesViewIndex := func()(int, error){
|
|
exists, currentIndex, err := mySettings.GetSetting("MatchesViewIndex")
|
|
if (err != nil) { return 0, err }
|
|
if (exists == false){
|
|
return 0, nil
|
|
}
|
|
currentIndexInt, err := helpers.ConvertStringToInt(currentIndex)
|
|
if (err != nil) { return 0, err }
|
|
|
|
if (currentIndexInt > (numberOfMatches-1)){
|
|
return 0, nil
|
|
}
|
|
|
|
return currentIndexInt, nil
|
|
}
|
|
|
|
currentViewIndex, err := getMatchesViewIndex()
|
|
if (err != nil) { return nil, err }
|
|
|
|
if (currentViewIndex == 0){
|
|
beginButton := getWidgetCentered(widget.NewButtonWithIcon("Begin Browsing", theme.NavigateNextIcon(), func(){
|
|
setBrowseMatchesPage(window, currentPage)
|
|
}))
|
|
return beginButton, nil
|
|
}
|
|
|
|
restartButton := getWidgetCentered(widget.NewButtonWithIcon("Restart From Beginning", theme.ContentUndoIcon(), func(){
|
|
mySettings.SetSetting("MatchesViewIndex", "0")
|
|
setBrowseMatchesPage(window, currentPage)
|
|
}))
|
|
|
|
currentViewIndexString := helpers.ConvertIntToString(currentViewIndex + 1)
|
|
|
|
continueButtonText := "Continue from profile " + currentViewIndexString + " of " + numberOfMatchesString
|
|
|
|
continueButton := getWidgetCentered(widget.NewButtonWithIcon(continueButtonText, theme.MailForwardIcon(), func(){
|
|
setBrowseMatchesPage(window, currentPage)
|
|
}))
|
|
|
|
buttons := container.NewVBox(restartButton, continueButton)
|
|
return buttons, nil
|
|
}
|
|
|
|
beginRestartContinueButtons, err := getBeginRestartContinueButtons()
|
|
if (err != nil) { return nil, err }
|
|
|
|
splashPageContent := container.NewVBox(numberOfMatchesFoundLabel, widget.NewSeparator(), beginRestartContinueButtons, refreshResultsButton)
|
|
|
|
return splashPageContent, nil
|
|
}
|
|
|
|
splashContainer, err := getSplashContainer()
|
|
if (err != nil){
|
|
setErrorEncounteredPage(window, err, func(){setHomePage(window)})
|
|
return
|
|
}
|
|
|
|
page := container.NewVBox(title, widget.NewSeparator(), buttonsRow, widget.NewSeparator(), sortByRow, widget.NewSeparator(), splashContainer)
|
|
|
|
setPageContent(page, window)
|
|
}
|
|
|
|
// This page should only be called if matches are ready and at least 1 exists
|
|
func setBrowseMatchesPage(window fyne.Window, previousPage func()){
|
|
|
|
currentPage := func(){setBrowseMatchesPage(window, previousPage)}
|
|
|
|
title := getPageTitleCentered("Browse Matches")
|
|
|
|
backButton := getBackButtonCentered(previousPage)
|
|
|
|
getPageContent := func()(*fyne.Container, error){
|
|
|
|
appNetworkType, err := getAppNetworkType.GetAppNetworkType()
|
|
if (err != nil) { return nil, err }
|
|
|
|
matchesReady, currentMatchesList, err := myMatches.GetMyMatchesList(appNetworkType)
|
|
if (err != nil) { return nil, err }
|
|
if (matchesReady == false) {
|
|
// This should not happen, because this page should only be called if matches are already ready
|
|
return nil, errors.New("setBrowseMatchesPage called when matches are not ready.")
|
|
}
|
|
|
|
if (len(currentMatchesList) == 0){
|
|
return nil, errors.New("setBrowseMatchesPage called with no matches found.")
|
|
}
|
|
|
|
numberOfMatches := len(currentMatchesList)
|
|
|
|
getViewIndex := func()(int, error){
|
|
|
|
exists, currentIndexString, err := mySettings.GetSetting("MatchesViewIndex")
|
|
if (err != nil) { return 0, err }
|
|
if (exists == false){
|
|
return 0, nil
|
|
}
|
|
currentIndex, err := helpers.ConvertStringToInt(currentIndexString)
|
|
if (err != nil){
|
|
return 0, errors.New("MySettings malformed: Contains invalid MatchesViewIndex: " + currentIndexString)
|
|
}
|
|
if (currentIndex < 0){
|
|
|
|
return 0, nil
|
|
}
|
|
|
|
maximumIndex := numberOfMatches-1
|
|
if (currentIndex > maximumIndex){
|
|
|
|
return maximumIndex, nil
|
|
}
|
|
|
|
return currentIndex, nil
|
|
}
|
|
|
|
currentIndex, err := getViewIndex()
|
|
if (err != nil) { return nil, err }
|
|
|
|
pageContent := container.NewVBox()
|
|
|
|
if (numberOfMatches > 1){
|
|
|
|
getNavigationButtons := func() *fyne.Container{
|
|
|
|
getGoToBeginningButton := func()fyne.Widget{
|
|
if (currentIndex == 0){
|
|
emptyButton := widget.NewButton("", nil)
|
|
return emptyButton
|
|
}
|
|
|
|
goToBeginningButton := widget.NewButtonWithIcon("", theme.MediaSkipPreviousIcon(), func(){
|
|
_ = mySettings.SetSetting("MatchesViewIndex", "0")
|
|
currentPage()
|
|
})
|
|
return goToBeginningButton
|
|
}
|
|
|
|
getGoToEndButton := func()fyne.Widget{
|
|
|
|
finalIndex := numberOfMatches - 1
|
|
|
|
if (currentIndex >= finalIndex){
|
|
emptyButton := widget.NewButton("", nil)
|
|
return emptyButton
|
|
}
|
|
|
|
goToEndButton := widget.NewButtonWithIcon("", theme.MediaSkipNextIcon(), func(){
|
|
finalIndexString := helpers.ConvertIntToString(finalIndex)
|
|
_ = mySettings.SetSetting("MatchesViewIndex", finalIndexString)
|
|
currentPage()
|
|
})
|
|
|
|
return goToEndButton
|
|
}
|
|
|
|
getLeftButton := func()fyne.Widget{
|
|
|
|
if (currentIndex == 0){
|
|
emptyButton := widget.NewButton("", nil)
|
|
return emptyButton
|
|
}
|
|
leftButton := widget.NewButtonWithIcon("", theme.NavigateBackIcon(), func(){
|
|
newIndex := helpers.ConvertIntToString(currentIndex-1)
|
|
_ = mySettings.SetSetting("MatchesViewIndex", newIndex)
|
|
currentPage()
|
|
})
|
|
return leftButton
|
|
}
|
|
|
|
getRightButton := func()fyne.Widget{
|
|
|
|
finalIndex := numberOfMatches - 1
|
|
|
|
if (currentIndex >= finalIndex){
|
|
|
|
emptyButton := widget.NewButton("", nil)
|
|
return emptyButton
|
|
}
|
|
rightButton := widget.NewButtonWithIcon("", theme.NavigateNextIcon(), func(){
|
|
newIndex := helpers.ConvertIntToString(currentIndex+1)
|
|
_ = mySettings.SetSetting("MatchesViewIndex", newIndex)
|
|
currentPage()
|
|
})
|
|
|
|
return rightButton
|
|
}
|
|
|
|
goToBeginningButton := getGoToBeginningButton()
|
|
goToEndButton := getGoToEndButton()
|
|
|
|
leftButton := getLeftButton()
|
|
rightButton := getRightButton()
|
|
|
|
if (numberOfMatches == 1){
|
|
buttons := getContainerCentered(container.NewGridWithRows(1, goToBeginningButton, leftButton, rightButton, goToEndButton))
|
|
|
|
return buttons
|
|
}
|
|
|
|
matchRank := currentIndex + 1
|
|
|
|
currentRankString := helpers.ConvertIntToString(matchRank)
|
|
numberOfMatchesString := helpers.ConvertIntToString(numberOfMatches)
|
|
currentRankDescription := getBoldLabel(currentRankString + "/" + numberOfMatchesString)
|
|
|
|
buttons := getContainerCentered(container.NewGridWithRows(1, goToBeginningButton, leftButton, currentRankDescription, rightButton, goToEndButton))
|
|
|
|
return buttons
|
|
}
|
|
|
|
navButtons := getNavigationButtons()
|
|
|
|
pageContent.Add(navButtons)
|
|
pageContent.Add(widget.NewSeparator())
|
|
}
|
|
|
|
getMatchDisplay := func()(*fyne.Container, error){
|
|
|
|
if (currentIndex >= len(currentMatchesList) || currentIndex < 0){
|
|
return nil, errors.New("Match index out of range.")
|
|
}
|
|
|
|
matchIdentityHash := currentMatchesList[currentIndex]
|
|
|
|
userIsBlocked, _, _, _, err := myBlockedUsers.CheckIfUserIsBlocked(matchIdentityHash)
|
|
if (err != nil) { return nil, err }
|
|
if (userIsBlocked == true){
|
|
|
|
isBlockedDescription1 := getBoldLabelCentered("User is blocked.")
|
|
isBlockedDescription2 := getLabelCentered("You have blocked this match.")
|
|
isBlockedDescription3 := getLabelCentered("Refresh your matches to fix this.")
|
|
|
|
refreshMatchesButton := getWidgetCentered(widget.NewButtonWithIcon("Refresh Matches", theme.ViewRefreshIcon(), func(){
|
|
_ = mySettings.SetSetting("MatchesGeneratedStatus", "No")
|
|
_ = mySettings.SetSetting("MatchesViewIndex", "0")
|
|
setMatchesPage(window)
|
|
}))
|
|
|
|
userIsBlockedSection := container.NewVBox(isBlockedDescription1, isBlockedDescription2, isBlockedDescription3, refreshMatchesButton)
|
|
return userIsBlockedSection, nil
|
|
}
|
|
|
|
getShowIgnoredMatchesBool := func()(bool, error){
|
|
|
|
exists, isIgnoredIsEnabled, err := myLocalDesires.GetDesire("IsIgnored_FilterAll")
|
|
if (err != nil) { return false, err }
|
|
if (exists == false){
|
|
// Desire is disabled.
|
|
return true, nil
|
|
}
|
|
if (isIgnoredIsEnabled == "No"){
|
|
// Desire is disabled.
|
|
// We will show ignored matches
|
|
return true, nil
|
|
}
|
|
exists, isIgnoredDesire, err := myLocalDesires.GetDesire("IsIgnored")
|
|
if (err != nil) { return false, err }
|
|
if (exists == false){
|
|
// Desire does not exist.
|
|
// We will show ignored matches
|
|
return true, nil
|
|
}
|
|
|
|
// isIgnoredDesire is a list of base64 encoded values which the user wants
|
|
// We see if "Yes" is contained within the list
|
|
// If it is not, then the user desires only non-ignored users
|
|
myDesiredChoicesList := strings.Split(isIgnoredDesire, "+")
|
|
|
|
yesBase64 := encoding.EncodeBytesToBase64String([]byte("Yes"))
|
|
|
|
yesExists := slices.Contains(myDesiredChoicesList, yesBase64)
|
|
if (yesExists == true){
|
|
// We want to see ignored users in our matches
|
|
return true, nil
|
|
}
|
|
|
|
return false, nil
|
|
}
|
|
|
|
showIgnoredMatchesBool, err := getShowIgnoredMatchesBool()
|
|
if (err != nil) { return nil, err }
|
|
|
|
userIsIgnored, _, _, _, err := myIgnoredUsers.CheckIfUserIsIgnored(matchIdentityHash)
|
|
if (err != nil) { return nil, err }
|
|
if (userIsIgnored == true && showIgnoredMatchesBool == false){
|
|
|
|
isIgnoredDescription1 := getBoldLabelCentered("User is ignored.")
|
|
isIgnoredDescription2 := getLabelCentered("You have ignored this match.")
|
|
isIgnoredDescription3 := getLabelCentered("Refresh your matches to fix this.")
|
|
|
|
refreshMatchesButton := getWidgetCentered(widget.NewButtonWithIcon("Refresh Matches", theme.ViewRefreshIcon(), func(){
|
|
_ = mySettings.SetSetting("MatchesGeneratedStatus", "No")
|
|
_ = mySettings.SetSetting("MatchesViewIndex", "0")
|
|
setMatchesPage(window)
|
|
}))
|
|
|
|
userIsIgnoredSection := container.NewVBox(isIgnoredDescription1, isIgnoredDescription2, isIgnoredDescription3, refreshMatchesButton)
|
|
return userIsIgnoredSection, nil
|
|
}
|
|
|
|
profileExists, _, getAnyAttributeFunction, err := viewableProfiles.GetRetrieveAnyNewestViewableUserProfileAttributeFunction(matchIdentityHash, appNetworkType, true, false, true)
|
|
if (err != nil) { return nil, err }
|
|
if (profileExists == false) {
|
|
|
|
matchNotFoundLabel := getBoldLabelCentered("Match Not Found")
|
|
|
|
description1 := getLabelCentered("Their profile may have been deleted.")
|
|
description2 := getLabelCentered("Refresh your matches to fix this.")
|
|
|
|
refreshMatchesButton := getWidgetCentered(widget.NewButtonWithIcon("Refresh Matches", theme.ViewRefreshIcon(), func(){
|
|
_ = mySettings.SetSetting("MatchesGeneratedStatus", "No")
|
|
_ = mySettings.SetSetting("MatchesViewIndex", "0")
|
|
setMatchesPage(window)
|
|
}))
|
|
|
|
matchNotFoundSection := container.NewVBox(matchNotFoundLabel, description1, description2, refreshMatchesButton)
|
|
return matchNotFoundSection, nil
|
|
}
|
|
|
|
exists, _, userIsDisabled, err := getAnyAttributeFunction("Disabled")
|
|
if (err != nil){ return nil, err }
|
|
if (exists == true && userIsDisabled == "Yes"){
|
|
|
|
matchIsDisabledLabel := getBoldLabelCentered("User Is Disabled")
|
|
|
|
description1 := getLabelCentered("This user has disabled their profile.")
|
|
description2 := getLabelCentered("Refresh your matches to fix this.")
|
|
|
|
refreshMatchesButton := getWidgetCentered(widget.NewButtonWithIcon("Refresh Matches", theme.ViewRefreshIcon(), func(){
|
|
_ = mySettings.SetSetting("MatchesGeneratedStatus", "No")
|
|
_ = mySettings.SetSetting("MatchesViewIndex", "0")
|
|
setMatchesPage(window)
|
|
}))
|
|
|
|
matchIsDisabledSection := container.NewVBox(matchIsDisabledLabel, description1, description2, refreshMatchesButton)
|
|
return matchIsDisabledSection, nil
|
|
}
|
|
|
|
// We see if user's newest viewable profile still fulfills our desires
|
|
|
|
profilePassesDesires, err := myMateDesires.CheckIfMateProfilePassesAllMyDesires(false, "", getAnyAttributeFunction)
|
|
if (err != nil) { return nil, err }
|
|
if (profilePassesDesires == false){
|
|
|
|
userIsNotAMatchLabel := getBoldLabelCentered("User Is Not A Match Anymore")
|
|
|
|
description1 := getLabelCentered("This user has changed their profile and they are no longer a match.")
|
|
description2 := getLabelCentered("Refresh your matches to fix this.")
|
|
|
|
refreshMatchesButton := getWidgetCentered(widget.NewButtonWithIcon("Refresh Matches", theme.ViewRefreshIcon(), func(){
|
|
_ = mySettings.SetSetting("MatchesGeneratedStatus", "No")
|
|
_ = mySettings.SetSetting("MatchesViewIndex", "0")
|
|
setMatchesPage(window)
|
|
}))
|
|
|
|
userIsNotAMatchSection := container.NewVBox(userIsNotAMatchLabel, description1, description2, refreshMatchesButton)
|
|
|
|
return userIsNotAMatchSection, nil
|
|
}
|
|
|
|
getAvatarOrImage := func()(*canvas.Image, error){
|
|
|
|
photosExist, _, photosAttribute, err := getAnyAttributeFunction("Photos")
|
|
if (err != nil) { return nil, err }
|
|
|
|
if (photosExist == true){
|
|
|
|
photosList := strings.Split(photosAttribute, "+")
|
|
|
|
firstPhotoBase64String := photosList[0]
|
|
|
|
goImageObject, err := imagery.ConvertWEBPBase64StringToCroppedDownsizedImageObject(firstPhotoBase64String)
|
|
if (err != nil) {
|
|
return nil, errors.New("Database corrupt: Contains profile with invalid Photos attribute")
|
|
}
|
|
|
|
fyneImageObject := canvas.NewImageFromImage(goImageObject)
|
|
fyneImageObject.FillMode = canvas.ImageFillContain
|
|
|
|
return fyneImageObject, nil
|
|
}
|
|
|
|
getAvatarEmojiIdentifier := func()(int, error){
|
|
|
|
exists, _, emojiIdentifier, err := getAnyAttributeFunction("Avatar")
|
|
if (err != nil){ return 0, err }
|
|
if (exists == false){
|
|
// This is the avatar for users who have not selected an avatar
|
|
return 2929, nil
|
|
}
|
|
|
|
emojiIdentifierInt, err := helpers.ConvertStringToInt(emojiIdentifier)
|
|
if (err != nil) {
|
|
return 0, errors.New("Database corrupt: Contains user profile with invalid avatar: " + emojiIdentifier)
|
|
}
|
|
|
|
return emojiIdentifierInt, nil
|
|
}
|
|
|
|
avatarEmojiIdentifier, err := getAvatarEmojiIdentifier()
|
|
if (err != nil) { return nil, err }
|
|
|
|
emojiImage, err := getEmojiImageObject(avatarEmojiIdentifier)
|
|
if (err != nil){ return nil, err }
|
|
|
|
emojiFyneImage := canvas.NewImageFromImage(emojiImage)
|
|
emojiFyneImage.FillMode = canvas.ImageFillContain
|
|
|
|
return emojiFyneImage, nil
|
|
}
|
|
|
|
avatarOrImage, err := getAvatarOrImage()
|
|
if (err != nil) { return nil, err }
|
|
avatarOrImage.SetMinSize(getCustomFyneSize(10))
|
|
|
|
avatarOrImageHeightenerA := container.NewVBox(widget.NewLabel(""), widget.NewLabel(""), widget.NewLabel(""))
|
|
avatarOrImageHeightenerB := container.NewVBox(widget.NewLabel(""), widget.NewLabel(""), widget.NewLabel(""))
|
|
|
|
avatarOrImageHeightened := getContainerCentered(container.NewGridWithRows(1, avatarOrImageHeightenerA, avatarOrImage, avatarOrImageHeightenerB))
|
|
|
|
viewProfileButton := getWidgetCentered(widget.NewButtonWithIcon("View Profile", theme.VisibilityIcon(), func(){
|
|
setViewPeerProfilePageFromIdentityHash(window, matchIdentityHash, currentPage)
|
|
}))
|
|
|
|
getAttributesSection := func()(*fyne.Container, error){
|
|
|
|
getDisplayAttributesList := func()([]string, error){
|
|
|
|
// First attribute is always the "Sort By" attribute
|
|
|
|
currentSortByAttribute, err := myMatches.GetMatchesSortByAttribute()
|
|
if (err != nil) { return nil, err }
|
|
|
|
exists, currentAttributesListString, err := mySettings.GetSetting("CustomMatchDisplayAttributesList")
|
|
if (err != nil) { return nil, err }
|
|
if (exists == false){
|
|
newDisplayAttributesList := []string{currentSortByAttribute}
|
|
return newDisplayAttributesList, nil
|
|
}
|
|
|
|
currentAttributesList := strings.Split(currentAttributesListString, ",")
|
|
|
|
displayAttributesListPruned, _ := helpers.DeleteAllMatchingItemsFromList(currentAttributesList, currentSortByAttribute)
|
|
|
|
newDisplayAttributesList := []string{currentSortByAttribute}
|
|
|
|
newDisplayAttributesList = append(newDisplayAttributesList, displayAttributesListPruned...)
|
|
|
|
return newDisplayAttributesList, nil
|
|
}
|
|
|
|
displayAttributesList, err := getDisplayAttributesList()
|
|
if (err != nil){ return nil, err }
|
|
|
|
attributesSection := container.NewVBox()
|
|
|
|
for _, attributeName := range displayAttributesList{
|
|
|
|
attributeTitle, _, formatValueFunction, attributeUnits, missingValueText, err := attributeDisplay.GetProfileAttributeDisplayInfo(attributeName)
|
|
if (err != nil) { return nil, err }
|
|
|
|
attributeTitleLabel := getBoldLabel(attributeTitle + ":")
|
|
|
|
getAttributeValueText := func()(string, error){
|
|
|
|
attributeValueExists, _, attributeValue, err := getAnyAttributeFunction(attributeName)
|
|
if (err != nil) { return "", err }
|
|
if (attributeValueExists == false){
|
|
return missingValueText, nil
|
|
}
|
|
|
|
formattedValue, err := formatValueFunction(attributeValue)
|
|
if (err != nil) { return "", err }
|
|
|
|
result := formattedValue + attributeUnits
|
|
|
|
return result, nil
|
|
}
|
|
|
|
attributeValueText, err := getAttributeValueText()
|
|
if (err != nil) { return nil, err }
|
|
|
|
attributeValueLabel := widget.NewLabel(attributeValueText)
|
|
|
|
attributeRow := container.NewHBox(layout.NewSpacer(), attributeTitleLabel, attributeValueLabel, layout.NewSpacer())
|
|
|
|
attributesSection.Add(attributeRow)
|
|
}
|
|
|
|
return attributesSection, nil
|
|
}
|
|
|
|
attributesSection, err := getAttributesSection()
|
|
if (err != nil) { return nil, err }
|
|
|
|
getLikeOrUnlikeButtonWithIcon := func()(*fyne.Container, error){
|
|
|
|
userIsLiked, _, err := myLikedUsers.CheckIfUserIsLiked(matchIdentityHash)
|
|
if (err != nil) { return nil, err }
|
|
if (userIsLiked == true){
|
|
unlikeIcon, err := getFyneImageIcon("Unlike")
|
|
if (err != nil) { return nil, err }
|
|
unlikeButton := widget.NewButton("Unlike", func(){
|
|
setConfirmUnlikeUserPage(window, matchIdentityHash, currentPage, currentPage)
|
|
})
|
|
|
|
unlikeButtonWithIcon := container.NewGridWithColumns(1, unlikeIcon, unlikeButton)
|
|
return unlikeButtonWithIcon, nil
|
|
}
|
|
|
|
likeIcon, err := getFyneImageIcon("Like")
|
|
if (err != nil) { return nil, err }
|
|
likeButton := widget.NewButton("Like", func(){
|
|
setConfirmLikeUserPage(window, matchIdentityHash, currentPage, currentPage)
|
|
})
|
|
|
|
likeButtonWithIcon := container.NewGridWithColumns(1, likeIcon, likeButton)
|
|
return likeButtonWithIcon, nil
|
|
}
|
|
|
|
likeOrUnlikeButtonWithIcon, err := getLikeOrUnlikeButtonWithIcon()
|
|
if (err != nil) { return nil, err }
|
|
|
|
getIgnoreOrUnignoreButtonWithIcon := func()(*fyne.Container, error){
|
|
|
|
if (userIsIgnored == true){
|
|
unignoreIcon := widget.NewIcon(theme.VisibilityIcon())
|
|
|
|
unignoreButton := widget.NewButton("Unignore", func(){
|
|
setConfirmUnignoreUserPage(window, matchIdentityHash, currentPage, currentPage)
|
|
})
|
|
|
|
unignoreButtonWithIcon := container.NewGridWithColumns(1, unignoreIcon, unignoreButton)
|
|
return unignoreButtonWithIcon, nil
|
|
}
|
|
|
|
ignoreIcon := widget.NewIcon(theme.VisibilityOffIcon())
|
|
|
|
ignoreButton := widget.NewButton("Ignore", func(){
|
|
setConfirmIgnoreUserPage(window, matchIdentityHash, currentPage, currentPage)
|
|
})
|
|
|
|
ignoreButtonWithIcon := container.NewGridWithColumns(1, ignoreIcon, ignoreButton)
|
|
return ignoreButtonWithIcon, nil
|
|
}
|
|
|
|
ignoreOrUnignoreButtonWithIcon, err := getIgnoreOrUnignoreButtonWithIcon()
|
|
if (err != nil) { return nil, err }
|
|
|
|
greetIcon, err := getFyneImageIcon("Greet")
|
|
if (err != nil) { return nil, err }
|
|
greetButton := widget.NewButton("Greet", func(){
|
|
setConfirmGreetOrRejectUserPage(window, "Greet", matchIdentityHash, currentPage, currentPage)
|
|
})
|
|
greetButtonWithIcon := container.NewGridWithColumns(1, greetIcon, greetButton)
|
|
|
|
moreIcon, err := getFyneImageIcon("Plus")
|
|
if (err != nil) { return nil, err }
|
|
moreButton := widget.NewButton("More", func(){
|
|
setViewPeerActionsPage(window, matchIdentityHash, currentPage)
|
|
})
|
|
moreButtonWithIcon := container.NewGridWithColumns(1, moreIcon, moreButton)
|
|
|
|
actionsRow := getContainerCentered(container.NewGridWithRows(1, likeOrUnlikeButtonWithIcon, ignoreOrUnignoreButtonWithIcon, greetButtonWithIcon, moreButtonWithIcon))
|
|
|
|
matchDisplay := container.NewVBox(avatarOrImageHeightened, viewProfileButton, widget.NewSeparator(), attributesSection, widget.NewSeparator(), actionsRow)
|
|
|
|
return matchDisplay, nil
|
|
}
|
|
|
|
matchDisplay, err := getMatchDisplay()
|
|
if (err != nil) { return nil, err }
|
|
|
|
pageContent.Add(matchDisplay)
|
|
|
|
return pageContent, nil
|
|
}
|
|
|
|
pageContent, err := getPageContent()
|
|
if (err != nil){
|
|
setErrorEncounteredPage(window, err, previousPage)
|
|
return
|
|
}
|
|
|
|
page := container.NewVBox(title, backButton, widget.NewSeparator(), pageContent)
|
|
|
|
setPageContent(page, window)
|
|
}
|
|
|
|
func setSelectMatchesSortByAttributePage(window fyne.Window, previousPage func()){
|
|
|
|
appMemory.SetMemoryEntry("CurrentViewedPage", "SortBySelectPage_Matches")
|
|
|
|
title := getPageTitleCentered("Select Sort By Attribute")
|
|
|
|
backButton := getBackButtonCentered(previousPage)
|
|
|
|
description := getLabelCentered("Choose the attribute to sort your matches by.")
|
|
|
|
getPageContent := func()(*fyne.Container, error){
|
|
|
|
generalAttributeButtonsGrid := container.NewGridWithColumns(1)
|
|
physicalAttributeButtonsGrid := container.NewGridWithColumns(1)
|
|
lifestyleAttributeButtonsGrid := container.NewGridWithColumns(1)
|
|
mentalAttributeButtonsGrid := container.NewGridWithColumns(1)
|
|
|
|
addAttributeSelectButton := func(attributeType string, attributeName string, sortDirection string)error{
|
|
|
|
attributeTitle, _, _, _, _, err := attributeDisplay.GetProfileAttributeDisplayInfo(attributeName)
|
|
if (err != nil) { return err }
|
|
|
|
attributeButton := widget.NewButton(attributeTitle, func(){
|
|
_ = mySettings.SetSetting("MatchesSortedStatus", "No")
|
|
_ = mySettings.SetSetting("MatchesSortByAttribute", attributeName)
|
|
_ = mySettings.SetSetting("MatchesSortDirection", sortDirection)
|
|
_ = mySettings.SetSetting("MatchesViewIndex", "0")
|
|
|
|
previousPage()
|
|
})
|
|
|
|
if (attributeType == "General"){
|
|
|
|
generalAttributeButtonsGrid.Add(attributeButton)
|
|
|
|
} else if (attributeType == "Physical"){
|
|
|
|
physicalAttributeButtonsGrid.Add(attributeButton)
|
|
|
|
} else if (attributeType == "Lifestyle"){
|
|
|
|
lifestyleAttributeButtonsGrid.Add(attributeButton)
|
|
|
|
} else if (attributeType == "Mental"){
|
|
|
|
mentalAttributeButtonsGrid.Add(attributeButton)
|
|
|
|
} else {
|
|
return errors.New("addSelectButton called with invalid attributeType: " + attributeType)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
generalLabel := getBoldLabelCentered("General")
|
|
|
|
err := addAttributeSelectButton("General", "MatchScore", "Descending")
|
|
if (err != nil) { return nil, err }
|
|
err = addAttributeSelectButton("General", "Distance", "Ascending")
|
|
if (err != nil) { return nil, err }
|
|
err = addAttributeSelectButton("General", "SearchTermsCount", "Descending")
|
|
if (err != nil) { return nil, err }
|
|
|
|
physicalLabel := getBoldLabelCentered("Physical")
|
|
|
|
err = addAttributeSelectButton("Physical", "Age", "Ascending")
|
|
if (err != nil) { return nil, err }
|
|
err = addAttributeSelectButton("Physical", "Height", "Descending")
|
|
if (err != nil) { return nil, err }
|
|
err = addAttributeSelectButton("Physical", "BodyFat", "Ascending")
|
|
if (err != nil) { return nil, err }
|
|
err = addAttributeSelectButton("Physical", "BodyMuscle", "Descending")
|
|
if (err != nil) { return nil, err }
|
|
err = addAttributeSelectButton("Physical", "SkinColor", "Ascending")
|
|
if (err != nil) { return nil, err }
|
|
err = addAttributeSelectButton("Physical", "HairTexture", "Ascending")
|
|
if (err != nil) { return nil, err }
|
|
|
|
err = addAttributeSelectButton("Physical", "RacialSimilarity", "Descending")
|
|
if (err != nil) { return nil, err }
|
|
|
|
err = addAttributeSelectButton("Physical", "EyeColorSimilarity", "Descending")
|
|
if (err != nil) { return nil, err }
|
|
err = addAttributeSelectButton("Physical", "EyeColorGenesSimilarity", "Descending")
|
|
if (err != nil) { return nil, err }
|
|
err = addAttributeSelectButton("Physical", "HairColorSimilarity", "Descending")
|
|
if (err != nil) { return nil, err }
|
|
err = addAttributeSelectButton("Physical", "HairColorGenesSimilarity", "Descending")
|
|
if (err != nil) { return nil, err }
|
|
err = addAttributeSelectButton("Physical", "SkinColorSimilarity", "Descending")
|
|
if (err != nil) { return nil, err }
|
|
err = addAttributeSelectButton("Physical", "SkinColorGenesSimilarity", "Descending")
|
|
if (err != nil) { return nil, err }
|
|
err = addAttributeSelectButton("Physical", "HairTextureSimilarity", "Descending")
|
|
if (err != nil) { return nil, err }
|
|
err = addAttributeSelectButton("Physical", "HairTextureGenesSimilarity", "Descending")
|
|
if (err != nil) { return nil, err }
|
|
err = addAttributeSelectButton("Physical", "FacialStructureGenesSimilarity", "Descending")
|
|
if (err != nil) { return nil, err }
|
|
err = addAttributeSelectButton("Physical", "23andMe_AncestralSimilarity", "Descending")
|
|
if (err != nil) { return nil, err }
|
|
err = addAttributeSelectButton("Physical", "23andMe_MaternalHaplogroupSimilarity", "Descending")
|
|
if (err != nil) { return nil, err }
|
|
err = addAttributeSelectButton("Physical", "23andMe_PaternalHaplogroupSimilarity", "Descending")
|
|
if (err != nil) { return nil, err }
|
|
|
|
err = addAttributeSelectButton("Physical", "OffspringProbabilityOfAnyMonogenicDisease", "Ascending")
|
|
if (err != nil) { return nil, err }
|
|
|
|
err = addAttributeSelectButton("Physical", "TotalPolygenicDiseaseRiskScore", "Ascending")
|
|
if (err != nil) { return nil, err }
|
|
|
|
err = addAttributeSelectButton("Physical", "OffspringTotalPolygenicDiseaseRiskScore", "Ascending")
|
|
if (err != nil) { return nil, err }
|
|
|
|
err = addAttributeSelectButton("Physical", "AutismRiskScore", "Ascending")
|
|
if (err != nil) { return nil, err }
|
|
err = addAttributeSelectButton("Physical", "OffspringAutismRiskScore", "Ascending")
|
|
if (err != nil) { return nil, err }
|
|
|
|
err = addAttributeSelectButton("Physical", "ObesityRiskScore", "Ascending")
|
|
if (err != nil) { return nil, err }
|
|
err = addAttributeSelectButton("Physical", "OffspringObesityRiskScore", "Ascending")
|
|
if (err != nil) { return nil, err }
|
|
|
|
err = addAttributeSelectButton("Physical", "OffspringBlueEyesProbability", "Descending")
|
|
if (err != nil) { return nil, err }
|
|
err = addAttributeSelectButton("Physical", "OffspringGreenEyesProbability", "Descending")
|
|
if (err != nil) { return nil, err }
|
|
err = addAttributeSelectButton("Physical", "OffspringHazelEyesProbability", "Descending")
|
|
if (err != nil) { return nil, err }
|
|
err = addAttributeSelectButton("Physical", "OffspringBrownEyesProbability", "Descending")
|
|
if (err != nil) { return nil, err }
|
|
|
|
err = addAttributeSelectButton("Physical", "OffspringLactoseToleranceProbability", "Descending")
|
|
if (err != nil) { return nil, err }
|
|
|
|
err = addAttributeSelectButton("Physical", "OffspringStraightHairProbability", "Descending")
|
|
if (err != nil) { return nil, err }
|
|
err = addAttributeSelectButton("Physical", "OffspringCurlyHairProbability", "Descending")
|
|
if (err != nil) { return nil, err }
|
|
|
|
// Numeric Traits:
|
|
|
|
err = addAttributeSelectButton("Physical", "HomosexualnessScore", "Ascending")
|
|
if (err != nil) { return nil, err }
|
|
err = addAttributeSelectButton("Physical", "OffspringHomosexualnessScore", "Ascending")
|
|
if (err != nil) { return nil, err }
|
|
|
|
err = addAttributeSelectButton("Physical", "PredictedHeight", "Descending")
|
|
if (err != nil) { return nil, err }
|
|
err = addAttributeSelectButton("Physical", "OffspringPredictedHeight", "Descending")
|
|
if (err != nil) { return nil, err }
|
|
|
|
err = addAttributeSelectButton("Physical", "23andMe_NeanderthalVariants", "Descending")
|
|
if (err != nil) { return nil, err }
|
|
|
|
lifestyleLabel := getBoldLabelCentered("Lifestyle")
|
|
|
|
err = addAttributeSelectButton("Lifestyle", "WealthInGold", "Descending")
|
|
if (err != nil) { return nil, err }
|
|
|
|
err = addAttributeSelectButton("Lifestyle", "Fame", "Descending")
|
|
if (err != nil) { return nil, err }
|
|
|
|
err = addAttributeSelectButton("Lifestyle", "FruitRating", "Descending")
|
|
if (err != nil) { return nil, err }
|
|
err = addAttributeSelectButton("Lifestyle", "VegetablesRating", "Descending")
|
|
if (err != nil) { return nil, err }
|
|
err = addAttributeSelectButton("Lifestyle", "NutsRating", "Descending")
|
|
if (err != nil) { return nil, err }
|
|
err = addAttributeSelectButton("Lifestyle", "GrainsRating", "Descending")
|
|
if (err != nil) { return nil, err }
|
|
err = addAttributeSelectButton("Lifestyle", "DairyRating", "Descending")
|
|
if (err != nil) { return nil, err }
|
|
err = addAttributeSelectButton("Lifestyle", "SeafoodRating", "Descending")
|
|
if (err != nil) { return nil, err }
|
|
err = addAttributeSelectButton("Lifestyle", "BeefRating", "Descending")
|
|
if (err != nil) { return nil, err }
|
|
err = addAttributeSelectButton("Lifestyle", "PorkRating", "Descending")
|
|
if (err != nil) { return nil, err }
|
|
err = addAttributeSelectButton("Lifestyle", "PoultryRating", "Descending")
|
|
if (err != nil) { return nil, err }
|
|
err = addAttributeSelectButton("Lifestyle", "EggsRating", "Descending")
|
|
if (err != nil) { return nil, err }
|
|
err = addAttributeSelectButton("Lifestyle", "BeansRating", "Descending")
|
|
if (err != nil) { return nil, err }
|
|
|
|
err = addAttributeSelectButton("Lifestyle", "AlcoholFrequency", "Ascending")
|
|
if (err != nil) { return nil, err }
|
|
err = addAttributeSelectButton("Lifestyle", "TobaccoFrequency", "Ascending")
|
|
if (err != nil) { return nil, err }
|
|
err = addAttributeSelectButton("Lifestyle", "CannabisFrequency", "Ascending")
|
|
if (err != nil) { return nil, err }
|
|
|
|
mentalLabel := getBoldLabelCentered("Mental")
|
|
|
|
err = addAttributeSelectButton("Mental", "PetsRating", "Descending")
|
|
if (err != nil) { return nil, err }
|
|
err = addAttributeSelectButton("Mental", "CatsRating", "Descending")
|
|
if (err != nil) { return nil, err }
|
|
err = addAttributeSelectButton("Mental", "DogsRating", "Descending")
|
|
if (err != nil) { return nil, err }
|
|
|
|
generalAttributeButtonsGridCentered := getContainerCentered(generalAttributeButtonsGrid)
|
|
physicalAttributeButtonsGridCentered := getContainerCentered(physicalAttributeButtonsGrid)
|
|
lifestyleAttributeButtonsGridCentered := getContainerCentered(lifestyleAttributeButtonsGrid)
|
|
mentalAttributeButtonsGridCentered := getContainerCentered(mentalAttributeButtonsGrid)
|
|
|
|
pageContent := container.NewVBox(generalLabel, widget.NewSeparator(), generalAttributeButtonsGridCentered, widget.NewSeparator(), physicalLabel, widget.NewSeparator(), physicalAttributeButtonsGridCentered, widget.NewSeparator(), lifestyleLabel, widget.NewSeparator(), lifestyleAttributeButtonsGridCentered, widget.NewSeparator(), mentalLabel, widget.NewSeparator(), mentalAttributeButtonsGridCentered)
|
|
|
|
return pageContent, nil
|
|
}
|
|
|
|
pageContent, err := getPageContent()
|
|
if (err != nil){
|
|
setErrorEncounteredPage(window, err, previousPage)
|
|
return
|
|
}
|
|
|
|
page := container.NewVBox(title, backButton, widget.NewSeparator(), description, widget.NewSeparator(), pageContent)
|
|
|
|
setPageContent(page, window)
|
|
}
|
|
|
|
|
|
func setMyMatchStatisticsPage(window fyne.Window, previousPage func()){
|
|
|
|
pageIdentifier, err := helpers.GetNewRandomHexString(16)
|
|
if (err != nil) {
|
|
setErrorEncounteredPage(window, err, previousPage)
|
|
return
|
|
}
|
|
|
|
appMemory.SetMemoryEntry("CurrentViewedPage", pageIdentifier)
|
|
|
|
checkIfPageHasChangedFunction := func()bool{
|
|
exists, currentViewedPage := appMemory.GetMemoryEntry("CurrentViewedPage")
|
|
if (exists == true && currentViewedPage == pageIdentifier){
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
currentPage := func(){setMyMatchStatisticsPage(window, previousPage)}
|
|
|
|
title := getPageTitleCentered("My Match Statistics")
|
|
|
|
backButton := getBackButtonCentered(previousPage)
|
|
|
|
description := getLabelCentered("Below are statistics about your matches.")
|
|
|
|
accuracyWarningButton := getWidgetCentered(widget.NewButtonWithIcon("Statistics Warning", theme.WarningIcon(), func(){
|
|
setMateDesireStatisticsWarningPage(window, currentPage)
|
|
}))
|
|
|
|
totalMateUsersBinding := binding.NewString()
|
|
totalBlockedUsersBinding := binding.NewString()
|
|
numberOfMatchesBinding := binding.NewString()
|
|
matchPercentageBinding := binding.NewString()
|
|
|
|
totalMateUsersDescription := widget.NewLabel("Total Mate Users:")
|
|
totalMateUsersLabel := widget.NewLabelWithData(totalMateUsersBinding)
|
|
totalMateUsersLabel.TextStyle = getFyneTextStyle_Bold()
|
|
totalMateUsersRow := container.NewHBox(layout.NewSpacer(), totalMateUsersDescription, totalMateUsersLabel, layout.NewSpacer())
|
|
|
|
totalBlockedUsersDescription := widget.NewLabel("Total Blocked Users:")
|
|
totalBlockedUsersLabel := widget.NewLabelWithData(totalBlockedUsersBinding)
|
|
totalBlockedUsersLabel.TextStyle = getFyneTextStyle_Bold()
|
|
totalBlockedUsersRow := container.NewHBox(layout.NewSpacer(), totalBlockedUsersDescription, totalBlockedUsersLabel, layout.NewSpacer())
|
|
|
|
numberOfMatchesDescription := widget.NewLabel("Number of Matches:")
|
|
numberOfMatchesLabel := widget.NewLabelWithData(numberOfMatchesBinding)
|
|
numberOfMatchesLabel.TextStyle = getFyneTextStyle_Bold()
|
|
numberOfMatchesRow := container.NewHBox(layout.NewSpacer(), numberOfMatchesDescription, numberOfMatchesLabel, layout.NewSpacer())
|
|
|
|
matchPercentageDescription := widget.NewLabel("Match Percentage:")
|
|
matchPercentageLabel := widget.NewLabelWithData(matchPercentageBinding)
|
|
matchPercentageLabel.TextStyle = getFyneTextStyle_Bold()
|
|
matchPercentageRow := container.NewHBox(layout.NewSpacer(), matchPercentageDescription, matchPercentageLabel, layout.NewSpacer())
|
|
|
|
appNetworkType, err := getAppNetworkType.GetAppNetworkType()
|
|
if (err != nil) {
|
|
setErrorEncounteredPage(window, err, previousPage)
|
|
return
|
|
}
|
|
|
|
updateBindingsFunction := func(){
|
|
|
|
var resultsReadyBoolMutex sync.RWMutex
|
|
resultsReadyBool := false
|
|
|
|
updateBindingsWithLoadingText := func(){
|
|
|
|
secondsElapsed := 0
|
|
|
|
for{
|
|
|
|
resultsReadyBoolMutex.RLock()
|
|
resultsReady := resultsReadyBool
|
|
resultsReadyBoolMutex.RUnlock()
|
|
|
|
if (resultsReady == true){
|
|
return
|
|
}
|
|
pageHasChanged := checkIfPageHasChangedFunction()
|
|
if (pageHasChanged == true){
|
|
return
|
|
}
|
|
|
|
if (secondsElapsed % 3 == 0){
|
|
totalMateUsersBinding.Set("Loading.")
|
|
numberOfMatchesBinding.Set("Loading.")
|
|
matchPercentageBinding.Set("Loading.")
|
|
} else if (secondsElapsed %3 == 1){
|
|
totalMateUsersBinding.Set("Loading..")
|
|
numberOfMatchesBinding.Set("Loading..")
|
|
matchPercentageBinding.Set("Loading..")
|
|
} else {
|
|
totalMateUsersBinding.Set("Loading...")
|
|
numberOfMatchesBinding.Set("Loading...")
|
|
matchPercentageBinding.Set("Loading...")
|
|
}
|
|
|
|
time.Sleep(time.Second)
|
|
secondsElapsed += 1
|
|
}
|
|
}
|
|
|
|
go updateBindingsWithLoadingText()
|
|
|
|
updateBindingsWithResultFunction := func()error{
|
|
|
|
// We use below to make sure we do not count ourselves as a peer profile
|
|
myIdentityExists, myIdentityHash, err := myIdentity.GetMyIdentityHash("Mate")
|
|
if (err != nil) { return err }
|
|
|
|
mateIdentityHashesList, err := badgerDatabase.GetAllProfileIdentityHashes("Mate")
|
|
if (err != nil) { return err }
|
|
|
|
numberOfUsersWithEnabledViewableProfile := 0
|
|
numberOfBlockedUsers := 0
|
|
numberOfMatches := 0
|
|
|
|
for _, userIdentityHash := range mateIdentityHashesList{
|
|
|
|
if (myIdentityExists == true && userIdentityHash == myIdentityHash){
|
|
// We don't count ourselves as a potential match
|
|
continue
|
|
}
|
|
|
|
profileExists, _, getAnyUserProfileAttributeFunction, err := viewableProfiles.GetRetrieveAnyNewestViewableUserProfileAttributeFunction(userIdentityHash, appNetworkType, true, false, false)
|
|
if (err != nil) { return err }
|
|
if (profileExists == false) {
|
|
continue
|
|
}
|
|
|
|
exists, _, _, err := getAnyUserProfileAttributeFunction("Disabled")
|
|
if (err != nil) { return err }
|
|
if (exists == true){
|
|
// Profile is disabled
|
|
continue
|
|
}
|
|
|
|
numberOfUsersWithEnabledViewableProfile += 1
|
|
|
|
userIsBlocked, _, _, _, err := myBlockedUsers.CheckIfUserIsBlocked(userIdentityHash)
|
|
if (err != nil) { return err }
|
|
if (userIsBlocked == true){
|
|
numberOfBlockedUsers += 1
|
|
continue
|
|
}
|
|
|
|
passesMyDesires, err := myMateDesires.CheckIfMateProfilePassesAllMyDesires(false, "", getAnyUserProfileAttributeFunction)
|
|
if (err != nil) { return err }
|
|
if (passesMyDesires == true){
|
|
numberOfMatches += 1
|
|
}
|
|
}
|
|
|
|
resultsReadyBoolMutex.Lock()
|
|
resultsReadyBool = true
|
|
resultsReadyBoolMutex.Unlock()
|
|
|
|
getMatchPercentage := func()float64{
|
|
if (numberOfUsersWithEnabledViewableProfile == 0){
|
|
return 0
|
|
}
|
|
|
|
matchPercentage := (float64(numberOfMatches)/float64(numberOfUsersWithEnabledViewableProfile)) * 100
|
|
return matchPercentage
|
|
}
|
|
|
|
matchPercentage := getMatchPercentage()
|
|
|
|
totalUsersString := helpers.ConvertIntToString(numberOfUsersWithEnabledViewableProfile)
|
|
totalBlockedUsersString := helpers.ConvertIntToString(numberOfBlockedUsers)
|
|
numberOfMatchesString := helpers.ConvertIntToString(numberOfMatches)
|
|
matchPercentageString := helpers.ConvertFloat64ToStringRounded(matchPercentage, 1)
|
|
|
|
totalMateUsersBinding.Set(totalUsersString)
|
|
totalBlockedUsersBinding.Set(totalBlockedUsersString)
|
|
numberOfMatchesBinding.Set(numberOfMatchesString)
|
|
matchPercentageBinding.Set(matchPercentageString + "%")
|
|
|
|
return nil
|
|
}
|
|
|
|
err := updateBindingsWithResultFunction()
|
|
if (err != nil){
|
|
pageHasChanged := checkIfPageHasChangedFunction()
|
|
if (pageHasChanged == false){
|
|
setErrorEncounteredPage(window, err, previousPage)
|
|
}
|
|
}
|
|
}
|
|
|
|
viewAllDesireStatisticsButton := getWidgetCentered(widget.NewButtonWithIcon("View All My Desire Statistics", theme.VisibilityIcon(), func(){
|
|
setViewAllMyDesireStatisticsPage(window, false, 0, 0, nil, currentPage)
|
|
}))
|
|
|
|
page := container.NewVBox(title, backButton, widget.NewSeparator(), description, widget.NewSeparator(), accuracyWarningButton, widget.NewSeparator(), totalMateUsersRow, totalBlockedUsersRow, numberOfMatchesRow, matchPercentageRow, viewAllDesireStatisticsButton)
|
|
|
|
setPageContent(page, window)
|
|
|
|
go updateBindingsFunction()
|
|
}
|
|
|
|
|
|
func setCustomizeMatchDisplayPage(window fyne.Window, previousPage func()){
|
|
|
|
appMemory.SetMemoryEntry("CurrentViewedPage", "CustomizeMatchDisplay")
|
|
|
|
currentPage := func(){setCustomizeMatchDisplayPage(window, previousPage)}
|
|
|
|
title := getPageTitleCentered("Customize Match Display")
|
|
|
|
backButton := getBackButtonCentered(previousPage)
|
|
|
|
description1 := getLabelCentered("Select the attributes to show when browsing matches.")
|
|
description2 := getLabelCentered("A maximum of 5 attributes can be selected.")
|
|
|
|
getCustomDisplayAttributesList := func()([]string, error){
|
|
|
|
exists, currentAttributesListString, err := mySettings.GetSetting("CustomMatchDisplayAttributesList")
|
|
if (err != nil) { return nil, err }
|
|
if (exists == false){
|
|
emptyList := make([]string, 0)
|
|
return emptyList, nil
|
|
}
|
|
|
|
currentAttributesList := strings.Split(currentAttributesListString, ",")
|
|
return currentAttributesList, nil
|
|
}
|
|
|
|
customDisplayAttributesList, err := getCustomDisplayAttributesList()
|
|
if (err != nil){
|
|
setErrorEncounteredPage(window, err, previousPage)
|
|
return
|
|
}
|
|
|
|
addAttributeButton := getWidgetCentered(widget.NewButtonWithIcon("Add Attribute", theme.ContentAddIcon(), func(){
|
|
if (len(customDisplayAttributesList) >= 5){
|
|
dialogTitle := translate("Attribute Limit Reached.")
|
|
dialogMessageA := getLabelCentered("You can only select 5 attributes.")
|
|
dialogContent := container.NewVBox(dialogMessageA)
|
|
dialog.ShowCustom(dialogTitle, translate("Close"), dialogContent, window)
|
|
return
|
|
}
|
|
setAddAttributeToCustomMatchDisplayPage(window, currentPage, currentPage)
|
|
}))
|
|
|
|
if (len(customDisplayAttributesList) == 0){
|
|
|
|
noAttributesSelectedLabel := getBoldLabelCentered("No Attributes Selected")
|
|
|
|
page := container.NewVBox(title, backButton, widget.NewSeparator(), description1, description2, widget.NewSeparator(), noAttributesSelectedLabel, addAttributeButton)
|
|
|
|
setPageContent(page, window)
|
|
return
|
|
}
|
|
|
|
currentAttributesLabel := getItalicLabelCentered("Current Attributes:")
|
|
|
|
getCurrentAttributesGrid := func()(*fyne.Container, error){
|
|
|
|
attributeIndexesColumn := container.NewVBox()
|
|
attributeTitlesColumn := container.NewVBox()
|
|
attributeRemoveButtonsColumn := container.NewVBox()
|
|
|
|
for index, attributeName := range customDisplayAttributesList{
|
|
|
|
attributeIndexString := helpers.ConvertIntToString(index+1) + "."
|
|
|
|
attributeTitle, _, _, _, _, err := attributeDisplay.GetProfileAttributeDisplayInfo(attributeName)
|
|
if (err != nil) { return nil, err }
|
|
|
|
attributeIndexLabel := getBoldLabelCentered(attributeIndexString)
|
|
attributeTitleLabel := getBoldLabelCentered(attributeTitle)
|
|
|
|
deleteAttributeButton := widget.NewButtonWithIcon("", theme.DeleteIcon(), func(){
|
|
|
|
newAttributesList, _ := helpers.DeleteAllMatchingItemsFromList(customDisplayAttributesList, attributeName)
|
|
|
|
if (len(newAttributesList) == 0){
|
|
|
|
err := mySettings.DeleteSetting("CustomMatchDisplayAttributesList")
|
|
if (err != nil) {
|
|
setErrorEncounteredPage(window, err, currentPage)
|
|
return
|
|
}
|
|
|
|
currentPage()
|
|
return
|
|
}
|
|
|
|
newAttributesListString := strings.Join(newAttributesList, ",")
|
|
|
|
err := mySettings.SetSetting("CustomMatchDisplayAttributesList", newAttributesListString)
|
|
if (err != nil) {
|
|
setErrorEncounteredPage(window, err, currentPage)
|
|
return
|
|
}
|
|
|
|
currentPage()
|
|
})
|
|
|
|
attributeIndexesColumn.Add(attributeIndexLabel)
|
|
attributeTitlesColumn.Add(attributeTitleLabel)
|
|
attributeRemoveButtonsColumn.Add(deleteAttributeButton)
|
|
|
|
attributeIndexesColumn.Add(widget.NewSeparator())
|
|
attributeTitlesColumn.Add(widget.NewSeparator())
|
|
attributeRemoveButtonsColumn.Add(widget.NewSeparator())
|
|
}
|
|
|
|
attributesGrid := container.NewHBox(layout.NewSpacer(), attributeIndexesColumn, attributeTitlesColumn, attributeRemoveButtonsColumn, layout.NewSpacer())
|
|
|
|
return attributesGrid, nil
|
|
}
|
|
|
|
currentAttributesGrid, err := getCurrentAttributesGrid()
|
|
if (err != nil){
|
|
setErrorEncounteredPage(window, err, previousPage)
|
|
return
|
|
}
|
|
|
|
page := container.NewVBox(title, backButton, widget.NewSeparator(), description1, description2, widget.NewSeparator(), addAttributeButton, widget.NewSeparator(), currentAttributesLabel, currentAttributesGrid)
|
|
|
|
setPageContent(page, window)
|
|
}
|
|
|
|
func setAddAttributeToCustomMatchDisplayPage(window fyne.Window, previousPage func(), nextPage func()){
|
|
|
|
currentPage := func(){setAddAttributeToCustomMatchDisplayPage(window, previousPage, nextPage)}
|
|
|
|
title := getPageTitleCentered("Add Attribute")
|
|
|
|
backButton := getBackButtonCentered(previousPage)
|
|
|
|
description := getLabelCentered("Choose the attribute to display.")
|
|
|
|
getPageContent := func()(*fyne.Container, error){
|
|
|
|
getCustomDisplayAttributesList := func()([]string, error){
|
|
|
|
exists, currentAttributesListString, err := mySettings.GetSetting("CustomMatchDisplayAttributesList")
|
|
if (err != nil) { return nil, err }
|
|
if (exists == false){
|
|
emptyList := make([]string, 0)
|
|
return emptyList, nil
|
|
}
|
|
currentAttributesList := strings.Split(currentAttributesListString, ",")
|
|
return currentAttributesList, nil
|
|
}
|
|
|
|
customDisplayAttributesList, err := getCustomDisplayAttributesList()
|
|
if (err != nil){ return nil, err }
|
|
|
|
if (len(customDisplayAttributesList) >= 5){
|
|
return nil, errors.New("setAddAttributeToCustomMatchDisplayPage called when attributesList is full.")
|
|
}
|
|
|
|
generalAttributeButtonsGrid := container.NewGridWithColumns(1)
|
|
physicalAttributeButtonsGrid := container.NewGridWithColumns(1)
|
|
lifestyleAttributeButtonsGrid := container.NewGridWithColumns(1)
|
|
mentalAttributeButtonsGrid := container.NewGridWithColumns(1)
|
|
|
|
addAttributeButton := func(attributeName string, attributeType string)error{
|
|
|
|
isSelected := slices.Contains(customDisplayAttributesList, attributeName)
|
|
if (isSelected == true){
|
|
// Attribute has already been selected
|
|
// We will not show it
|
|
return nil
|
|
}
|
|
|
|
attributeTitle, _, _, _, _, err := attributeDisplay.GetProfileAttributeDisplayInfo(attributeName)
|
|
if (err != nil) { return err }
|
|
|
|
attributeButton := widget.NewButton(attributeTitle, func(){
|
|
|
|
newAttributesList := append(customDisplayAttributesList, attributeName)
|
|
|
|
newAttributesListString := strings.Join(newAttributesList, ",")
|
|
|
|
err := mySettings.SetSetting("CustomMatchDisplayAttributesList", newAttributesListString)
|
|
if (err != nil) {
|
|
setErrorEncounteredPage(window, err, currentPage)
|
|
return
|
|
}
|
|
nextPage()
|
|
})
|
|
|
|
if (attributeType == "General"){
|
|
|
|
generalAttributeButtonsGrid.Add(attributeButton)
|
|
|
|
} else if (attributeType == "Physical"){
|
|
|
|
physicalAttributeButtonsGrid.Add(attributeButton)
|
|
|
|
} else if (attributeType == "Lifestyle"){
|
|
|
|
lifestyleAttributeButtonsGrid.Add(attributeButton)
|
|
|
|
} else if (attributeType == "Mental"){
|
|
|
|
mentalAttributeButtonsGrid.Add(attributeButton)
|
|
|
|
} else {
|
|
return errors.New("addAttributeButton called with invalid attributeType: " + attributeType)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
generalAttributeNamesList := []string{
|
|
"MatchScore",
|
|
"Username",
|
|
"Sexuality",
|
|
"Distance",
|
|
"HasMessagedMe",
|
|
"IHaveMessaged",
|
|
"HasRejectedMe",
|
|
"IsLiked",
|
|
"IsMyContact",
|
|
"SearchTermsCount",
|
|
"PrimaryLocationCountry",
|
|
}
|
|
|
|
physicalAttributeNamesList := []string{
|
|
"Age",
|
|
"Height",
|
|
"Sex",
|
|
"HairColor",
|
|
"HairTexture",
|
|
"EyeColor",
|
|
"SkinColor",
|
|
"RacialSimilarity",
|
|
"HasHIV",
|
|
"HasGenitalHerpes",
|
|
"BodyFat",
|
|
"BodyMuscle",
|
|
"23andMe_MaternalHaplogroup",
|
|
"23andMe_PaternalHaplogroup",
|
|
"23andMe_NeanderthalVariants",
|
|
"EyeColorSimilarity",
|
|
"EyeColorGenesSimilarity",
|
|
"HairColorSimilarity",
|
|
"HairColorGenesSimilarity",
|
|
"SkinColorSimilarity",
|
|
"SkinColorGenesSimilarity",
|
|
"HairTextureSimilarity",
|
|
"HairTextureGenesSimilarity",
|
|
"FacialStructureGenesSimilarity",
|
|
"23andMe_AncestralSimilarity",
|
|
"23andMe_MaternalHaplogroupSimilarity",
|
|
"23andMe_PaternalHaplogroupSimilarity",
|
|
"OffspringProbabilityOfAnyMonogenicDisease",
|
|
"TotalPolygenicDiseaseRiskScore",
|
|
"OffspringTotalPolygenicDiseaseRiskScore",
|
|
"AutismRiskScore",
|
|
"OffspringAutismRiskScore",
|
|
"ObesityRiskScore",
|
|
"OffspringObesityRiskScore",
|
|
"PredictedEyeColor",
|
|
"OffspringBlueEyesProbability",
|
|
"OffspringGreenEyesProbability",
|
|
"OffspringHazelEyesProbability",
|
|
"OffspringBrownEyesProbability",
|
|
"PredictedLactoseTolerance",
|
|
"OffspringLactoseToleranceProbability",
|
|
"PredictedHairTexture",
|
|
"OffspringStraightHairProbability",
|
|
"OffspringCurlyHairProbability",
|
|
"HomosexualnessScore",
|
|
"OffspringHomosexualnessScore",
|
|
"PredictedHeight",
|
|
"OffspringPredictedHeight",
|
|
}
|
|
|
|
lifestyleAttributeNamesList := []string{
|
|
"Fame",
|
|
"WealthInGold",
|
|
"AlcoholFrequency",
|
|
"TobaccoFrequency",
|
|
"CannabisFrequency",
|
|
"FruitRating",
|
|
"VegetablesRating",
|
|
"NutsRating",
|
|
"GrainsRating",
|
|
"DairyRating",
|
|
"SeafoodRating",
|
|
"BeefRating",
|
|
"PorkRating",
|
|
"PoultryRating",
|
|
"EggsRating",
|
|
"BeansRating",
|
|
}
|
|
|
|
mentalAttributeNamesList := []string{
|
|
"GenderIdentity",
|
|
"PetsRating",
|
|
"DogsRating",
|
|
"CatsRating",
|
|
}
|
|
|
|
for _, attributeName := range generalAttributeNamesList{
|
|
|
|
err = addAttributeButton(attributeName, "General")
|
|
if (err != nil) { return nil, err }
|
|
}
|
|
|
|
for _, attributeName := range physicalAttributeNamesList{
|
|
|
|
err = addAttributeButton(attributeName, "Physical")
|
|
if (err != nil) { return nil, err }
|
|
}
|
|
|
|
for _, attributeName := range lifestyleAttributeNamesList{
|
|
|
|
err = addAttributeButton(attributeName, "Lifestyle")
|
|
if (err != nil) { return nil, err }
|
|
}
|
|
|
|
for _, attributeName := range mentalAttributeNamesList{
|
|
|
|
err = addAttributeButton(attributeName, "Mental")
|
|
if (err != nil) { return nil, err }
|
|
}
|
|
|
|
|
|
generalLabel := getBoldLabelCentered("General")
|
|
physicalLabel := getBoldLabelCentered("Physical")
|
|
lifestyleLabel := getBoldLabelCentered("Lifestyle")
|
|
mentalLabel := getBoldLabelCentered("Mental")
|
|
|
|
generalAttributeButtonsGridCentered := getContainerCentered(generalAttributeButtonsGrid)
|
|
physicalAttributeButtonsGridCentered := getContainerCentered(physicalAttributeButtonsGrid)
|
|
lifestyleAttributeButtonsGridCentered := getContainerCentered(lifestyleAttributeButtonsGrid)
|
|
mentalAttributeButtonsGridCentered := getContainerCentered(mentalAttributeButtonsGrid)
|
|
|
|
pageContent := container.NewVBox(generalLabel, widget.NewSeparator(), generalAttributeButtonsGridCentered, widget.NewSeparator(), physicalLabel, widget.NewSeparator(), physicalAttributeButtonsGridCentered, widget.NewSeparator(), lifestyleLabel, widget.NewSeparator(), lifestyleAttributeButtonsGridCentered, widget.NewSeparator(), mentalLabel, widget.NewSeparator(), mentalAttributeButtonsGridCentered)
|
|
|
|
return pageContent, nil
|
|
}
|
|
|
|
pageContent, err := getPageContent()
|
|
if (err != nil){
|
|
setErrorEncounteredPage(window, err, previousPage)
|
|
return
|
|
}
|
|
|
|
page := container.NewVBox(title, backButton, widget.NewSeparator(), description, widget.NewSeparator(), pageContent)
|
|
|
|
setPageContent(page, window)
|
|
}
|
|
|
|
|
|
func setConfigureMatchScorePage(window fyne.Window, previousPage func()){
|
|
|
|
setLoadingScreen(window, "Configure Match Score", "Loading Configure Match Score page...")
|
|
|
|
currentPage := func(){setConfigureMatchScorePage(window, previousPage)}
|
|
|
|
title := getPageTitleCentered("Configure Match Score")
|
|
|
|
backButton := getBackButtonCentered(previousPage)
|
|
|
|
description1 := getLabelCentered("Customize how a user's match score is calculated.")
|
|
description2 := getLabelCentered("Each desire's points will be added to a user's match score if they fulfills the desire.")
|
|
description3 := getLabelCentered("Increase the Point value for desires that are more important to you.")
|
|
|
|
viewMatchScoreDistributionButton := getWidgetCentered(widget.NewButtonWithIcon("View Match Score Distribution", theme.VisibilityIcon(), func(){
|
|
setViewUserAttributeStatisticsPage_BarChart(window, "Mate", "MatchScore", "Number Of Users", " users", true, false, false, nil, false, nil, nil, currentPage)
|
|
}))
|
|
|
|
//TODO: Split into multiple pages and add Navigation buttons
|
|
|
|
getDesirePointsGrid := func()(*fyne.Container, error){
|
|
|
|
desireNameLabel := getItalicLabelCentered("Desire Name")
|
|
pointsLabel := getItalicLabelCentered("Points")
|
|
emptyLabel := widget.NewLabel("")
|
|
|
|
desireTitleColumn := container.NewVBox(desireNameLabel, widget.NewSeparator())
|
|
desirePointsColumn := container.NewVBox(pointsLabel, widget.NewSeparator())
|
|
editPointsButtonsColumn := container.NewVBox(emptyLabel, widget.NewSeparator())
|
|
|
|
allMyDesiresList := myMateDesires.GetAllMyDesiresList(false)
|
|
|
|
for _, desireName := range allMyDesiresList{
|
|
|
|
desireTitle, err := mateDesires.GetDesireTitleFromDesireName(desireName)
|
|
if (err != nil) { return nil, err }
|
|
|
|
desireTitleTranslated := translate(desireTitle)
|
|
|
|
desireTitleLabel := getBoldLabelCentered(desireTitleTranslated)
|
|
|
|
desirePoints, err := myMatchScore.GetMyMatchScoreDesirePoints(desireName)
|
|
if (err != nil) { return nil, err }
|
|
|
|
desirePointsString := helpers.ConvertIntToString(desirePoints)
|
|
desirePointsLabel := getBoldLabelCentered(desirePointsString)
|
|
|
|
editPointsButton := widget.NewButtonWithIcon("", theme.DocumentCreateIcon(), func(){
|
|
setEditMatchScoreDesirePointsPage(window, desireName, currentPage)
|
|
})
|
|
|
|
desireTitleColumn.Add(desireTitleLabel)
|
|
desirePointsColumn.Add(desirePointsLabel)
|
|
editPointsButtonsColumn.Add(editPointsButton)
|
|
|
|
desireTitleColumn.Add(widget.NewSeparator())
|
|
desirePointsColumn.Add(widget.NewSeparator())
|
|
editPointsButtonsColumn.Add(widget.NewSeparator())
|
|
}
|
|
|
|
desirePointsGrid := container.NewHBox(layout.NewSpacer(), desireTitleColumn, desirePointsColumn, editPointsButtonsColumn, layout.NewSpacer())
|
|
return desirePointsGrid, nil
|
|
}
|
|
|
|
desirePointsGrid, err := getDesirePointsGrid()
|
|
if (err != nil) {
|
|
setErrorEncounteredPage(window, err, previousPage)
|
|
return
|
|
}
|
|
|
|
page := container.NewVBox(title, backButton, widget.NewSeparator(), description1, description2, description3, widget.NewSeparator(), viewMatchScoreDistributionButton, widget.NewSeparator(), desirePointsGrid)
|
|
|
|
setPageContent(page, window)
|
|
}
|
|
|
|
|
|
func setEditMatchScoreDesirePointsPage(window fyne.Window, desireName string, previousPage func()){
|
|
|
|
currentPage := func(){setEditMatchScoreDesirePointsPage(window, desireName, previousPage)}
|
|
|
|
title := getPageTitleCentered("Edit Attribute Points")
|
|
|
|
backButton := getBackButtonCentered(previousPage)
|
|
|
|
description1 := getLabelCentered("Edit your desire's points.")
|
|
description2 := getLabelCentered("These will be added to a user's match score if they fulfill the desire.")
|
|
|
|
desireTitle, err := mateDesires.GetDesireTitleFromDesireName(desireName)
|
|
if (err != nil) {
|
|
setErrorEncounteredPage(window, err, previousPage)
|
|
return
|
|
}
|
|
|
|
desireNameLabel := widget.NewLabel("Desire Name:")
|
|
desireTitleLabel := getBoldLabel(desireTitle)
|
|
desireTitleRow := container.NewHBox(layout.NewSpacer(), desireNameLabel, desireTitleLabel, layout.NewSpacer())
|
|
|
|
desirePoints, err := myMatchScore.GetMyMatchScoreDesirePoints(desireName)
|
|
if (err != nil) {
|
|
setErrorEncounteredPage(window, err, previousPage)
|
|
return
|
|
}
|
|
|
|
desirePointsString := helpers.ConvertIntToString(desirePoints)
|
|
|
|
desirePointsTitle := getBoldLabelCentered("Desire Points:")
|
|
|
|
desirePointsLabel := getBoldLabelCentered(desirePointsString)
|
|
|
|
getDecreasePointsButton := func()fyne.Widget{
|
|
|
|
if (desirePoints > 1){
|
|
decreaseButton := widget.NewButton("-", func(){
|
|
err := myMatchScore.SetMyMatchScoreDesirePoints(desireName, desirePoints-1)
|
|
if (err != nil) {
|
|
setErrorEncounteredPage(window, err, currentPage)
|
|
return
|
|
}
|
|
currentPage()
|
|
})
|
|
return decreaseButton
|
|
}
|
|
|
|
emptyButton := widget.NewButton("", nil)
|
|
|
|
return emptyButton
|
|
}
|
|
|
|
getIncreasePointsButton := func()fyne.Widget{
|
|
|
|
if (desirePoints < 100){
|
|
increaseButton := widget.NewButton("+", func(){
|
|
err := myMatchScore.SetMyMatchScoreDesirePoints(desireName, desirePoints+1)
|
|
if (err != nil) {
|
|
setErrorEncounteredPage(window, err, currentPage)
|
|
return
|
|
}
|
|
currentPage()
|
|
})
|
|
return increaseButton
|
|
}
|
|
emptyButton := widget.NewButton("", nil)
|
|
return emptyButton
|
|
}
|
|
|
|
decreasePointsButton := getDecreasePointsButton()
|
|
increasePointsButton := getIncreasePointsButton()
|
|
|
|
decreaseIncreaseButtons := getContainerCentered(container.NewGridWithColumns(2, decreasePointsButton, increasePointsButton))
|
|
|
|
page := container.NewVBox(title, backButton, widget.NewSeparator(), description1, description2, widget.NewSeparator(), desireTitleRow, widget.NewSeparator(), desirePointsTitle, desirePointsLabel, decreaseIncreaseButtons)
|
|
|
|
setPageContent(page, window)
|
|
}
|
|
|
|
|
|
// This page will explain a user's match score by describing which desires the user passes
|
|
func setViewUserMatchScoreBreakdownPage(window fyne.Window, userIdentityHash [16]byte, previousPage func()){
|
|
|
|
userIdentityType, err := identity.GetIdentityTypeFromIdentityHash(userIdentityHash)
|
|
if (err != nil){
|
|
userIdentityHashHex := encoding.EncodeBytesToHexString(userIdentityHash[:])
|
|
setErrorEncounteredPage(window, errors.New("setViewUserMatchScoreBreakdownPage called with invalid userIdentityHash: " + userIdentityHashHex), previousPage)
|
|
return
|
|
}
|
|
if (userIdentityType != "Mate"){
|
|
setErrorEncounteredPage(window, errors.New("setViewUserMatchScoreBreakdownPage called with non-mate identity hash."), previousPage)
|
|
return
|
|
}
|
|
|
|
currentPage := func(){setViewUserMatchScoreBreakdownPage(window, userIdentityHash, previousPage)}
|
|
|
|
title := getPageTitleCentered("User Match Score Breakdown")
|
|
|
|
backButton := getBackButtonCentered(previousPage)
|
|
|
|
appNetworkType, err := getAppNetworkType.GetAppNetworkType()
|
|
if (err != nil){
|
|
setErrorEncounteredPage(window, err, previousPage)
|
|
return
|
|
}
|
|
|
|
profileExists, _, getAnyUserProfileAttributeFunction, err := viewableProfiles.GetRetrieveAnyNewestViewableUserProfileAttributeFunction(userIdentityHash, appNetworkType, true, false, true)
|
|
if (err != nil) {
|
|
setErrorEncounteredPage(window, err, previousPage)
|
|
return
|
|
}
|
|
if (profileExists == false) {
|
|
// Profile must have been deleted or it is not viewable
|
|
description1 := getBoldLabelCentered("User's profile is not found.")
|
|
description2 := getLabelCentered("Thus, the user's match score breakdown cannot be shown.")
|
|
description3 := getLabelCentered("Their profile was either banned or deleted.")
|
|
description4 := getLabelCentered("Deletion should only happen if the user is no longer a match.")
|
|
|
|
page := container.NewVBox(title, backButton, widget.NewSeparator(), description1, description2, description3, description4)
|
|
|
|
setPageContent(page, window)
|
|
return
|
|
}
|
|
|
|
exists, _, userIsDisabled, err := getAnyUserProfileAttributeFunction("Disabled")
|
|
if (err != nil) {
|
|
setErrorEncounteredPage(window, err, previousPage)
|
|
return
|
|
}
|
|
if (exists == true && userIsDisabled == "Yes"){
|
|
// User's newest viewable profile is disabled.
|
|
description1 := getBoldLabelCentered("User's profile is disabled.")
|
|
description2 := getLabelCentered("Thus, the user's match score breakdown cannot be shown.")
|
|
|
|
page := container.NewVBox(title, backButton, widget.NewSeparator(), description1, description2)
|
|
|
|
setPageContent(page, window)
|
|
return
|
|
}
|
|
|
|
// This bool will track if we have any desires at all
|
|
anyPreferenceExists := false
|
|
|
|
userMatchScore := 0
|
|
|
|
// This map stores the number of points we added for each desire
|
|
// Map Structure: Desire name -> Points we added
|
|
desirePointsMap := make(map[string]int)
|
|
|
|
// This is a list of desires which the user fulfills
|
|
fulfilledDesiresList := make([]string, 0)
|
|
|
|
// This is a list of desires which the user does not fulfill
|
|
unfulfilledDesiresList := make([]string, 0)
|
|
|
|
// This is a list of desires for which we do not know if the user fulfills our preference, not caused by them not responding
|
|
unknownStatusDesiresList := make([]string, 0)
|
|
|
|
// This is a list of desires for which the user has no response
|
|
noResponseExistsDesiresList := make([]string, 0)
|
|
|
|
// This is a list of desires which we have no preference for
|
|
noPreferenceExistsDesiresList := make([]string, 0)
|
|
|
|
allMyDesiresList := myMateDesires.GetAllMyDesiresList(false)
|
|
|
|
for _, desireName := range allMyDesiresList{
|
|
|
|
myDesireExists, statusIsKnown, userFulfillsDesire, err := myMateDesires.CheckIfMateProfileFulfillsMyDesire(desireName, getAnyUserProfileAttributeFunction)
|
|
if (err != nil){
|
|
setErrorEncounteredPage(window, err, previousPage)
|
|
return
|
|
}
|
|
if (myDesireExists == false){
|
|
|
|
noPreferenceExistsDesiresList = append(noPreferenceExistsDesiresList, desireName)
|
|
continue
|
|
}
|
|
|
|
anyPreferenceExists = true
|
|
|
|
if (statusIsKnown == false){
|
|
|
|
noResponseIsPossible, _ := mateDesires.CheckIfDesireAllowsRequireResponse(desireName)
|
|
if (noResponseIsPossible == false){
|
|
// Whether or not the user responded does not effect the desire's status is known status
|
|
// An example is OffspringProbabilityOfAnyMonogenicDisease, which requires information from us *and* the user
|
|
unknownStatusDesiresList = append(unknownStatusDesiresList, desireName)
|
|
continue
|
|
}
|
|
noResponseExistsDesiresList = append(noResponseExistsDesiresList, desireName)
|
|
continue
|
|
}
|
|
|
|
if (userFulfillsDesire == false){
|
|
|
|
unfulfilledDesiresList = append(unfulfilledDesiresList, desireName)
|
|
continue
|
|
}
|
|
|
|
fulfilledDesiresList = append(fulfilledDesiresList, desireName)
|
|
|
|
pointsToAdd, err := myMatchScore.GetMyMatchScoreDesirePoints(desireName)
|
|
if (err != nil){
|
|
setErrorEncounteredPage(window, err, previousPage)
|
|
return
|
|
}
|
|
|
|
desirePointsMap[desireName] += pointsToAdd
|
|
|
|
userMatchScore += pointsToAdd
|
|
}
|
|
|
|
if (anyPreferenceExists == false){
|
|
|
|
description1 := getBoldLabelCentered("You have not added any desires.")
|
|
description2 := getLabelCentered("Thus, the match score for all users will be 0.")
|
|
description3 := getLabelCentered("Visit the Desires page to enter some desires.")
|
|
|
|
page := container.NewVBox(title, backButton, widget.NewSeparator(), description1, description2, description3)
|
|
|
|
setPageContent(page, window)
|
|
return
|
|
}
|
|
|
|
matchScoreTitle := widget.NewLabel("User Match Score:")
|
|
|
|
matchScoreString := helpers.ConvertIntToString(userMatchScore)
|
|
|
|
matchScoreLabel := getBoldLabel(matchScoreString)
|
|
|
|
matchScoreRow := container.NewHBox(layout.NewSpacer(), matchScoreTitle, matchScoreLabel, layout.NewSpacer())
|
|
|
|
getMatchScoreBreakdownGrid := func()(*fyne.Container, error){
|
|
|
|
desireNameHeader := getItalicLabelCentered("Desire Name")
|
|
userFulfillsDesireHeader := getItalicLabelCentered("User Fulfills Desire")
|
|
pointsAddedHeader := getItalicLabelCentered("Points Added")
|
|
|
|
desireNameColumn := container.NewVBox(desireNameHeader, widget.NewSeparator())
|
|
userFulfillsDesireColumn := container.NewVBox(userFulfillsDesireHeader, widget.NewSeparator())
|
|
pointsAddedColumn := container.NewVBox(pointsAddedHeader, widget.NewSeparator())
|
|
|
|
for _, desireName := range fulfilledDesiresList{
|
|
|
|
desireTitle, err := mateDesires.GetDesireTitleFromDesireName(desireName)
|
|
if (err != nil) { return nil, err }
|
|
|
|
desireTitleLabel := getBoldLabelCentered(desireTitle)
|
|
|
|
userFulfillsDesireLabel := getBoldLabelCentered(translate("Yes"))
|
|
|
|
pointsAdded, exists := desirePointsMap[desireName]
|
|
if (exists == false){
|
|
return nil, errors.New("desirePointsMap missing desire: " + desireName)
|
|
}
|
|
|
|
pointsAddedString := helpers.ConvertIntToString(pointsAdded)
|
|
pointsAddedLabel := getBoldLabelCentered("+" + pointsAddedString)
|
|
|
|
desireNameColumn.Add(desireTitleLabel)
|
|
userFulfillsDesireColumn.Add(userFulfillsDesireLabel)
|
|
pointsAddedColumn.Add(pointsAddedLabel)
|
|
|
|
desireNameColumn.Add(widget.NewSeparator())
|
|
userFulfillsDesireColumn.Add(widget.NewSeparator())
|
|
pointsAddedColumn.Add(widget.NewSeparator())
|
|
}
|
|
|
|
for _, desireName := range unfulfilledDesiresList{
|
|
|
|
desireTitle, err := mateDesires.GetDesireTitleFromDesireName(desireName)
|
|
if (err != nil) { return nil, err }
|
|
|
|
desireTitleLabel := getBoldLabelCentered(desireTitle)
|
|
|
|
userFulfillsDesireLabel := getBoldLabelCentered(translate("No"))
|
|
|
|
pointsAddedLabel := getBoldLabelCentered("0")
|
|
|
|
desireNameColumn.Add(desireTitleLabel)
|
|
userFulfillsDesireColumn.Add(userFulfillsDesireLabel)
|
|
pointsAddedColumn.Add(pointsAddedLabel)
|
|
|
|
desireNameColumn.Add(widget.NewSeparator())
|
|
userFulfillsDesireColumn.Add(widget.NewSeparator())
|
|
pointsAddedColumn.Add(widget.NewSeparator())
|
|
}
|
|
|
|
for _, desireName := range unknownStatusDesiresList{
|
|
|
|
desireTitle, err := mateDesires.GetDesireTitleFromDesireName(desireName)
|
|
if (err != nil) { return nil, err }
|
|
|
|
desireTitleLabel := getBoldLabelCentered(desireTitle)
|
|
|
|
userFulfillsDesireLabel := getItalicLabelCentered(translate("Unknown"))
|
|
|
|
pointsAddedLabel := getBoldLabelCentered("0")
|
|
|
|
desireNameColumn.Add(desireTitleLabel)
|
|
userFulfillsDesireColumn.Add(userFulfillsDesireLabel)
|
|
pointsAddedColumn.Add(pointsAddedLabel)
|
|
|
|
desireNameColumn.Add(widget.NewSeparator())
|
|
userFulfillsDesireColumn.Add(widget.NewSeparator())
|
|
pointsAddedColumn.Add(widget.NewSeparator())
|
|
}
|
|
|
|
for _, desireName := range noResponseExistsDesiresList{
|
|
|
|
desireTitle, err := mateDesires.GetDesireTitleFromDesireName(desireName)
|
|
if (err != nil) { return nil, err }
|
|
|
|
desireTitleLabel := getBoldLabelCentered(desireTitle)
|
|
|
|
userFulfillsDesireLabel := getItalicLabelCentered(translate("No Response"))
|
|
|
|
pointsAddedLabel := getBoldLabelCentered("0")
|
|
|
|
desireNameColumn.Add(desireTitleLabel)
|
|
userFulfillsDesireColumn.Add(userFulfillsDesireLabel)
|
|
pointsAddedColumn.Add(pointsAddedLabel)
|
|
|
|
desireNameColumn.Add(widget.NewSeparator())
|
|
userFulfillsDesireColumn.Add(widget.NewSeparator())
|
|
pointsAddedColumn.Add(widget.NewSeparator())
|
|
}
|
|
|
|
matchScoreBreakdownGrid := container.NewHBox(layout.NewSpacer(), desireNameColumn, userFulfillsDesireColumn, pointsAddedColumn, layout.NewSpacer())
|
|
|
|
return matchScoreBreakdownGrid, nil
|
|
}
|
|
|
|
matchScoreBreakdownGrid, err := getMatchScoreBreakdownGrid()
|
|
if (err != nil){
|
|
setErrorEncounteredPage(window, err, previousPage)
|
|
return
|
|
}
|
|
|
|
page := container.NewVBox(title, backButton, widget.NewSeparator(), matchScoreRow, widget.NewSeparator(), matchScoreBreakdownGrid)
|
|
|
|
numberOfNoPreferenceDesires := len(noPreferenceExistsDesiresList)
|
|
|
|
if (numberOfNoPreferenceDesires != 0){
|
|
|
|
numberOfNoPreferenceDesiresString := helpers.ConvertIntToString(numberOfNoPreferenceDesires)
|
|
|
|
description1 := getLabelCentered("You have " + numberOfNoPreferenceDesiresString + " desires with no preference.")
|
|
description2 := getLabelCentered("These desires will have no impact on match scores.")
|
|
|
|
viewMyNoPreferenceDesiresButton := getWidgetCentered(widget.NewButtonWithIcon("View My No Preference Desires", theme.VisibilityIcon(), func(){
|
|
setViewMyNoPreferenceDesiresPage(window, noPreferenceExistsDesiresList, currentPage)
|
|
}))
|
|
|
|
page.Add(widget.NewSeparator())
|
|
page.Add(description1)
|
|
page.Add(description2)
|
|
page.Add(viewMyNoPreferenceDesiresButton)
|
|
}
|
|
|
|
setPageContent(page, window)
|
|
}
|
|
|
|
|
|
func setViewMyNoPreferenceDesiresPage(window fyne.Window, myNoPreferenceDesiresList []string, previousPage func()){
|
|
|
|
title := getPageTitleCentered("My No Preference Desires")
|
|
|
|
backButton := getBackButtonCentered(previousPage)
|
|
|
|
description := getLabelCentered("Below is a list of your desires for which you have no provided no preference.")
|
|
|
|
page := container.NewVBox(title, backButton, widget.NewSeparator(), description, widget.NewSeparator())
|
|
|
|
for _, desireName := range myNoPreferenceDesiresList{
|
|
|
|
desireTitle, err := mateDesires.GetDesireTitleFromDesireName(desireName)
|
|
if (err != nil) {
|
|
setErrorEncounteredPage(window, err, previousPage)
|
|
return
|
|
}
|
|
|
|
desireTitleLabel := getBoldLabelCentered(desireTitle)
|
|
|
|
page.Add(desireTitleLabel)
|
|
}
|
|
|
|
setPageContent(page, window)
|
|
}
|
|
|
|
|