From d37a3e31e86cd1d61220c71fe8c9622d96794f9c Mon Sep 17 00:00:00 2001 From: Yoshi Askharoun Date: Sun, 31 Aug 2025 18:13:01 -0700 Subject: [PATCH] Add donation request dialog --- ZuneModdingHelper/Pages/ModsPage.xaml.cs | 65 +++++++++++++++++++++++- ZuneModdingHelper/Services/Settings.cs | 23 +++++++++ 2 files changed, 87 insertions(+), 1 deletion(-) diff --git a/ZuneModdingHelper/Pages/ModsPage.xaml.cs b/ZuneModdingHelper/Pages/ModsPage.xaml.cs index 30804c7..da49e73 100644 --- a/ZuneModdingHelper/Pages/ModsPage.xaml.cs +++ b/ZuneModdingHelper/Pages/ModsPage.xaml.cs @@ -1,12 +1,16 @@ using CommunityToolkit.Mvvm.DependencyInjection; +using CommunityToolkit.Mvvm.Input; using CommunityToolkit.Mvvm.Messaging; using OwlCore.AbstractUI.Models; using OwlCore.ComponentModel; +using System.Net.NetworkInformation; +using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using ZuneModCore; using ZuneModCore.Services; using ZuneModdingHelper.Messages; +using ZuneModdingHelper.Services; namespace ZuneModdingHelper.Pages { @@ -18,10 +22,12 @@ namespace ZuneModdingHelper.Pages private const string MOD_MANAGER_TITLE = "MOD MANAGER"; private readonly IModCoreConfig _modConfig; + private readonly Settings _settings; - public ModsPage(IModCoreConfig modConfig) + public ModsPage(IModCoreConfig modConfig, Settings settings) { _modConfig = modConfig; + _settings = settings; InitializeComponent(); ModList.ItemsSource = ModManager.ModFactories; @@ -89,6 +95,7 @@ namespace ZuneModdingHelper.Pages { Title = MOD_MANAGER_TITLE, Description = $"Successfully applied '{modTitle}'", + OnAction = new AsyncRelayCommand(ShowDonationRequestDialog) })); } @@ -153,5 +160,61 @@ namespace ZuneModdingHelper.Pages modFactory = (sender as FrameworkElement)?.DataContext as IModFactory; return modFactory is not null; } + + private async Task ShowDonationRequestDialog(bool _) + { + // Close success dialog + WeakReferenceMessenger.Default.Send(); + + // Don't bother users if they're offline or the site is inaccessible + try + { + var ping = new Ping(); + var result = await ping.SendPingAsync(App.DonateUri.Host); + if (result.Status is not IPStatus.Success) + return; + } + catch + { + return; + } + + // Ask for donations every once in a while (but only when mod is successful) + if (_settings.NextDonationRequestTime is not null && _settings.NextDonationRequestTime <= System.DateTimeOffset.UtcNow) + { + // Set next request time + var nextRequestTime = _settings.NextDonationRequestTime.Value; + _settings.NextDonationRequestTime = _settings.DonationRequestInterval switch + { + DonationRequestInterval.EveryMod => nextRequestTime, + DonationRequestInterval.OneWeek => nextRequestTime.AddDays(7), + DonationRequestInterval.TwoWeeks => nextRequestTime.AddMonths(14), + DonationRequestInterval.OneMonth => nextRequestTime.AddMonths(1), + DonationRequestInterval.ThreeMonths => nextRequestTime.AddMonths(3), + DonationRequestInterval.SixMonths => nextRequestTime.AddMonths(6), + DonationRequestInterval.OneYear => nextRequestTime.AddYears(1), + _ => nextRequestTime.AddMonths(1), + }; + + // Show request dialog + WeakReferenceMessenger.Default.Send(new ShowDialogMessage(new() + { + Title = "THANK YOU FOR USING ZMH", + Description = $"{App.Title} is free software, but it still takes money and a lot of time to write, support, and distribute it.\r\n\r\n" + + "If ZMH has been helpful for you, please consider supporting this and other ZuneDev projects with a donation to the author.", + AffirmativeText = "DONATE", + NegativeText = "REMIND ME LATER", + ShowNegativeButton = true, + OnAction = new AsyncRelayCommand(openDonation => + { + if (openDonation) + App.OpenDonationLink(); + + WeakReferenceMessenger.Default.Send(); + return Task.CompletedTask; + }) + })); + } + } } } diff --git a/ZuneModdingHelper/Services/Settings.cs b/ZuneModdingHelper/Services/Settings.cs index ab9b460..52d0b5e 100644 --- a/ZuneModdingHelper/Services/Settings.cs +++ b/ZuneModdingHelper/Services/Settings.cs @@ -25,4 +25,27 @@ public class Settings(IModifiableFolder folder) : SettingsBase(folder, SystemTex get => GetSetting(() => Mod.DefaultZuneInstallDir); set => SetSetting(value); } + + public DateTimeOffset? NextDonationRequestTime + { + get => GetSetting(() => DateTimeOffset.UtcNow); + set => SetSetting(value); + } + + public DonationRequestInterval DonationRequestInterval + { + get => GetSetting(() => DonationRequestInterval.OneMonth); + set => SetSetting(value); + } +} + +public enum DonationRequestInterval +{ + EveryMod, + OneWeek, + TwoWeeks, + OneMonth, + ThreeMonths, + SixMonths, + OneYear }