seekia/gui/accountCreditGui.go

1092 lines
39 KiB
Go

package gui
// accountCreditGui.go implements pages to view and increase a user's account credit, and to spend credit to increase their identity balance
import "fyne.io/fyne/v2"
import "fyne.io/fyne/v2/widget"
import "fyne.io/fyne/v2/container"
import "fyne.io/fyne/v2/layout"
import "fyne.io/fyne/v2/theme"
import "fyne.io/fyne/v2/dialog"
import "seekia/resources/currencies"
import "seekia/internal/appMemory"
import "seekia/internal/convertCurrencies"
import "seekia/internal/globalSettings"
import "seekia/internal/helpers"
import "seekia/internal/network/appNetworkType/getAppNetworkType"
import "seekia/internal/network/myAccountCredit"
import "seekia/internal/parameters/getParameters"
import "errors"
import "time"
func setViewMyAccountCreditPage(window fyne.Window, myIdentityType string, previousPage func()){
currentPage := func(){setViewMyAccountCreditPage(window, myIdentityType, previousPage)}
appMemory.SetMemoryEntry("CurrentViewedPage", "AccountCredit")
title := getPageTitleCentered("My " + myIdentityType + " Account Credit")
backButton := getBackButtonCentered(previousPage)
description1 := getLabelCentered("Broadcasting to the Seekia network requires credit.")
description2 := getLabelCentered("You can be gifted credit to your account by sharing an account identifier.")
description3 := getLabelCentered("You can also send Ethereum or Cardano to add to your account credit.")
getMyCreditBalanceSection := func()(*fyne.Container, error){
appNetworkType, err := getAppNetworkType.GetAppNetworkType()
if (err != nil) { return nil, err }
myCreditBalanceLabel := getItalicLabelCentered("My Credit Balance:")
getCurrentAppCurrency := func()(string, error){
exists, currentAppCurrency, err := globalSettings.GetSetting("Currency")
if (err != nil) { return "", err }
if (exists == false){
return "USD", nil
}
return currentAppCurrency, nil
}
currentAppCurrencyCode, err := getCurrentAppCurrency()
if (err != nil){ return nil, err }
_, appCurrencySymbol, err := currencies.GetCurrencyInfoFromCurrencyCode(currentAppCurrencyCode)
if (err != nil) { return nil, err }
appCurrencySymbolButton := widget.NewButton(appCurrencySymbol, func(){
setChangeAppCurrencyPage(window, currentPage)
})
parametersExist, appCurrencyAccountCreditBalance, err := myAccountCredit.GetMyCreditAccountBalanceInAnyCurrency(myIdentityType, appNetworkType, currentAppCurrencyCode)
if (err != nil) { return nil, err }
getAccountBalanceText := func()(string, error){
if (parametersExist == false){
return "Unknown", nil
}
appCurrencyAccountCreditBalanceString := helpers.ConvertFloat64ToStringRounded(appCurrencyAccountCreditBalance, 3)
return appCurrencyAccountCreditBalanceString, nil
}
accountBalanceText, err := getAccountBalanceText()
if (err != nil) { return nil, err }
appCurrencyAccountCreditBalanceLabel := getBoldLabel(accountBalanceText + " " + currentAppCurrencyCode)
myCreditBalanceRow := container.NewHBox(layout.NewSpacer(), appCurrencySymbolButton, appCurrencyAccountCreditBalanceLabel, layout.NewSpacer())
currentBalanceRefreshButton := getWidgetCentered(widget.NewButtonWithIcon("Refresh", theme.ViewRefreshIcon(), func(){
if (parametersExist == false){
dialogTitle := translate("Parameters Missing.")
dialogMessageA := getLabelCentered(translate("The network parameters are not downloaded."))
dialogMessageB := getLabelCentered(translate("You must wait for them to download to view your balance."))
//TODO: View progress button
dialogContent := container.NewVBox(dialogMessageA, dialogMessageB)
dialog.ShowCustom(dialogTitle, translate("Close"), dialogContent, window)
return
}
//TODO
showUnderConstructionDialog(window)
}))
myCreditBalanceSection := container.NewVBox(myCreditBalanceLabel, myCreditBalanceRow, currentBalanceRefreshButton)
return myCreditBalanceSection, nil
}
myCreditBalanceSection, err := getMyCreditBalanceSection()
if (err != nil) {
setErrorEncounteredPage(window, err, previousPage)
return
}
viewAccountIdentifierButton := getWidgetCentered(widget.NewButtonWithIcon("View Account Identifier", theme.VisibilityIcon(), func(){
setAddAccountCreditWithAccountIdentifierPage(window, myIdentityType, currentPage)
}))
ethereumIcon, err := getFyneImageIcon("Ethereum")
if (err != nil){
setErrorEncounteredPage(window, err, previousPage)
return
}
iconSize := getCustomFyneSize(0)
ethereumIcon.SetMinSize(iconSize)
addFundsButton_Ethereum := widget.NewButton("Send Ethereum", func(){
nextPage := func(){setAddAccountCreditWithCryptocurrencyPage(window, myIdentityType, "Ethereum", currentPage)}
setBuyAccountCreditCryptoPrivacyWarningPage(window, currentPage, nextPage)
})
addFundsButtonWithIcon_Ethereum := container.NewGridWithColumns(1, ethereumIcon, addFundsButton_Ethereum)
cardanoIcon, err := getFyneImageIcon("Cardano")
if (err != nil){
setErrorEncounteredPage(window, err, previousPage)
return
}
cardanoIcon.SetMinSize(iconSize)
addFundsButton_Cardano := widget.NewButton("Send Cardano", func(){
nextPage := func(){setAddAccountCreditWithCryptocurrencyPage(window, myIdentityType, "Cardano", currentPage)}
setBuyAccountCreditCryptoPrivacyWarningPage(window, currentPage, nextPage)
})
addFundsButtonWithIcon_Cardano := container.NewGridWithColumns(1, cardanoIcon, addFundsButton_Cardano)
viewPricingButton := getWidgetCentered(widget.NewButtonWithIcon("View Pricing", theme.VisibilityIcon(), func(){
setViewSeekiaPricingPage(window, currentPage)
}))
addFundsButtonsGrid := getContainerCentered(container.NewGridWithColumns(2, addFundsButtonWithIcon_Ethereum, addFundsButtonWithIcon_Cardano))
page := container.NewVBox(title, backButton, widget.NewSeparator(), description1, description2, description3, widget.NewSeparator(), myCreditBalanceSection, widget.NewSeparator(), viewAccountIdentifierButton, widget.NewSeparator(), addFundsButtonsGrid, widget.NewSeparator(), viewPricingButton)
setPageContent(page, window)
}
func setAddAccountCreditWithAccountIdentifierPage(window fyne.Window, myIdentityType string, previousPage func()){
title := getPageTitleCentered("Add Account Credit")
backButton := getBackButtonCentered(previousPage)
description1 := getLabelCentered("Use this identifier to receive account credit.")
appNetworkType, err := getAppNetworkType.GetAppNetworkType()
if (err != nil) {
setErrorEncounteredPage(window, err, previousPage)
return
}
viewUsedIdentifiersButton := getWidgetCentered(widget.NewButtonWithIcon("View Used Identifiers", theme.HistoryIcon(), func(){
//TODO
showUnderConstructionDialog(window)
}))
identityExists, unusedAccountIdentifier, err := myAccountCredit.GetAnUnusedCreditAccountIdentifier(myIdentityType, appNetworkType)
if (err != nil){
setErrorEncounteredPage(window, err, previousPage)
return
}
if (identityExists == false){
setErrorEncounteredPage(window, errors.New("setAddAccountCreditWithAccountIdentifierPage called when identity is missing"), previousPage)
return
}
myIdentifierLabel := getBoldLabelCentered("My Account Identifier:")
identifierEntry := widget.NewEntry()
identifierEntry.SetText(unusedAccountIdentifier)
identifierEntry.OnChanged = func(_ string){
identifierEntry.SetText(unusedAccountIdentifier)
}
identifierEntryBoxed := getWidgetBoxed(identifierEntry)
entryWidener := widget.NewLabel(" ")
entryWidened := getContainerCentered(container.NewGridWithColumns(1, identifierEntryBoxed, entryWidener))
page := container.NewVBox(title, backButton, widget.NewSeparator(), description1, widget.NewSeparator(), viewUsedIdentifiersButton, widget.NewSeparator(), myIdentifierLabel, entryWidened)
setPageContent(page, window)
}
func setBuyAccountCreditCryptoPrivacyWarningPage(window fyne.Window, previousPage func(), nextPage func()){
title := getPageTitleCentered("Privacy Warning")
backButton := getBackButtonCentered(previousPage)
description1 := getLabelCentered("Be aware that your privacy is at risk when using cryptocurrencies.")
description2 := getLabelCentered("When you send money from your wallet, it is possible to guess that you are a user of Seekia.")
description3 := getLabelCentered("There is also a risk of someone linking your wallet to your Seekia identity.")
description4 := getBoldLabelCentered("To protect yourself, wait before funding your Seekia identity.")
description5 := getLabelCentered("For example, after funding your account, wait a few days before funding your identity.")
description6 := getLabelCentered("This will break the link between your transaction and your Seekia profile/identity.")
description7 := getLabelCentered("If you have a large amount of cryptocurrency, you should be wary of sending your funds from that wallet.")
description8 := getLabelCentered("For privacy, you should send funds directly from an exchange.")
description9 := getLabelCentered("You can also use a privacy tool such as a zero knowledge accumulator for stronger protection.")
description10 := getBoldLabelCentered("Do you understand the privacy risks?")
iUnderstandButton := getWidgetCentered(widget.NewButtonWithIcon("I Understand", theme.ConfirmIcon(), nextPage))
page := container.NewVBox(title, backButton, widget.NewSeparator(), description1, description2, description3, widget.NewSeparator(), description4, description5, description6, widget.NewSeparator(), description7, description8, description9, widget.NewSeparator(), description10, iUnderstandButton)
setPageContent(page, window)
}
func setAddAccountCreditWithCryptocurrencyPage(window fyne.Window, myIdentityType string, cryptocurrency string, previousPage func()){
setLoadingScreen(window, "Add " + myIdentityType + " Account Credit", "Loading Add Account Credit page...")
if (cryptocurrency != "Ethereum" && cryptocurrency != "Cardano"){
setErrorEncounteredPage(window, errors.New("Invalid cryptocurrency: " + cryptocurrency), previousPage)
return
}
currentPage := func(){setAddAccountCreditWithCryptocurrencyPage(window, myIdentityType, cryptocurrency, previousPage)}
title := getPageTitleCentered("Add " + myIdentityType + " Account Credit")
backButton := getBackButtonCentered(previousPage)
viewUsedAddressesButton := getWidgetCentered(widget.NewButtonWithIcon("View Used Addresses", theme.HistoryIcon(), func(){
//TODO
showUnderConstructionDialog(window)
}))
appNetworkType, err := getAppNetworkType.GetAppNetworkType()
if (err != nil) {
setErrorEncounteredPage(window, err, previousPage)
return
}
myIdentityExists, myFundsAddress, err := myAccountCredit.GetAnUnusedCreditAccountCryptoAddress(myIdentityType, appNetworkType, cryptocurrency)
if (err != nil){
setErrorEncounteredPage(window, err, previousPage)
return
}
if (myIdentityExists == false){
description1 := getBoldLabelCentered("Your " + myIdentityType + " identity does not exist.")
descriptionB := getLabelCentered("Create your identity?.")
createIdentityButton := getWidgetCentered(widget.NewButtonWithIcon("Create Identity", theme.NavigateNextIcon(), func(){
setChooseNewIdentityHashPage(window, myIdentityType, currentPage, currentPage)
}))
page := container.NewVBox(title, backButton, widget.NewSeparator(), description1, descriptionB, createIdentityButton)
setPageContent(page, window)
return
}
description1 := getLabelCentered("Send " + cryptocurrency + " to increase your account credit.")
descriptionB := getBoldLabelCentered("All funds sent will be destroyed forever.")
cryptoAddressLabelRow, err := getCryptocurrencyAddressLabelWithCopyAndQRButtons(window, cryptocurrency, myFundsAddress, currentPage)
if (err != nil) {
setErrorEncounteredPage(window, err, previousPage)
return
}
estimateCostsDescription := getLabelCentered("Use the page below to determine how much you should send.")
viewPricingButton := getWidgetCentered(widget.NewButtonWithIcon("View Pricing", theme.VisibilityIcon(), func(){
setViewSeekiaPricingPage(window, currentPage)
}))
page := container.NewVBox(title, backButton, widget.NewSeparator(), description1, descriptionB, widget.NewSeparator(), viewUsedAddressesButton, widget.NewSeparator(), cryptoAddressLabelRow, widget.NewSeparator(), estimateCostsDescription, viewPricingButton)
setPageContent(page, window)
return
}
// This page is used to show how much it costs to fund broadcasts on the Seekia network
func setViewSeekiaPricingPage(window fyne.Window, previousPage func()){
currentPage := func(){setViewSeekiaPricingPage(window, previousPage)}
title := getPageTitleCentered("Seekia Pricing (Under Construction)")
backButton := getBackButtonCentered(previousPage)
description := getLabelCentered("Below are the estimated prices to broadcast content on the Seekia network.")
getAppCurrency := func()(string, error){
exists, appCurrencyCode, err := globalSettings.GetSetting("Currency")
if (err != nil) { return "", err }
if (exists == false){
return "USD", nil
}
return appCurrencyCode, nil
}
appCurrencyCode, err := getAppCurrency()
if (err != nil) {
setErrorEncounteredPage(window, err, previousPage)
return
}
currentCurrencyLabel := getBoldLabelCentered("Current Currency:")
_, appCurrencySymbol, err := currencies.GetCurrencyInfoFromCurrencyCode(appCurrencyCode)
if (err != nil) {
setErrorEncounteredPage(window, err, previousPage)
return
}
chooseCurrencyButton := widget.NewButton(appCurrencySymbol + appCurrencyCode, func(){
setChangeAppCurrencyPage(window, currentPage)
})
currentCurrencyRow := container.NewHBox(layout.NewSpacer(), currentCurrencyLabel, chooseCurrencyButton, layout.NewSpacer())
actionNameLabel := getItalicLabelCentered("Action Name")
costLabel := getItalicLabelCentered("Cost")
actionNameColumn := container.NewVBox(actionNameLabel, widget.NewSeparator())
costColumn := container.NewVBox(costLabel, widget.NewSeparator())
appNetworkType, err := getAppNetworkType.GetAppNetworkType()
if (err != nil) {
setErrorEncounteredPage(window, err, previousPage)
return
}
//Outputs:
// -bool: Parameters exist
// -error
addActionRows := func()(bool, error){
exchangeRatesAreDownloaded, err := convertCurrencies.CheckIfExchangeRatesAreDownloaded(appNetworkType)
if (err != nil){ return false, err }
if (exchangeRatesAreDownloaded == false){
return false, nil
}
//Outputs:
// -bool: Exchange rates exist
// -error
addActionRow := func(actionName string, costInGramsOfGold float64)(bool, error){
costInKilogramsOfGold := costInGramsOfGold/1000
exchangeRateExists, appCurrencyCostFloat64, err := convertCurrencies.ConvertKilogramsOfGoldToAnyCurrency(appNetworkType, costInKilogramsOfGold, appCurrencyCode)
if (err != nil) { return false, err }
if (exchangeRateExists == false) {
return false, nil
}
appCurrencyCostString := helpers.ConvertFloat64ToStringRounded(appCurrencyCostFloat64, 3)
appCurrencyCostFormatted := appCurrencySymbol + " " + appCurrencyCostString + " " + appCurrencyCode
actionNameText := getBoldLabelCentered(actionName)
currencyCostLabel := getBoldLabelCentered(appCurrencyCostFormatted)
actionNameColumn.Add(actionNameText)
costColumn.Add(currencyCostLabel)
actionNameColumn.Add(widget.NewSeparator())
costColumn.Add(widget.NewSeparator())
return true, nil
}
currentTime := time.Now().Unix()
parametersExist, messageKilobyteGoldCostPerDay, err := getParameters.GetMessageKilobyteGoldCostPerDay(appNetworkType, currentTime)
if (err != nil) { return false, err }
if (parametersExist == false){
return false, nil
}
//TODO: Fix below numbers
textMessageSizeKilobytes := float64(2)
imageMessageSizeKilobytes := float64(22)
textMessageGramsOfGoldCost := messageKilobyteGoldCostPerDay * textMessageSizeKilobytes * 14
imageMessageGramsOfGoldCost := messageKilobyteGoldCostPerDay * imageMessageSizeKilobytes * 14
parametersExist, err = addActionRow("Send 100 Text Messages", textMessageGramsOfGoldCost * 100)
if (err != nil) { return false, err }
if (parametersExist == false){
return false, nil
}
parametersExist, err = addActionRow("Send 100 Image Messages", imageMessageGramsOfGoldCost * 100)
if (err != nil) { return false, err }
if (parametersExist == false){
return false, nil
}
parametersExist, mateIdentityGoldCostPerDay, err := getParameters.GetIdentityBalanceGoldCostPerDay(appNetworkType, "Mate", currentTime)
if (err != nil) { return false, err }
if (parametersExist == false){
return false, nil
}
parametersExist, err = addActionRow("Fund Mate Identity for 3 Months", mateIdentityGoldCostPerDay * 90)
if (err != nil) { return false, err }
if (parametersExist == false){
return false, nil
}
parametersExist, hostIdentityGoldCostPerDay, err := getParameters.GetIdentityBalanceGoldCostPerDay(appNetworkType, "Host", currentTime)
if (err != nil) { return false, err }
if (parametersExist == false){
return false, nil
}
parametersExist, err = addActionRow("Fund Host Identity for 3 Months", hostIdentityGoldCostPerDay * 90)
if (err != nil) { return false, err }
if (parametersExist == false){
return false, nil
}
parametersExist, fundMateProfileCost, err := getParameters.GetFundMateProfileCostInGold(appNetworkType, currentTime)
if (err != nil) { return false, err }
if (parametersExist == false){
return false, nil
}
parametersExist, err = addActionRow("Broadcast Mate Profile 30 Times", fundMateProfileCost * 30)
if (err != nil) { return false, err }
if (parametersExist == false){
return false, nil
}
parametersExist, fundReportCost, err := getParameters.GetFundReportCostInGold(appNetworkType, currentTime)
if (err != nil) { return false, err }
if (parametersExist == false){
return false, nil
}
parametersExist, err = addActionRow("Make 10 Reports", fundReportCost * 10)
if (err != nil) { return false, err }
if (parametersExist == false){
return false, nil
}
return true, nil
}
parametersExist, err := addActionRows()
if (err != nil){
setErrorEncounteredPage(window, err, previousPage)
return
}
if (parametersExist == false){
description1 := getBoldLabelCentered("Currency exchange rates are not downloaded.")
descriptionB := getLabelCentered("Please wait for them to download to view pricing.")
//TODO: Add monitor button
refreshButton := getWidgetCentered(widget.NewButtonWithIcon("Refresh", theme.ViewRefreshIcon(), currentPage))
page := container.NewVBox(title, backButton, widget.NewSeparator(), description1, descriptionB, refreshButton)
setPageContent(page, window)
return
}
pricingGrid := container.NewHBox(layout.NewSpacer(), actionNameColumn, costColumn, layout.NewSpacer())
calculateDescription := getLabelCentered("Use the pages below to calculate costs.")
identityIcon, err := getFyneImageIcon("Profile")
if (err != nil) {
setErrorEncounteredPage(window, err, previousPage)
return
}
chatIcon, err := getFyneImageIcon("Chat")
if (err != nil) {
setErrorEncounteredPage(window, err, previousPage)
return
}
identityCostsButton := widget.NewButton("Identity Costs", func(){
setViewIdentityBalancePriceCalculatorPage(window, "Mate", 30, currentPage)
})
chatCostsButton := widget.NewButton("Chat Costs", func(){
setViewMessagePricingCalculatorPage(window, "Image", 14, 100, currentPage)
})
identityCostsButtonWithIcon := container.NewGridWithColumns(1, identityIcon, identityCostsButton)
chatCostsButtonWithIcon := container.NewGridWithColumns(1, chatIcon, chatCostsButton)
buttonsGrid := getContainerCentered(container.NewGridWithRows(1, identityCostsButtonWithIcon, chatCostsButtonWithIcon))
page := container.NewVBox(title, backButton, widget.NewSeparator(), description, widget.NewSeparator(), currentCurrencyRow, widget.NewSeparator(), pricingGrid, widget.NewSeparator(), calculateDescription, buttonsGrid)
setPageContent(page, window)
}
// This page is used to show how much it costs to fund a user on the Seekia network
// Users use this to determine how much money to send to their account
func setViewIdentityBalancePriceCalculatorPage(window fyne.Window, identityType string, daysToFund int, previousPage func()){
currentPage := func(){setViewIdentityBalancePriceCalculatorPage(window, identityType, daysToFund, previousPage)}
if (identityType != "Mate" && identityType != "Host"){
setErrorEncounteredPage(window, errors.New("setViewIdentityBalancePriceCalculatorPage called with invalid identityType: " + identityType), previousPage)
return
}
title := getPageTitleCentered("Identity Balance Pricing")
backButton := getBackButtonCentered(previousPage)
subtitle := getPageSubtitleCentered("Calculate Identity Balance Pricing")
appNetworkType, err := getAppNetworkType.GetAppNetworkType()
if (err != nil) {
setErrorEncounteredPage(window, err, previousPage)
return
}
//Outputs:
// -bool: Parameters exist
// -*fyne.Container: Calculator section
// -error
getCalculatorContainer := func()(bool, *fyne.Container, error){
currentTime := time.Now().Unix()
exchangeRatesAreDownloaded, err := convertCurrencies.CheckIfExchangeRatesAreDownloaded(appNetworkType)
if (err != nil){ return false, nil, err }
if (exchangeRatesAreDownloaded == false){
return false, nil, nil
}
identityTypeLabel := getBoldLabelCentered("Identity Type:")
identityTypesList := []string{"Mate", "Host"}
identityTypeSelector := widget.NewSelect(identityTypesList, func(newIdentityType string){
if (newIdentityType == identityType){
return
}
setViewIdentityBalancePriceCalculatorPage(window, newIdentityType, daysToFund, previousPage)
})
identityTypeSelector.Selected = identityType
identityTypeSelectorCentered := getWidgetCentered(identityTypeSelector)
daysToFundSelectorFunction := func(entry string){
if (entry == "1 month"){
if (daysToFund == 30){
return
}
setViewIdentityBalancePriceCalculatorPage(window, identityType, 30, previousPage)
}
if (entry == "3 months"){
if (daysToFund == 90){
return
}
setViewIdentityBalancePriceCalculatorPage(window, identityType, 90, previousPage)
}
if (entry == "6 months"){
if (daysToFund == 180){
return
}
setViewIdentityBalancePriceCalculatorPage(window, identityType, 180, previousPage)
}
}
desiredDurationLabel := getBoldLabelCentered("Desired Duration:")
daysToFundSelectorOptions := []string{"1 month", "3 months", "6 months"}
daysToFundSelector := widget.NewSelect(daysToFundSelectorOptions, daysToFundSelectorFunction)
if (daysToFund == 30){
daysToFundSelector.Selected = "1 month"
} else if (daysToFund == 90){
daysToFundSelector.Selected = "3 months"
} else if (daysToFund == 180){
daysToFundSelector.Selected = "6 months"
}
daysToFundSelectorCentered := getWidgetCentered(daysToFundSelector)
costLabel := getBoldLabelCentered("Cost:")
parametersExist, gramsOfGoldCostPerDay, err := getParameters.GetIdentityBalanceGoldCostPerDay(appNetworkType, identityType, currentTime)
if (err != nil) { return false, nil, err }
if (parametersExist == false){
return false, nil, nil
}
gramsOfGoldCost := gramsOfGoldCostPerDay * float64(daysToFund)
kilogramsOfGoldCost := gramsOfGoldCost/1000
getAppCurrency := func()(string, error){
exists, appCurrencyCode, err := globalSettings.GetSetting("Currency")
if (err != nil) { return "", err }
if (exists == false){
return "USD", nil
}
return appCurrencyCode, nil
}
appCurrencyCode, err := getAppCurrency()
if (err != nil) { return false, nil, err }
exchangeRateExists, appCurrencyCost, err := convertCurrencies.ConvertKilogramsOfGoldToAnyCurrency(appNetworkType, kilogramsOfGoldCost, appCurrencyCode)
if (err != nil) { return false, nil, err }
if (exchangeRateExists == false) {
return false, nil, nil
}
appCurrencyCostString := helpers.ConvertFloat64ToStringRounded(appCurrencyCost, 2)
_, appCurrencySymbol, err := currencies.GetCurrencyInfoFromCurrencyCode(appCurrencyCode)
if (err != nil) { return false, nil, err }
appCurrencyIconButton := widget.NewButton(appCurrencySymbol, func(){
setChangeAppCurrencyPage(window, currentPage)
})
appCurrencyCostLabel := getBoldLabel(appCurrencyCostString + " " + appCurrencyCode)
appCurrencyRow := container.NewHBox(layout.NewSpacer(), appCurrencyIconButton, appCurrencyCostLabel, layout.NewSpacer())
calculatorContainer := container.NewVBox(identityTypeLabel, identityTypeSelectorCentered, widget.NewSeparator(), desiredDurationLabel, daysToFundSelectorCentered, widget.NewSeparator(), costLabel, appCurrencyRow)
return true, calculatorContainer, nil
}
parametersExist, calculatorContainer, err := getCalculatorContainer()
if (err != nil) {
setErrorEncounteredPage(window, err, previousPage)
return
}
if (parametersExist == false){
description1 := getBoldLabelCentered("Network parameters are not downloaded.")
description2 := getLabelCentered("Please wait for them to download.")
//TODO: Add page to monitor download progress.
refreshButton := getWidgetCentered(widget.NewButtonWithIcon("Refresh", theme.ViewRefreshIcon(), currentPage))
page := container.NewVBox(title, backButton, widget.NewSeparator(), subtitle, widget.NewSeparator(), description1, description2, refreshButton)
setPageContent(page, window)
return
}
description1 := getLabelCentered("Calculate identity balance pricing below.")
description2 := getLabelCentered("All mate and host identities must be funded before broadcasting profiles.")
description3 := getLabelCentered("You can always increase your identity balance later.")
page := container.NewVBox(title, backButton, widget.NewSeparator(), subtitle, widget.NewSeparator(), description1, description2, description3, widget.NewSeparator(), calculatorContainer)
setPageContent(page, window)
}
// This page is used to show how much it costs to fund messages
// Users can use this to determine how much credit to send to their account
func setViewMessagePricingCalculatorPage(window fyne.Window, messageType string, messageDuration int64, numberOfMessages int, previousPage func()){
if (messageType != "Image" && messageType != "Text"){
setErrorEncounteredPage(window, errors.New("setViewMessagePricingCalculatorPage called with invalid messageType: " + messageType), previousPage)
return
}
if (messageDuration != 2 && messageDuration != 14){
setErrorEncounteredPage(window, errors.New("setViewMessagePricingCalculatorPage called with invalid messageDuration."), previousPage)
return
}
if (numberOfMessages != 10 && numberOfMessages != 100 && numberOfMessages != 1000){
setErrorEncounteredPage(window, errors.New("setViewMessagePricingCalculatorPage called with invalid numberOfMessages."), previousPage)
return
}
currentPage := func(){setViewMessagePricingCalculatorPage(window, messageType, messageDuration, numberOfMessages, previousPage)}
title := getPageTitleCentered("Message Pricing Calculator")
backButton := getBackButtonCentered(previousPage)
subtitle := getPageSubtitleCentered("Calculate Message Costs")
appNetworkType, err := getAppNetworkType.GetAppNetworkType()
if (err != nil) {
setErrorEncounteredPage(window, err, previousPage)
return
}
//Outputs:
// -bool: Parameters exist
// -*fyne.Container: Calculator section
// -error
getPricingCalculatorSection := func()(bool, *fyne.Container, error){
messageTypeLabel := getBoldLabelCentered("Message Type:")
messageTypesList := []string{"Image", "Text"}
messageTypeSelector := widget.NewSelect(messageTypesList, func(newMessageType string){
if (newMessageType == messageType){
return
}
setViewMessagePricingCalculatorPage(window, newMessageType, messageDuration, numberOfMessages, previousPage)
})
messageTypeSelector.Selected = messageType
messageTypeSelectorCentered := getWidgetCentered(messageTypeSelector)
messageDurationLabel := getBoldLabelCentered("Message Duration:")
durationOptionsList := []string{"2 days", "2 weeks"}
durationSelectFunction := func(newDuration string){
if (newDuration == "2 days"){
if (messageDuration == 2){
return
}
setViewMessagePricingCalculatorPage(window, messageType, 2, numberOfMessages, previousPage)
return
}
if (newDuration == "2 weeks"){
if (messageDuration == 14){
return
}
setViewMessagePricingCalculatorPage(window, messageType, 14, numberOfMessages, previousPage)
return
}
}
durationSelector := widget.NewSelect(durationOptionsList, durationSelectFunction)
if (messageDuration == 2){
durationSelector.Selected = "2 days"
} else if (messageDuration == 14){
durationSelector.Selected = "2 weeks"
}
durationSelectorCentered := getWidgetCentered(durationSelector)
numberOfMessagesLabel := getBoldLabelCentered("Number Of Messages:")
numberOfMessagesOptionsList := []string{"10 Messages", "100 Messages", "1000 Messages"}
numberOfMessagesSelector := widget.NewSelect(numberOfMessagesOptionsList, func(newNumberOfMessages string){
if (newNumberOfMessages == "10 Messages"){
if (numberOfMessages == 10){
return
}
setViewMessagePricingCalculatorPage(window, messageType, messageDuration, 10, previousPage)
return
}
if (newNumberOfMessages == "100 Messages"){
if (numberOfMessages == 100){
return
}
setViewMessagePricingCalculatorPage(window, messageType, messageDuration, 100, previousPage)
return
}
if (newNumberOfMessages == "1000 Messages"){
if (numberOfMessages == 1000){
return
}
setViewMessagePricingCalculatorPage(window, messageType, messageDuration, 1000, previousPage)
return
}
})
if (numberOfMessages == 10){
numberOfMessagesSelector.Selected = "10 Messages"
} else if (numberOfMessages == 100){
numberOfMessagesSelector.Selected = "100 Messages"
} else if (numberOfMessages == 1000){
numberOfMessagesSelector.Selected = "1000 Messages"
}
numberOfMessagesSelectorCentered := getWidgetCentered(numberOfMessagesSelector)
costLabel := getBoldLabelCentered("Cost:")
currentTime := time.Now().Unix()
parametersExist, messageKilobyteGoldCostPerDay, err := getParameters.GetMessageKilobyteGoldCostPerDay(appNetworkType, currentTime)
if (err != nil) { return false, nil, err }
if (parametersExist == false){
return false, nil, nil
}
getMessageSizeKilobytes := func()int{
//TODO: Fix below numbers
if (messageType == "Text"){
return 2
}
// messageType == "Image"
return 22
}
messageSizeKilobytes := getMessageSizeKilobytes()
gramsOfGoldCost := messageKilobyteGoldCostPerDay * float64(messageSizeKilobytes) * float64(messageDuration) * float64(numberOfMessages)
kilogramsOfGoldCost := gramsOfGoldCost/1000
exchangeRatesExist, err := convertCurrencies.CheckIfExchangeRatesAreDownloaded(appNetworkType)
if (err != nil) { return false, nil, err }
if (exchangeRatesExist == false){
return false, nil, nil
}
getAppCurrencyCode := func()(string, error){
exists, appCurrencyCode, err := globalSettings.GetSetting("Currency")
if (err != nil) { return "", err }
if (exists == false){
return "USD", nil
}
return appCurrencyCode, nil
}
appCurrencyCode, err := getAppCurrencyCode()
if (err != nil) { return false, nil, err }
parametersExist, appCurrencyCost, err := convertCurrencies.ConvertKilogramsOfGoldToAnyCurrency(appNetworkType, kilogramsOfGoldCost, appCurrencyCode)
if (err != nil) { return false, nil, err }
if (parametersExist == false){
return false, nil, nil
}
_, appCurrencyUnitsSymbol, err := currencies.GetCurrencyInfoFromCurrencyCode(appCurrencyCode)
if (err != nil) { return false, nil, err }
appCurrencyCostString := helpers.ConvertFloat64ToStringRounded(appCurrencyCost, 2)
appCurrencySymbolButton := widget.NewButton(appCurrencyUnitsSymbol, func(){
setChangeAppCurrencyPage(window, currentPage)
})
appCurrencyLabel := getBoldLabel(appCurrencyCostString + " " + appCurrencyCode)
appCurrencyRow := container.NewHBox(layout.NewSpacer(), appCurrencySymbolButton, appCurrencyLabel, layout.NewSpacer())
pricingCalculatorSection := container.NewVBox(messageTypeLabel, messageTypeSelectorCentered, widget.NewSeparator(), messageDurationLabel, durationSelectorCentered, widget.NewSeparator(), numberOfMessagesLabel, numberOfMessagesSelectorCentered, widget.NewSeparator(), costLabel, appCurrencyRow)
return true, pricingCalculatorSection, nil
}
parametersExist, pricingCalculatorSection, err := getPricingCalculatorSection()
if (err != nil) {
setErrorEncounteredPage(window, err, previousPage)
return
}
if (parametersExist == false){
description1 := getBoldLabelCentered("Network parameters are not downloaded.")
description2 := getLabelCentered("Please wait for them to download.")
//TODO: Add page to monitor download progress.
refreshButton := getWidgetCentered(widget.NewButtonWithIcon("Refresh", theme.ViewRefreshIcon(), currentPage))
page := container.NewVBox(title, backButton, widget.NewSeparator(), subtitle, widget.NewSeparator(), description1, description2, refreshButton)
setPageContent(page, window)
return
}
description := getLabelCentered("Use this calculator to estimate message costs.")
page := container.NewVBox(title, backButton, widget.NewSeparator(), subtitle, widget.NewSeparator(), description, widget.NewSeparator(), pricingCalculatorSection)
setPageContent(page, window)
}
func setIncreaseMyIdentityBalancePage(window fyne.Window, myIdentityType string, daysToFund int, previousPage func()){
if (myIdentityType != "Mate" && myIdentityType != "Host"){
setErrorEncounteredPage(window, errors.New("setIncreaseMyIdentityBalancePage called with invalid myIdentityType: " + myIdentityType), previousPage)
}
currentPage := func(){setIncreaseMyIdentityBalancePage(window, myIdentityType, daysToFund, previousPage)}
title := getPageTitleCentered("Increase Identity Balance")
backButton := getBackButtonCentered(previousPage)
appNetworkType, err := getAppNetworkType.GetAppNetworkType()
if (err != nil) {
setErrorEncounteredPage(window, err, previousPage)
return
}
//Outputs:
// -bool: Parameters exist
// -*fyne.Container
// -error
getPageContent := func()(bool, *fyne.Container, error){
description := getLabelCentered("Choose the amount of time to add to your identity balance.")
myCreditBalanceLabel := getItalicLabelCentered("My Credit Balance:")
getCurrentAppCurrency := func()(string, error){
exists, currentAppCurrency, err := globalSettings.GetSetting("Currency")
if (err != nil) { return "", err }
if (exists == false){
return "USD", nil
}
return currentAppCurrency, nil
}
currentAppCurrencyCode, err := getCurrentAppCurrency()
if (err != nil){ return false, nil, err }
_, appCurrencySymbol, err := currencies.GetCurrencyInfoFromCurrencyCode(currentAppCurrencyCode)
if (err != nil){ return false, nil, err }
appCurrencySymbolButton1 := widget.NewButton(appCurrencySymbol, func(){
setChangeAppCurrencyPage(window, currentPage)
})
parametersExist, appCurrencyAccountCreditBalance, err := myAccountCredit.GetMyCreditAccountBalanceInAnyCurrency(myIdentityType, appNetworkType, currentAppCurrencyCode)
if (err != nil){ return false, nil, err }
if (parametersExist == false){
return false, nil, nil
}
getAccountBalanceText := func()(string, error){
if (parametersExist == false){
return "Unknown", nil
}
appCurrencyAccountCreditBalanceString := helpers.ConvertFloat64ToStringRounded(appCurrencyAccountCreditBalance, 3)
return appCurrencyAccountCreditBalanceString, nil
}
accountBalanceText, err := getAccountBalanceText()
if (err != nil){ return false, nil, err }
appCurrencyAccountCreditBalanceLabel := getBoldLabel(accountBalanceText + " " + currentAppCurrencyCode)
myCreditBalanceRow := container.NewHBox(layout.NewSpacer(), appCurrencySymbolButton1, appCurrencyAccountCreditBalanceLabel, layout.NewSpacer())
manageMyBalanceButton := getWidgetCentered(widget.NewButtonWithIcon("Manage", theme.VisibilityIcon(), func(){
setViewMyAccountCreditPage(window, myIdentityType, currentPage)
}))
currentTime := time.Now().Unix()
selectTimeDescription := getLabelCentered("Select the amount of time to fund.")
//TODO: Make clear that there is a minimum amount that must be initially sent and show that value in the GUI
timeOptionsList := []string{"1 Day", "1 Week", "1 Month", "3 Months", "6 Months"}
timeToFundSelector := widget.NewSelect(timeOptionsList, func(response string){
getNewDaysToFund := func()int{
if (response == "1 Day"){
return 1
}
if (response == "1 Week"){
return 7
}
if (response == "1 Month"){
return 30
}
if (response == "3 Months"){
return 90
}
// response == "6 Months"
return 180
}
newDaysToFund := getNewDaysToFund()
if (newDaysToFund == daysToFund){
return
}
setIncreaseMyIdentityBalancePage(window, myIdentityType, newDaysToFund, previousPage)
})
if (daysToFund == 1){
timeToFundSelector.Selected = "1 Day"
} else if (daysToFund == 7){
timeToFundSelector.Selected = "1 Week"
} else if (daysToFund == 30){
timeToFundSelector.Selected = "1 Month"
} else if (daysToFund == 90){
timeToFundSelector.Selected = "3 Months"
} else if (daysToFund == 180){
timeToFundSelector.Selected = "6 Months"
}
timeToFundSelectorCentered := getWidgetCentered(timeToFundSelector)
costLabel := getLabelCentered("Cost:")
parametersExist, gramsOfGoldCostPerDay, err := getParameters.GetIdentityBalanceGoldCostPerDay(appNetworkType, myIdentityType, currentTime)
if (err != nil){ return false, nil, err }
if (parametersExist == false){
return false, nil, nil
}
appCurrencySymbolButton2 := widget.NewButton(appCurrencySymbol, func(){
setChangeAppCurrencyPage(window, currentPage)
})
costInKilogramsOfGold := (gramsOfGoldCostPerDay/1000) * float64(daysToFund)
parametersExist, appCurrencyCost, err := convertCurrencies.ConvertKilogramsOfGoldToAnyCurrency(appNetworkType, costInKilogramsOfGold, currentAppCurrencyCode)
if (err != nil){ return false, nil, err }
appCurrencyCostString := helpers.ConvertFloat64ToStringRounded(appCurrencyCost, 3)
appCurrencyLabel := getBoldLabel(appCurrencyCostString + " " + currentAppCurrencyCode)
costRow := container.NewHBox(layout.NewSpacer(), appCurrencySymbolButton2, appCurrencyLabel, layout.NewSpacer())
confirmButton := getWidgetCentered(widget.NewButtonWithIcon("Confirm Payment", theme.ConfirmIcon(), func(){
//TODO
showUnderConstructionDialog(window)
}))
pageContent := container.NewVBox(description, widget.NewSeparator(), myCreditBalanceLabel, myCreditBalanceRow, manageMyBalanceButton, widget.NewSeparator(), selectTimeDescription, timeToFundSelectorCentered, widget.NewSeparator(), costLabel, costRow, widget.NewSeparator(), confirmButton)
return true, pageContent, nil
}
parametersExist, pageContent, err := getPageContent()
if (err != nil){
setErrorEncounteredPage(window, err, previousPage)
return
}
if (parametersExist == false){
description1 := getBoldLabelCentered("Seekia is missing the network parameters.")
description2 := getLabelCentered("You must wait for them to download.")
//TODO: View progress page
refreshButton := getWidgetCentered(widget.NewButtonWithIcon("Refresh", theme.ViewRefreshIcon(), currentPage))
page := container.NewVBox(title, backButton, widget.NewSeparator(), description1, description2, refreshButton)
setPageContent(page, window)
return
}
page := container.NewVBox(title, backButton, widget.NewSeparator(), pageContent)
setPageContent(page, window)
}