2024-04-11 15:51:56 +02:00
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 , "," )
2024-08-11 14:31:40 +02:00
displayAttributesListPruned , _ := helpers . DeleteAllMatchingItemsFromList ( currentAttributesList , currentSortByAttribute )
2024-04-11 15:51:56 +02:00
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 }
2024-08-14 13:04:19 +02:00
err = addAttributeSelectButton ( "Physical" , "AutismRiskScore" , "Ascending" )
if ( err != nil ) { return nil , err }
err = addAttributeSelectButton ( "Physical" , "OffspringAutismRiskScore" , "Ascending" )
if ( err != nil ) { return nil , err }
2024-04-11 15:51:56 +02:00
2024-08-14 13:04:19 +02:00
err = addAttributeSelectButton ( "Physical" , "ObesityRiskScore" , "Ascending" )
if ( err != nil ) { return nil , err }
err = addAttributeSelectButton ( "Physical" , "OffspringObesityRiskScore" , "Ascending" )
if ( err != nil ) { return nil , err }
2024-04-11 15:51:56 +02:00
2024-08-14 13:04:19 +02:00
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 }
2024-04-11 15:51:56 +02:00
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 ( ) {
2024-08-11 14:31:40 +02:00
newAttributesList , _ := helpers . DeleteAllMatchingItemsFromList ( customDisplayAttributesList , attributeName )
2024-04-11 15:51:56 +02:00
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" ,
2024-08-14 13:04:19 +02:00
"OffspringProbabilityOfAnyMonogenicDisease" ,
"TotalPolygenicDiseaseRiskScore" ,
"OffspringTotalPolygenicDiseaseRiskScore" ,
"AutismRiskScore" ,
"OffspringAutismRiskScore" ,
"ObesityRiskScore" ,
"OffspringObesityRiskScore" ,
"PredictedEyeColor" ,
"OffspringBlueEyesProbability" ,
"OffspringGreenEyesProbability" ,
"OffspringHazelEyesProbability" ,
"OffspringBrownEyesProbability" ,
"PredictedLactoseTolerance" ,
"OffspringLactoseToleranceProbability" ,
"PredictedHairTexture" ,
"OffspringStraightHairProbability" ,
"OffspringCurlyHairProbability" ,
"HomosexualnessScore" ,
"OffspringHomosexualnessScore" ,
"PredictedHeight" ,
"OffspringPredictedHeight" ,
2024-04-11 15:51:56 +02:00
}
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 )
}