seekia/gui/viewHostsGui.go

594 lines
18 KiB
Go
Raw Normal View History

package gui
// viewHostsGui.go implements a page to browse hosts
import "fyne.io/fyne/v2"
import "fyne.io/fyne/v2/container"
import "fyne.io/fyne/v2/widget"
import "fyne.io/fyne/v2/layout"
import "fyne.io/fyne/v2/theme"
import "fyne.io/fyne/v2/data/binding"
import "seekia/internal/appMemory"
import "seekia/internal/helpers"
import "seekia/internal/identity"
import "seekia/internal/mySettings"
import "seekia/internal/network/appNetworkType/getAppNetworkType"
import "seekia/internal/network/viewedHosts"
import "seekia/internal/profiles/viewableProfiles"
import "time"
import "errors"
func setViewHostsPage(window fyne.Window, previousPage func()){
appMemory.SetMemoryEntry("CurrentViewedPage", "ViewHosts")
checkIfPageHasChangedFunction := func()bool{
exists, currentViewedPage := appMemory.GetMemoryEntry("CurrentViewedPage")
if (exists == false || currentViewedPage != "ViewHosts"){
return true
}
return false
}
//TODO: Check if moderator/host mode is enabled
// If not, many attributes cannot be displayed, and the list will be empty/outdated
// Require either mode to be enabled to view hosts
currentPage := func(){setViewHostsPage(window, previousPage)}
title := getPageTitleCentered("Viewing Hosts")
backButton := getBackButtonCentered(previousPage)
filtersIcon, err := getFyneImageIcon("Desires")
if (err != nil){
setErrorEncounteredPage(window, err, previousPage)
return
}
filtersButton := widget.NewButton("Filters", func(){
//TODO
showUnderConstructionDialog(window)
})
filtersButtonWithIcon := container.NewGridWithRows(2, filtersIcon, filtersButton)
statsIcon, err := getFyneImageIcon("Stats")
if (err != nil){
setErrorEncounteredPage(window, err, previousPage)
return
}
statsButton := widget.NewButton("Stats", func(){
//TODO
showUnderConstructionDialog(window)
})
statsButtonWithIcon := container.NewGridWithRows(2, statsIcon, statsButton)
pageButtonsRow := getContainerCentered(container.NewGridWithRows(1, filtersButtonWithIcon, statsButtonWithIcon))
currentSortByAttribute, err := viewedHosts.GetViewedHostsSortByAttribute()
if (err != nil) {
setErrorEncounteredPage(window, err, previousPage)
return
}
sortingByLabel := getBoldLabel(translate("Sorting By:"))
getSortByAttributeTitle := func()string{
if (currentSortByAttribute == "BanAdvocates"){
result := translate("Ban Advocates")
return result
}
result := translate(currentSortByAttribute)
return result
}
sortByAttributeTitle := getSortByAttributeTitle()
sortByAttributeButton := widget.NewButton(sortByAttributeTitle, func(){
setSelectViewedHostsSortByAttributePage(window, currentPage)
})
getSortDirectionButtonWithIcon := func()(fyne.Widget, error){
currentSortDirection, err := viewedHosts.GetViewedHostsSortDirection()
if (err != nil) { return nil, err }
if (currentSortDirection == "Ascending"){
button := widget.NewButtonWithIcon(translate("Ascending"), theme.MoveUpIcon(), func(){
appMemory.SetMemoryEntry("StopBuildViewedHostsYesNo", "Yes")
mySettings.SetSetting("ViewedHostsSortDirection", "Descending")
mySettings.SetSetting("ViewedHostsSortedStatus", "No")
mySettings.SetSetting("ViewedHostsViewIndex", "0")
currentPage()
})
return button, nil
}
button := widget.NewButtonWithIcon(translate("Descending"), theme.MoveDownIcon(), func(){
appMemory.SetMemoryEntry("StopBuildViewedHostsYesNo", "Yes")
mySettings.SetSetting("ViewedHostsSortDirection", "Ascending")
mySettings.SetSetting("ViewedHostsSortedStatus", "No")
mySettings.SetSetting("ViewedHostsViewIndex", "0")
currentPage()
})
return button, nil
}
sortByDirectionButton, err := getSortDirectionButtonWithIcon()
if (err != nil){
setErrorEncounteredPage(window, err, previousPage)
return
}
sortByRow := container.NewHBox(layout.NewSpacer(), sortingByLabel, sortByAttributeButton, sortByDirectionButton, layout.NewSpacer())
appNetworkType, err := getAppNetworkType.GetAppNetworkType()
if (err != nil) {
setErrorEncounteredPage(window, err, previousPage)
return
}
viewedHostsReady, err := viewedHosts.GetViewedHostsAreReadyStatus(appNetworkType)
if (err != nil) {
setErrorEncounteredPage(window, err, previousPage)
return
}
if (viewedHostsReady == false){
progressPercentageBinding := binding.NewFloat()
sortingDetailsBinding := binding.NewString()
startUpdateHostsAndProgressBarFunction := func(){
err := viewedHosts.StartUpdatingViewedHosts(appNetworkType)
if (err != nil) {
setErrorEncounteredPage(window, err, previousPage)
return
}
sortingDetailsBindingSet := false
var encounteredError error
for {
pageHasChanged := checkIfPageHasChangedFunction()
if (pageHasChanged == true){
appMemory.SetMemoryEntry("StopBuildViewedHostsYesNo", "Yes")
return
}
buildEncounteredError, errorEncounteredString, buildIsStopped, hostsAreReady, currentPercentageProgress, err := viewedHosts.GetViewedHostsBuildStatus(appNetworkType)
if (err != nil){
encounteredError = err
break
}
if (buildEncounteredError == true){
encounteredError = errors.New(errorEncounteredString)
break
}
if (buildIsStopped == true){
return
}
if (hostsAreReady == 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 && sortingDetailsBindingSet == false){
numberOfHosts, err := viewedHosts.GetNumberOfGeneratedViewedHosts()
if (err != nil) {
encounteredError = err
break
}
if (numberOfHosts != 0){
numberOfHostsString := helpers.ConvertIntToString(numberOfHosts)
sortingDetailsBinding.Set("Sorting " + numberOfHostsString + " Hosts...")
}
sortingDetailsBindingSet = true
}
time.Sleep(100 * time.Millisecond)
}
// This is only reached if an error is encountered during build
errorToShow := errors.New("Error encountered during build of viewed hosts: " + encounteredError.Error())
setErrorEncounteredPage(window, errorToShow, previousPage)
}
loadingLabel := getBoldLabelCentered("Loading Hosts...")
loadingBar := getWidgetCentered(widget.NewProgressBarWithData(progressPercentageBinding))
loadingDetailsLabel := widget.NewLabelWithData(sortingDetailsBinding)
loadingDetailsLabel.TextStyle = getFyneTextStyle_Italic()
loadingDetailsLabelCentered := getWidgetCentered(loadingDetailsLabel)
page := container.NewVBox(title, backButton, widget.NewSeparator(), pageButtonsRow, widget.NewSeparator(), sortByRow, widget.NewSeparator(), loadingLabel, loadingBar, loadingDetailsLabelCentered)
setPageContent(page, window)
go startUpdateHostsAndProgressBarFunction()
return
}
getResultsContainer := func()(*fyne.Container, error){
getRefreshResultsButtonText := func()(string, error){
needsRefresh, err := viewedHosts.CheckIfViewedHostsNeedsRefresh()
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("ViewedHostsGeneratedStatus", "No")
mySettings.SetSetting("ViewedHostsViewIndex", "0")
currentPage()
}))
listIsReady, currentViewedHostsList, err := viewedHosts.GetViewedHostsList(appNetworkType)
if (err != nil) { return nil, err }
if (listIsReady == false){
return nil, errors.New("Viewed hosts list not ready after generation completed.")
}
numberOfViewedHosts := len(currentViewedHostsList)
if (numberOfViewedHosts == 0){
noHostsFoundLabel := getBoldLabelCentered("No Hosts Found")
numberOfFilters, err := viewedHosts.GetNumberOfActiveHostFilters()
if (err != nil) { return nil, err }
if (numberOfFilters == 0){
noHostsFoundLabelWithRefreshButton := container.NewVBox(noHostsFoundLabel, refreshResultsButton)
return noHostsFoundLabelWithRefreshButton, nil
}
numberOfFiltersString := helpers.ConvertIntToString(numberOfFilters)
getActiveFiltersText := func()string{
if (numberOfFilters == 1){
return "active filter"
}
return "active filters"
}
activeFiltersText := getActiveFiltersText()
activeFiltersLabel := getLabelCentered(numberOfFiltersString + " " + activeFiltersText)
noHostsFoundWithFiltersInfo := container.NewVBox(noHostsFoundLabel, activeFiltersLabel, refreshResultsButton)
return noHostsFoundWithFiltersInfo, nil
}
getCurrentViewIndex := func()(int, error){
exists, viewIndexString, err := mySettings.GetSetting("ViewedHostsViewIndex")
if (err != nil) { return 0, err }
if (exists == false){
return 0, nil
}
viewIndex, err := helpers.ConvertStringToInt(viewIndexString)
if (err != nil){
return 0, errors.New("MySettings malformed: Invalid ViewedHostsViewIndex: " + viewIndexString)
}
if (viewIndex < 0) {
return 0, nil
}
maximumViewIndex := numberOfViewedHosts-1
if (viewIndex > maximumViewIndex){
return maximumViewIndex, nil
}
return viewIndex, nil
}
viewIndex, err := getCurrentViewIndex()
if (err != nil) { return nil, err }
getNavigateToBeginningButton := func()fyne.Widget{
if (numberOfViewedHosts <= 5 || viewIndex == 0){
emptyButton := widget.NewButton(" ", nil)
return emptyButton
}
goToBeginningButton := widget.NewButtonWithIcon("", theme.MediaSkipPreviousIcon(), func(){
mySettings.SetSetting("ViewedHostsViewIndex", "0")
currentPage()
})
return goToBeginningButton
}
getNavigateToEndButton := func()fyne.Widget{
emptyButton := widget.NewButton(" ", nil)
if (numberOfViewedHosts <= 5){
return emptyButton
}
finalPageMinimumIndex := numberOfViewedHosts - 5
if (viewIndex >= finalPageMinimumIndex){
return emptyButton
}
goToEndButton := widget.NewButtonWithIcon("", theme.MediaSkipNextIcon(), func(){
finalPageIndexString := helpers.ConvertIntToString(finalPageMinimumIndex)
mySettings.SetSetting("ViewedHostsViewIndex", finalPageIndexString)
currentPage()
})
return goToEndButton
}
getNavigateLeftButton := func()fyne.Widget{
if (numberOfViewedHosts <= 5 || viewIndex == 0){
emptyButton := widget.NewButton(" ", nil)
return emptyButton
}
button := widget.NewButtonWithIcon("", theme.NavigateBackIcon(), func(){
newIndex := helpers.ConvertIntToString(viewIndex-5)
mySettings.SetSetting("ViewedHostsViewIndex", newIndex)
currentPage()
})
return button
}
getNavigateRightButton := func()fyne.Widget{
emptyButton := widget.NewButton(" ", nil)
if (numberOfViewedHosts <= 5){
return emptyButton
}
finalPageMinimumIndex := numberOfViewedHosts - 5
if (viewIndex >= finalPageMinimumIndex){
return emptyButton
}
button := widget.NewButtonWithIcon("", theme.NavigateNextIcon(), func(){
newIndex := helpers.ConvertIntToString(viewIndex+5)
mySettings.SetSetting("ViewedHostsViewIndex", newIndex)
currentPage()
})
return button
}
getViewingHostsInfoRow := func()*fyne.Container{
numberOfViewedHostsString := helpers.ConvertIntToString(numberOfViewedHosts)
getHostOrHostsText := func()string{
if (numberOfViewedHosts == 1){
return "Host"
}
return "Hosts"
}
hostOrHostsText := getHostOrHostsText()
numberOfViewedHostsLabel := getBoldLabel("Viewing " + numberOfViewedHostsString + " " + hostOrHostsText)
if (numberOfViewedHosts <= 5){
viewingHostsInfoRow := getWidgetCentered(numberOfViewedHostsLabel)
return viewingHostsInfoRow
}
navigateToBeginningButton := getNavigateToBeginningButton()
navigateToEndButton := getNavigateToEndButton()
navigateLeftButton := getNavigateLeftButton()
navigateRightButton := getNavigateRightButton()
viewingHostsInfoRow := container.NewHBox(layout.NewSpacer(), navigateToBeginningButton, navigateLeftButton, numberOfViewedHostsLabel, navigateRightButton, navigateToEndButton, layout.NewSpacer())
return viewingHostsInfoRow
}
viewingHostsInfoRow := getViewingHostsInfoRow()
hostResultsContainer := container.NewVBox()
if (viewIndex == 0){
hostResultsContainer.Add(refreshResultsButton)
hostResultsContainer.Add(widget.NewSeparator())
}
emptyLabelA := widget.NewLabel("")
nameLabel := getItalicLabelCentered("Name")
identityHashTitle := getItalicLabelCentered("Identity Hash")
featuredAttributeTitle := getItalicLabelCentered(sortByAttributeTitle)
emptyLabelB := widget.NewLabel("")
resultIndexColumn := container.NewVBox(emptyLabelA, widget.NewSeparator())
nameColumn := container.NewVBox(nameLabel, widget.NewSeparator())
identityHashColumn := container.NewVBox(identityHashTitle, widget.NewSeparator())
featuredAttributeColumn := container.NewVBox(featuredAttributeTitle, widget.NewSeparator())
viewButtonsColumn := container.NewVBox(emptyLabelB, widget.NewSeparator())
viewIndexOnwardsHostIdentityHashesList := currentViewedHostsList[viewIndex:]
for index, hostIdentityHash := range viewIndexOnwardsHostIdentityHashesList{
resultIndex := viewIndex + index + 1
resultIndexString := helpers.ConvertIntToString(resultIndex)
resultIndexBoldLabel := getBoldLabel(resultIndexString + ".")
profileExists, _, getAnyHostAttributeFunction, err := viewableProfiles.GetRetrieveAnyNewestViewableUserProfileAttributeFunction(hostIdentityHash, appNetworkType, true, true, true)
if (err != nil) { return nil, err }
if (profileExists == false) {
// Profile has expired since results were generated
continue
}
getUserName := func()(string, error){
exists, _, username, err := getAnyHostAttributeFunction("Username")
if (err != nil) { return "", err }
if (exists == false) {
return "Anonymous", nil
}
theirUsernameTrimmed, _, err := helpers.TrimAndFlattenString(username, 15)
if (err != nil) { return "", err }
return theirUsernameTrimmed, nil
}
currentTheirUsername, err := getUserName()
if (err != nil) { return nil, err }
userNameLabel := getBoldLabelCentered(currentTheirUsername)
hostIdentityHashString, _, err := identity.EncodeIdentityHashBytesToString(hostIdentityHash)
if (err != nil) { return nil, err }
theirIdentityHashTrimmed, _, err := helpers.TrimAndFlattenString(hostIdentityHashString, 10)
if (err != nil) { return nil, err }
theirIdentityHashLabel := getBoldLabelCentered(theirIdentityHashTrimmed)
getFeaturedAttributeValue := func()(string, error){
exists, _, featuredAttributeValue, err := getAnyHostAttributeFunction(currentSortByAttribute)
if (err != nil) { return "", err }
if (exists == false){
return "Unknown", nil
}
return featuredAttributeValue, nil
}
featuredAttributeValue, err := getFeaturedAttributeValue()
if (err != nil) { return nil, err }
featuredAttributeValueLabel := getBoldLabelCentered(featuredAttributeValue)
viewHostButton := widget.NewButtonWithIcon("View", theme.VisibilityIcon(), func(){
setViewHostDetailsPage(window, hostIdentityHash, currentPage)
})
resultIndexColumn.Add(resultIndexBoldLabel)
nameColumn.Add(userNameLabel)
identityHashColumn.Add(theirIdentityHashLabel)
featuredAttributeColumn.Add(featuredAttributeValueLabel)
viewButtonsColumn.Add(viewHostButton)
resultIndexColumn.Add(widget.NewSeparator())
nameColumn.Add(widget.NewSeparator())
identityHashColumn.Add(widget.NewSeparator())
featuredAttributeColumn.Add(widget.NewSeparator())
viewButtonsColumn.Add(widget.NewSeparator())
if (index >= 4){
break
}
}
hostResultsGrid := container.NewHBox(layout.NewSpacer(), resultIndexColumn, nameColumn, identityHashColumn, featuredAttributeColumn, viewButtonsColumn, layout.NewSpacer())
hostResultsContainer.Add(hostResultsGrid)
viewedHostContainerScrollable := container.NewVScroll(hostResultsContainer)
viewedHostContainerBoxed := getWidgetBoxed(viewedHostContainerScrollable)
resultsContainer := container.NewBorder(viewingHostsInfoRow, nil, nil, nil, viewedHostContainerBoxed)
return resultsContainer, nil
}
resultsContainer, err := getResultsContainer()
if (err != nil){
setErrorEncounteredPage(window, err, previousPage)
return
}
header := container.NewVBox(title, backButton, widget.NewSeparator(), pageButtonsRow, widget.NewSeparator(), sortByRow, widget.NewSeparator())
page := container.NewBorder(header, nil, nil, nil, resultsContainer)
setPageContent(page, window)
}
func setSelectViewedHostsSortByAttributePage(window fyne.Window, previousPage func()){
appMemory.SetMemoryEntry("CurrentViewedPage", "ViewedHostsSortBySelect")
title := getPageTitleCentered("Select Sort By Attribute")
backButton := getBackButtonCentered(previousPage)
description := getLabelCentered("Select the attribute to sort the hosts by.")
getSelectButton := func(attributeTitle string, attributeName string, sortDirection string) fyne.Widget{
button := widget.NewButton(attributeTitle, func(){
mySettings.SetSetting("ViewedHostsSortedStatus", "No")
mySettings.SetSetting("ViewedHostsSortByAttribute", attributeName)
mySettings.SetSetting("ViewedHostsSortDirection", sortDirection)
mySettings.SetSetting("ViewedHostsViewIndex", "0")
previousPage()
})
return button
}
//TODO: Add more attributes
banAdvocatesButton := getSelectButton("Ban Advocates", "BanAdvocates", "Ascending")
buttonsGrid := getContainerCentered(container.NewGridWithColumns(1, banAdvocatesButton))
content := container.NewVBox(title, backButton, widget.NewSeparator(), description, widget.NewSeparator(), buttonsGrid)
setPageContent(content, window)
}