diff --git a/Models/AppSettings.cs b/Models/AppSettings.cs
index ce7412f..a376a4d 100644
--- a/Models/AppSettings.cs
+++ b/Models/AppSettings.cs
@@ -22,6 +22,16 @@ static Settings()
///
public string? DataLocation { get; set; }
+ ///
+ /// Discord WebHook URL for backups.
+ ///
+ public string? DiscordWebhookURL { get; set; }
+
+ ///
+ /// Discord WebHook backups toggle state.
+ ///
+ public bool DiscordWebhookEnabled { get; set; }
+
///
/// Automatically copy newly detected save codes as you play.
///
diff --git a/Models/Entry.cs b/Models/Entry.cs
index 24d48a2..001519c 100644
--- a/Models/Entry.cs
+++ b/Models/Entry.cs
@@ -34,12 +34,16 @@ internal class Entry
public DateTime Timestamp;
public string Content;
+ [JsonProperty("pc")]
+ public int PlayerCount;
public string? Players;
public string[]? RTerrors;
public string? RType;
+ public ToNRoundType RT;
public ToNRoundResult RResult;
+ [JsonIgnore] public History? Parent;
[JsonIgnore] public bool Fresh;
[JsonIgnore] public int Length => Content.Length;
@@ -58,7 +62,7 @@ public override string ToString()
if (Settings.Get.SaveRoundInfo && Settings.Get.ShowWinLose)
{
sb.Append('[');
- sb.Append(RResult == ToNRoundResult.R ? ' ' : RResult.ToString());
+ sb.Append(RResult);
sb.Append("] ");
}
@@ -73,11 +77,11 @@ public override string ToString()
return sb.ToString();
}
- public string GetTooltip(bool showPlayers, bool showTerrors)
+ public string GetTooltip(bool showPlayers, bool showTerrors, bool showNote = true)
{
StringBuilder sb = new StringBuilder();
sb.Append(Timestamp.ToString("F"));
- if (!string.IsNullOrEmpty(Note))
+ if (!string.IsNullOrEmpty(Note) && showNote)
{
sb.AppendLine();
sb.AppendLine();
@@ -89,7 +93,7 @@ public string GetTooltip(bool showPlayers, bool showTerrors)
sb.AppendLine();
sb.AppendLine();
- sb.AppendLine("Round info: " + (RResult == ToNRoundResult.W ? "Survived" : "Died"));
+ // sb.AppendLine("Round info: " + (RResult == ToNRoundResult.W ? "Survived" : "Died"));
if (!string.IsNullOrEmpty(RType))
sb.AppendLine("Round type: " + RType);
diff --git a/Models/History.cs b/Models/History.cs
index 8d75a90..b957e1d 100644
--- a/Models/History.cs
+++ b/Models/History.cs
@@ -1,6 +1,8 @@
using Newtonsoft.Json;
using System.Globalization;
+using LogContext = ToNSaveManager.Utils.LogWatcher.LogContext;
+
namespace ToNSaveManager.Models
{
internal class History : IComparable
@@ -10,6 +12,8 @@ internal class History : IComparable
public DateTime Timestamp = DateTime.MinValue;
public bool IsCustom = false;
+ public string? DisplayName = string.Empty;
+
[JsonConstructor]
private History() { }
@@ -27,6 +31,11 @@ public History(string name, DateTime timestamp)
IsCustom = true;
}
+ public void SetLogContext(LogContext context)
+ {
+ DisplayName = context.DisplayName;
+ }
+
public void SetLogKey(string logKey)
{
if (IsCustom) return;
diff --git a/Models/ToNIndex.cs b/Models/ToNIndex.cs
index 6f18015..35f8e6b 100644
--- a/Models/ToNIndex.cs
+++ b/Models/ToNIndex.cs
@@ -1,4 +1,4 @@
-using System.Diagnostics;
+using Newtonsoft.Json;
namespace ToNSaveManager.Models
{
@@ -93,6 +93,9 @@ public string GetNames(string separator = ", ")
"RUN" , "走れ!", // The meatball man
"8 Pages" , "8ページ",
+ // Events
+ "Cold Night" , "冷たい夜", // Winterfest
+
// Beyond's favorite
"Custom" , "カスタム", // IGNORE SAVES FOR THIS ONE
};
@@ -115,13 +118,40 @@ static ToNRoundType GetRoundType(string raw)
raw = raw.Replace(' ', '_').Replace("8", "Eight");
return Enum.TryParse(typeof(ToNRoundType), raw, out object? result) && result != null ? (ToNRoundType)result : ToNRoundType.Unknown;
}
+
+ internal static uint GetRoundColorFromType(ToNRoundType RoundType) => RoundTypeColors.ContainsKey(RoundType) ? RoundTypeColors[RoundType] : 16721714;
+
+ internal static readonly Dictionary RoundTypeColors = new Dictionary()
+ {
+ { ToNRoundType.Unknown, 16721714 },
+ { ToNRoundType.Classic, 0xFFFFFF },
+ { ToNRoundType.Fog, 0x808486 },
+ { ToNRoundType.Punished, 0xFFF800 },
+ { ToNRoundType.Sabotage, 0x3BF37D },
+ { ToNRoundType.Cracked, 0xFF00D3 },
+ { ToNRoundType.Bloodbath, 0xF51313 },
+
+ { ToNRoundType.Midnight, 0xE23232 },
+ { ToNRoundType.Alternate, 0xF1F1F1 },
+
+ { ToNRoundType.Mystic_Moon, 0xB0DEF9 },
+ { ToNRoundType.Twilight, 0xF8A900 },
+ { ToNRoundType.Blood_Moon, 0xF51313 },
+ { ToNRoundType.Solstice, 0x3BF3B3 },
+
+ { ToNRoundType.RUN, 0xC15E3D },
+ { ToNRoundType.Eight_Pages, 0xFFFFFF },
+ { ToNRoundType.Custom, 0x000000 }, // Ignored
+
+ { ToNRoundType.Cold_Night, 0xA37BE4 },
+ };
}
public enum ToNRoundResult
{
R, // Respawn
W, // Win
- L, // Lose
+ D, // Leaving
}
public enum ToNRoundType
@@ -140,7 +170,10 @@ public enum ToNRoundType
Mystic_Moon, Blood_Moon, Twilight, Solstice,
// Special // Replace 8 with Eight
- RUN, Eight_Pages, Custom
+ RUN, Eight_Pages, Custom,
+
+ // Events
+ Cold_Night
}
internal class ToNIndex
diff --git a/README.md b/README.md
index 9c0d655..3f58af8 100644
--- a/README.md
+++ b/README.md
@@ -26,10 +26,11 @@
- `Auto Clipboard Copy` Automatically copy new save codes to clipboard.
- `Collect Player Names` Save codes will show players that were in the instance.
- `XSOverlay Popup` XSOverlay notifications when new save codes are detected.
-- `Play Audio` Play a notification audio when a new save is detected.
+- `Play Sound` Play a notification audio when a new save is detected.
- Double Click to select a custom audio file. (Only '.wav' files)
- Right Click to reset audio file back to 'default.wav'
- `Colorful Objectives` Items in the 'Objectives' window will show colors that correspond to those of the items in the game.
+- `Auto Discord Backup` Uses a [discord webhook](##how-to-properly-configure-automatic-discord-backup-using-webhooks) to automatically upload a backup of your new codes to a discord channel as you play.
- `Check For Updates` When clicked, it will check this github repo for new releases, and prompt you to try an automatic update.
Preview Image
@@ -41,6 +42,7 @@
- ### Save Codes (Right Panel)
* `Add to` Lets you save or favorite this code to a separated custom collection with a name of your choice.
* `Edit Note` You can attach a note to this save code, so you can recognize it better.
+ * `Backup` Forces a backup upload to Discord if **Auto Discord Backup** is configured on settings.
* `Delete` Deletes just this save code from the database.
### Objectives Window
@@ -71,6 +73,26 @@
>
>
+> ## How to properly configure Automatic Discord Backup using Webhooks?
+> You can set a Discord webhook url to automatically upload your codes to a discord channel.
+>
+> - Just go to your preferred channel on your discord server.
+> - Click **Edit Channel** and then go to **Integrations**.
+> - Add a webhook integration to this channel. *You can give it a name and a profile picture*.
+> - Copy the webhook url.
+> - Open settings on the Save Manager app.
+> - Enable `Auto Discord Backup`, you will see a text input popup.
+> - Paste your webhook url in the text field.
+> - Click **save**.
+>
+> NOTE: If you want to test this functionality, you can right click on a save entry then click **Backup**. If everything is right, save will be uploaded to the discord channel.
+>
+> Show Discord Screenshots
+>
+>
+>
+>
+
> ## Why is the .exe so big? >100MB
> The exe is bundled with the .NET runtime that it's required to run the program. Using a command line argument for dotnet publishing: `--self-contained true -p:PublishSingleFile=true`
> This adds size to the file, but ensures that the program runs independently without relying on a previous .NET installation.
@@ -87,8 +109,14 @@
> We are allowed to read these files since it does not modify or alter the game in any way.
> **This is not a mod or a cheat.**
+> ### Please do NOT message Beyond about suggestions or problems with this tool.
+> You can report problems or suggestions under the [Issues](https://github.com/ChrisFeline/ToNSaveManager/issues) tab on this repo. Alternatively see contact information below.
+
# 📫 Contact:
> **Discord:** [@Kittenji](https://discord.gg/HGk2RQX)
> **VRChat:** [Kittenji](https://vrchat.com/home/user/usr_7ac745b8-e50e-4c9c-95e5-8e7e3bcde682)
> ## Say hi if you see me playing [Terrors of Nowhere](https://vrchat.com/home/world/wrld_a61cdabe-1218-4287-9ffc-2a4d1414e5bd)!
->
\ No newline at end of file
+>
+
+# ❤️ Support:
+> If you want to support the development of this tool you can [Buy Me A Coffee ♥](https://ko-fi.com/kittenji) on ko-fi.
\ No newline at end of file
diff --git a/Resources/Webhook/screenshot_0.png b/Resources/Webhook/screenshot_0.png
new file mode 100644
index 0000000..0f064cd
Binary files /dev/null and b/Resources/Webhook/screenshot_0.png differ
diff --git a/Resources/Webhook/screenshot_1.png b/Resources/Webhook/screenshot_1.png
new file mode 100644
index 0000000..b47563e
Binary files /dev/null and b/Resources/Webhook/screenshot_1.png differ
diff --git a/Resources/Webhook/screenshot_2.png b/Resources/Webhook/screenshot_2.png
new file mode 100644
index 0000000..f25c298
Binary files /dev/null and b/Resources/Webhook/screenshot_2.png differ
diff --git a/Resources/settings.png b/Resources/settings.png
index aac8c0d..a6ac865 100644
Binary files a/Resources/settings.png and b/Resources/settings.png differ
diff --git a/Resources/support_icon.png b/Resources/support_icon.png
new file mode 100644
index 0000000..126ce44
Binary files /dev/null and b/Resources/support_icon.png differ
diff --git a/ToNSaveManager.csproj b/ToNSaveManager.csproj
index 8c70228..ecc2ce3 100644
--- a/ToNSaveManager.csproj
+++ b/ToNSaveManager.csproj
@@ -52,4 +52,19 @@
+
+
+ True
+ True
+ Resources.resx
+
+
+
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+
+
+
\ No newline at end of file
diff --git a/Utils/Discord/DSWebHook.cs b/Utils/Discord/DSWebHook.cs
new file mode 100644
index 0000000..0c28e09
--- /dev/null
+++ b/Utils/Discord/DSWebHook.cs
@@ -0,0 +1,147 @@
+using System.Text;
+using ToNSaveManager.Models;
+using Newtonsoft.Json;
+using System.Globalization;
+using System.Text.RegularExpressions;
+
+namespace ToNSaveManager.Utils.Discord
+{
+ using Models;
+
+ internal class Payload
+ {
+ [JsonProperty("embeds")]
+ public Embed[] Embeds = new Embed[1] { new Embed() };
+
+ [JsonIgnore]
+ public Embed Embed => Embeds[0];
+ }
+
+ internal static class DSWebHook
+ {
+ static Entry? LastEntry;
+
+ static readonly Embed[] Embeds = new Embed[1];
+
+ static readonly Payload PayloadData = new Payload();
+ static Embed EmbedData => PayloadData.Embed;
+
+ static readonly JsonSerializerSettings JsonSettings = new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore };
+
+ static readonly Queue EntryQueue = new Queue();
+ static bool IsSending = false;
+
+ internal static void Send(Entry entry, bool ignoreDuplicate = false)
+ {
+ if (!Settings.Get.DiscordWebhookEnabled) return;
+
+ string? webhookUrl = Settings.Get.DiscordWebhookURL;
+ if (string.IsNullOrEmpty(webhookUrl)) return;
+
+ if (!ignoreDuplicate && LastEntry != null && LastEntry.Content == entry.Content) return;
+ LastEntry = entry;
+
+ EntryQueue.Enqueue(entry);
+ if (IsSending) return;
+
+ _ = Send(webhookUrl);
+ }
+
+ private static async Task Send(string webhookUrl)
+ {
+ IsSending = true;
+
+ try
+ {
+ using (HttpClient httpClient = new HttpClient())
+ {
+ while (EntryQueue.Count > 0)
+ {
+ Entry entry = EntryQueue.Dequeue();
+ DateTime time = entry.Timestamp;
+
+ if (EmbedData.Footer == null)
+ {
+ EmbedData.Footer = new EmbedFooter()
+ {
+ IconUrl = "https://github.com/ChrisFeline/ToNSaveManager/blob/main/Resources/xs_icon.png?raw=true",
+ ProxyIconUrl = "https://github.com/ChrisFeline/ToNSaveManager/blob/main/Resources/xs_icon.png?raw=true",
+ Text = "Terrors of Nowhere: Save Manager"
+ };
+ }
+
+ EmbedData.Description = string.Empty;
+ EmbedData.Timestamp = time;
+ EmbedData.Color = TerrorMatrix.GetRoundColorFromType(entry.RT);
+
+ if (entry.Parent != null && !string.IsNullOrEmpty(entry.Parent.DisplayName))
+ {
+ // if (EmbedData.Description.Length > 0) EmbedData.Description += "\n";
+ EmbedData.Description += "**Username**: `" + entry.Parent.DisplayName + "`";
+ }
+
+ if (!string.IsNullOrEmpty(entry.RType))
+ {
+ if (EmbedData.Description.Length > 0) EmbedData.Description += "\n";
+ EmbedData.Description += "**Round Type**: `" + entry.RType + "`";
+ }
+
+ if (entry.RTerrors != null && entry.RTerrors.Length > 0)
+ {
+ if (EmbedData.Description.Length > 0) EmbedData.Description += "\n";
+ EmbedData.Description += "**Terrors in Round**: `" + string.Join("`, `", entry.RTerrors) + "`";
+ }
+
+ if (entry.PlayerCount > 0)
+ {
+ if (EmbedData.Description.Length > 0) EmbedData.Description += "\n";
+ EmbedData.Description += $"**Player Count**: `{entry.PlayerCount}`";
+ }
+
+ string payloadData = JsonConvert.SerializeObject(PayloadData, JsonSettings);
+
+ MultipartFormDataContent form = new MultipartFormDataContent();
+ // Append file data
+ byte[] data = Encoding.Default.GetBytes(entry.Content);
+ form.Add(new ByteArrayContent(data, 0, data.Length), "Document", $"TON_BACKUP_{time.Year}_{time.Month}_{time.Day}_{time.Hour.ToString("00")}{time.Minute.ToString("00")}{time.Second.ToString("00")}.txt");
+ // Append json
+ form.Add(new StringContent(payloadData, Encoding.UTF8, "application/json"), "payload_json");
+ _ = await httpClient.PostAsync(webhookUrl, form);
+
+ // Wait a second before send the next message
+ if (EntryQueue.Count > 0) await Task.Delay(1000);
+ }
+ }
+ }
+ catch (Exception) { }
+
+ IsSending = false;
+ }
+
+ #region Validation
+ private static Regex WebhookUrlRegex = new Regex(@"^.*(discord|discordapp)\.com\/api\/webhooks\/([\d]+)\/([a-z0-9_-]+)$", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
+
+ internal static bool ValidateURL(string webhookUrl)
+ {
+ if (string.IsNullOrWhiteSpace(webhookUrl))
+ return false;
+
+ Match match = WebhookUrlRegex.Match(webhookUrl);
+ if (match != null)
+ {
+ // ensure that the first group is a ulong, set the _webhookId
+ // 0th group is always the entire match, and 1 is the domain; so start at index 2
+ if (!(match.Groups[2].Success && ulong.TryParse(match.Groups[2].Value, NumberStyles.None, CultureInfo.InvariantCulture, out ulong webhookId)) || webhookId == 0)
+ return false;
+
+ if (!match.Groups[3].Success)
+ return false;
+
+ return true;
+ }
+
+ return false;
+ }
+ #endregion
+ }
+}
diff --git a/Utils/Discord/Models/Embed.cs b/Utils/Discord/Models/Embed.cs
new file mode 100644
index 0000000..140e239
--- /dev/null
+++ b/Utils/Discord/Models/Embed.cs
@@ -0,0 +1,45 @@
+using Newtonsoft.Json;
+
+namespace ToNSaveManager.Utils.Discord.Models
+{
+ internal class Embed
+ {
+ [JsonProperty("title")]
+ public string? Title { get; set; }
+
+ [JsonProperty("description")]
+ public string? Description { get; set; }
+
+ [JsonProperty("url")]
+ public string? Url { get; set; }
+
+ [JsonProperty("color")]
+ public uint Color { get; set; } = 16721714;
+
+ [JsonProperty("timestamp")]
+ public DateTimeOffset? Timestamp { get; set; }
+
+ [JsonProperty("footer")]
+ public EmbedFooter? Footer { get; set; }
+
+ /*
+ [JsonProperty("author")]
+ public EmbedAuthor Author { get; set; }
+
+ [JsonProperty("video")]
+ public EmbedVideo Video { get; set; }
+
+ [JsonProperty("thumbnail")]
+ public EmbedThumbnail Thumbnail { get; set; }
+
+ [JsonProperty("image")]
+ public EmbedImage Image { get; set; }
+
+ [JsonProperty("provider")]
+ public EmbedProvider Provider { get; set; }
+
+ [JsonProperty("fields")]
+ public EmbedField[] Fields { get; set; }
+ */
+ }
+}
diff --git a/Utils/Discord/Models/EmbedFooter.cs b/Utils/Discord/Models/EmbedFooter.cs
new file mode 100644
index 0000000..9f4bbfd
--- /dev/null
+++ b/Utils/Discord/Models/EmbedFooter.cs
@@ -0,0 +1,16 @@
+using Newtonsoft.Json;
+
+namespace ToNSaveManager.Utils.Discord.Models
+{
+ internal class EmbedFooter
+ {
+ [JsonProperty("text")]
+ public string? Text { get; set; }
+
+ [JsonProperty("icon_url")]
+ public string? IconUrl { get; set; }
+
+ [JsonProperty("proxy_icon_url")]
+ public string? ProxyIconUrl { get; set; }
+ }
+}
diff --git a/Utils/LogWatcher.cs b/Utils/LogWatcher.cs
index f239902..61ce6b2 100644
--- a/Utils/LogWatcher.cs
+++ b/Utils/LogWatcher.cs
@@ -107,7 +107,7 @@ private void LogTick(object? sender, EventArgs? e)
}
if (SkipParsedLogs)
- SetParsedPos(logContext.DateKey, logContext.Position, firstRun);
+ SetParsedPos(logContext.DateKey, isOlder ? logContext.Position : logContext.RoomReadPos, firstRun);
}
}
@@ -246,6 +246,8 @@ private bool ParseLocation(string line, DateTime lineDate, LogContext logContext
var worldName = line.Substring(index).Trim('\n', '\r');
logContext.Enter(worldName, lineDate);
+ logContext.RoomReadPos = logContext.Position;
+
return true;
}
@@ -299,6 +301,7 @@ public class LogContext
public string? DisplayName;
// Recent Instance info
+ public long RoomReadPos { get; set; }
public string? RoomName { get; private set; }
public DateTime RoomDate { get; private set; }
public readonly HashSet Players;
diff --git a/Windows/EditWindow.cs b/Windows/EditWindow.cs
index ecefb79..250b939 100644
--- a/Windows/EditWindow.cs
+++ b/Windows/EditWindow.cs
@@ -8,7 +8,7 @@ public struct EditResult
public partial class EditWindow : Form
{
- static readonly EditWindow Instance = new EditWindow();
+ static EditWindow Instance = new EditWindow();
public static Size GetSize() => Instance.Size;
string Content
@@ -24,6 +24,8 @@ private EditWindow()
public static EditResult Show(string content, string title, Form parent)
{
+ if (Instance.IsDisposed) Instance = new EditWindow();
+
Instance.Text = title;
Instance.Owner = parent;
Instance.StartPosition = FormStartPosition.CenterParent;
diff --git a/Windows/MainWindow.Designer.cs b/Windows/MainWindow.Designer.cs
index 4af7e69..5500cd2 100644
--- a/Windows/MainWindow.Designer.cs
+++ b/Windows/MainWindow.Designer.cs
@@ -36,6 +36,7 @@ private void InitializeComponent()
ctxMenuEntriesCopyTo = new ToolStripMenuItem();
ctxMenuEntriesNew = new ToolStripMenuItem();
ctxMenuEntriesNote = new ToolStripMenuItem();
+ ctxMenuEntriesBackup = new ToolStripMenuItem();
toolStripMenuItem2 = new ToolStripSeparator();
ctxMenuEntriesDelete = new ToolStripMenuItem();
ctxMenuKeys = new ContextMenuStrip(components);
@@ -47,6 +48,7 @@ private void InitializeComponent()
button1 = new Button();
button2 = new Button();
splitContainer1 = new SplitContainer();
+ linkSupport = new Button();
ctxMenuEntries.SuspendLayout();
ctxMenuKeys.SuspendLayout();
((System.ComponentModel.ISupportInitialize)splitContainer1).BeginInit();
@@ -98,9 +100,9 @@ private void InitializeComponent()
//
// ctxMenuEntries
//
- ctxMenuEntries.Items.AddRange(new ToolStripItem[] { ctxMenuEntriesCopyTo, ctxMenuEntriesNote, toolStripMenuItem2, ctxMenuEntriesDelete });
+ ctxMenuEntries.Items.AddRange(new ToolStripItem[] { ctxMenuEntriesCopyTo, ctxMenuEntriesNote, ctxMenuEntriesBackup, toolStripMenuItem2, ctxMenuEntriesDelete });
ctxMenuEntries.Name = "ctxMenuEntries";
- ctxMenuEntries.Size = new Size(138, 76);
+ ctxMenuEntries.Size = new Size(181, 120);
ctxMenuEntries.Closed += ctxMenuEntries_Closed;
ctxMenuEntries.Opened += ctxMenuEntries_Opened;
//
@@ -108,13 +110,13 @@ private void InitializeComponent()
//
ctxMenuEntriesCopyTo.DropDownItems.AddRange(new ToolStripItem[] { ctxMenuEntriesNew });
ctxMenuEntriesCopyTo.Name = "ctxMenuEntriesCopyTo";
- ctxMenuEntriesCopyTo.Size = new Size(137, 22);
+ ctxMenuEntriesCopyTo.Size = new Size(180, 22);
ctxMenuEntriesCopyTo.Text = "Add to";
//
// ctxMenuEntriesNew
//
ctxMenuEntriesNew.Name = "ctxMenuEntriesNew";
- ctxMenuEntriesNew.Size = new Size(172, 22);
+ ctxMenuEntriesNew.Size = new Size(155, 22);
ctxMenuEntriesNew.Text = "New Collection";
ctxMenuEntriesNew.ToolTipText = "Add this entry to a new collection.";
ctxMenuEntriesNew.Click += ctxMenuEntriesNew_Click;
@@ -122,19 +124,28 @@ private void InitializeComponent()
// ctxMenuEntriesNote
//
ctxMenuEntriesNote.Name = "ctxMenuEntriesNote";
- ctxMenuEntriesNote.Size = new Size(137, 22);
+ ctxMenuEntriesNote.Size = new Size(180, 22);
ctxMenuEntriesNote.Text = "Edit Note";
ctxMenuEntriesNote.Click += ctxMenuEntriesNote_Click;
//
+ // ctxMenuEntriesBackup
+ //
+ ctxMenuEntriesBackup.Enabled = false;
+ ctxMenuEntriesBackup.Name = "ctxMenuEntriesBackup";
+ ctxMenuEntriesBackup.Size = new Size(180, 22);
+ ctxMenuEntriesBackup.Text = "Backup";
+ ctxMenuEntriesBackup.ToolTipText = "Force upload a backup of this code to Discord as a file, requires Auto Discord Backup to be enabled in settings.";
+ ctxMenuEntriesBackup.Click += ctxMenuEntriesBackup_Click;
+ //
// toolStripMenuItem2
//
toolStripMenuItem2.Name = "toolStripMenuItem2";
- toolStripMenuItem2.Size = new Size(134, 6);
+ toolStripMenuItem2.Size = new Size(177, 6);
//
// ctxMenuEntriesDelete
//
ctxMenuEntriesDelete.Name = "ctxMenuEntriesDelete";
- ctxMenuEntriesDelete.Size = new Size(137, 22);
+ ctxMenuEntriesDelete.Size = new Size(180, 22);
ctxMenuEntriesDelete.Text = "Delete";
ctxMenuEntriesDelete.Click += ctxMenuEntriesDelete_Click;
//
@@ -142,31 +153,31 @@ private void InitializeComponent()
//
ctxMenuKeys.Items.AddRange(new ToolStripItem[] { importToolStripMenuItem, renameToolStripMenuItem, toolStripMenuItem1, deleteToolStripMenuItem });
ctxMenuKeys.Name = "ctxMenuKeys";
- ctxMenuKeys.Size = new Size(117, 76);
+ ctxMenuKeys.Size = new Size(118, 76);
//
// importToolStripMenuItem
//
importToolStripMenuItem.Name = "importToolStripMenuItem";
- importToolStripMenuItem.Size = new Size(116, 22);
+ importToolStripMenuItem.Size = new Size(117, 22);
importToolStripMenuItem.Text = "Import";
importToolStripMenuItem.Click += ctxMenuKeysImport_Click;
//
// renameToolStripMenuItem
//
renameToolStripMenuItem.Name = "renameToolStripMenuItem";
- renameToolStripMenuItem.Size = new Size(116, 22);
+ renameToolStripMenuItem.Size = new Size(117, 22);
renameToolStripMenuItem.Text = "Rename";
renameToolStripMenuItem.Click += ctxMenuKeysRename_Click;
//
// toolStripMenuItem1
//
toolStripMenuItem1.Name = "toolStripMenuItem1";
- toolStripMenuItem1.Size = new Size(113, 6);
+ toolStripMenuItem1.Size = new Size(114, 6);
//
// deleteToolStripMenuItem
//
deleteToolStripMenuItem.Name = "deleteToolStripMenuItem";
- deleteToolStripMenuItem.Size = new Size(116, 22);
+ deleteToolStripMenuItem.Size = new Size(117, 22);
deleteToolStripMenuItem.Text = "Delete";
deleteToolStripMenuItem.Click += ctxMenuKeysDelete_Click;
//
@@ -195,7 +206,7 @@ private void InitializeComponent()
button1.ForeColor = Color.White;
button1.Location = new Point(0, 223);
button1.Name = "button1";
- button1.Size = new Size(259, 24);
+ button1.Size = new Size(229, 24);
button1.TabIndex = 0;
button1.TabStop = false;
button1.Text = "Objectives";
@@ -209,7 +220,7 @@ private void InitializeComponent()
button2.FlatAppearance.BorderColor = Color.FromArgb(122, 122, 122);
button2.FlatStyle = FlatStyle.Flat;
button2.ForeColor = Color.White;
- button2.Location = new Point(265, 223);
+ button2.Location = new Point(235, 223);
button2.Name = "button2";
button2.Size = new Size(58, 24);
button2.TabIndex = 3;
@@ -231,6 +242,7 @@ private void InitializeComponent()
//
// splitContainer1.Panel2
//
+ splitContainer1.Panel2.Controls.Add(linkSupport);
splitContainer1.Panel2.Controls.Add(listBoxEntries);
splitContainer1.Panel2.Controls.Add(button1);
splitContainer1.Panel2.Controls.Add(button2);
@@ -240,6 +252,22 @@ private void InitializeComponent()
splitContainer1.TabStop = false;
splitContainer1.SplitterMoved += splitContainer1_SplitterMoved;
//
+ // linkSupport
+ //
+ linkSupport.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;
+ linkSupport.BackColor = Color.FromArgb(46, 52, 64);
+ linkSupport.FlatAppearance.BorderColor = Color.FromArgb(122, 122, 122);
+ linkSupport.FlatStyle = FlatStyle.Flat;
+ linkSupport.ForeColor = Color.White;
+ linkSupport.Image = (Image)resources.GetObject("linkSupport.Image");
+ linkSupport.Location = new Point(299, 223);
+ linkSupport.Name = "linkSupport";
+ linkSupport.Size = new Size(24, 24);
+ linkSupport.TabIndex = 4;
+ linkSupport.TabStop = false;
+ linkSupport.UseVisualStyleBackColor = false;
+ linkSupport.Click += linkSupport_Click;
+ //
// MainWindow
//
AutoScaleDimensions = new SizeF(7F, 15F);
@@ -283,5 +311,7 @@ private void InitializeComponent()
private Button button1;
private Button button2;
private SplitContainer splitContainer1;
+ private ToolStripMenuItem ctxMenuEntriesBackup;
+ private Button linkSupport;
}
}
\ No newline at end of file
diff --git a/Windows/MainWindow.cs b/Windows/MainWindow.cs
index c5b0ed1..033e7d7 100644
--- a/Windows/MainWindow.cs
+++ b/Windows/MainWindow.cs
@@ -1,4 +1,4 @@
-using System.Diagnostics;
+using System.Diagnostics;
using System.Media;
using ToNSaveManager.Extensions;
using ToNSaveManager.Models;
@@ -7,6 +7,7 @@
using OnLineArgs = ToNSaveManager.Utils.LogWatcher.OnLineArgs;
using LogContext = ToNSaveManager.Utils.LogWatcher.LogContext;
+using ToNSaveManager.Utils.Discord;
namespace ToNSaveManager
{
@@ -60,6 +61,9 @@ private void mainWindow_Loaded(object sender, EventArgs e)
this.Text = "Loading, please wait...";
XSOverlay.SetPort(Settings.Get.XSOverlayPort);
+
+ SetBackupButton(Settings.Get.DiscordWebhookEnabled && !string.IsNullOrWhiteSpace(Settings.Get.DiscordWebhookURL));
+ TooltipUtil.Set(linkSupport, "Buy Me A Coffee ♥");
}
private void mainWindow_Shown(object sender, EventArgs e)
@@ -280,7 +284,12 @@ private void ctxMenuEntries_Opened(object sender, EventArgs e)
ctxMenuEntriesCopyTo.DropDownItems.Add(ctxMenuEntriesNew);
if (listBoxEntries.SelectedItem == null) ctxMenuEntries.Close();
- else ContextEntry = (Entry)listBoxEntries.SelectedItem;
+ else
+ {
+ ContextEntry = (Entry)listBoxEntries.SelectedItem;
+ if (ContextEntry.Parent == null)
+ ContextEntry.Parent = (History?)listBoxKeys.SelectedItem;
+ }
}
private void ctxMenuEntriesNew_Click(object sender, EventArgs e)
@@ -307,6 +316,14 @@ private void ctxMenuEntriesNote_Click(object sender, EventArgs e)
listBoxEntries.SelectedIndex = -1;
}
+ private void ctxMenuEntriesBackup_Click(object sender, EventArgs e)
+ {
+ if (ContextEntry != null)
+ DSWebHook.Send(ContextEntry, true);
+
+ listBoxEntries.SelectedIndex = -1;
+ }
+
private void ctxMenuEntriesDelete_Click(object sender, EventArgs e)
{
if (listBoxKeys.SelectedItem == null)
@@ -351,6 +368,12 @@ private void linkWiki_Clicked(object sender, EventArgs e)
OpenExternalLink(wiki);
}
+ private void linkSupport_Click(object sender, EventArgs e)
+ {
+ const string support = "https://ko-fi.com/kittenji";
+ OpenExternalLink(support);
+ }
+
private void btnObjectives_Click(object sender, EventArgs e)
{
ObjectivesWindow.Open(this);
@@ -459,6 +482,11 @@ internal static string GetTruncatedText(string text, Font font, int maxWidth)
return text + "...";
}
+
+ internal void SetBackupButton(bool enabled)
+ {
+ ctxMenuEntriesBackup.Enabled = enabled;
+ }
#endregion
#region Log Handling
@@ -551,7 +579,7 @@ private bool HandleTerrorIndex(string line, DateTime timestamp, LogContext conte
isOptedIn = line.StartsWith(ROUND_WON_KEYWORD);
if (isOptedIn || line.StartsWith(ROUND_LOST_KEYWORD))
{
- context.Set(ROUND_RESULT_KEY, isOptedIn ? ToNRoundResult.W : ToNRoundResult.L);
+ context.Set(ROUND_RESULT_KEY, isOptedIn ? ToNRoundResult.W : ToNRoundResult.D);
return true;
}
@@ -627,13 +655,22 @@ private void AddLogEntry(string dateKey, string content, DateTime timestamp, Log
if (collection == null)
{
collection = new History(dateKey);
+ collection.SetLogContext(context);
AddKey(collection);
}
+ if (string.IsNullOrEmpty(context.DisplayName) && !string.IsNullOrEmpty(collection.DisplayName))
+ {
+ context.DisplayName = collection.DisplayName;
+ }
+
int ind = collection.Add(content, timestamp, out Entry? entry);
if (ind < 0) return; // Not added, duplicate
#pragma warning disable CS8604, CS8602 // Nullability is handled along with the return value of .Add
+ entry.PlayerCount = context.Players.Count;
+ entry.Parent = collection;
+
if (Settings.Get.SaveNames) entry.Players = context.GetRoomString();
if (Settings.Get.SaveRoundInfo)
{
@@ -652,6 +689,7 @@ private void AddLogEntry(string dateKey, string content, DateTime timestamp, Log
{
entry.RTerrors = killers.TerrorNames;
entry.RType = killers.RoundTypeRaw;
+ entry.RT = killers.RoundType;
if (Settings.Get.SaveRoundNote)
entry.Note = string.Join(", ", killers.TerrorNames);
@@ -672,6 +710,7 @@ private void AddLogEntry(string dateKey, string content, DateTime timestamp, Log
{
PlayNotification();
SendXSNotification();
+ DSWebHook.Send(entry);
}
}
diff --git a/Windows/MainWindow.resx b/Windows/MainWindow.resx
index 12df1fd..7d1a689 100644
--- a/Windows/MainWindow.resx
+++ b/Windows/MainWindow.resx
@@ -18,7 +18,7 @@
System.Resources.ResXResourceReader, System.Windows.Forms, ...
System.Resources.ResXResourceWriter, System.Windows.Forms, ...
this is my long stringthis is a comment
- Blue
+ Blue
[base64 mime encoded serialized .NET Framework object]
@@ -124,6 +124,21 @@
175, 17
+
+
+ iVBORw0KGgoAAAANSUhEUgAAAAsAAAAKCAYAAABi8KSDAAABgmlDQ1BJQ0MgcHJvZmlsZQAAKM+VkTlI
+ A0EYhT+jEhEvMIWI4BZqZRoVsQxRFEFBYgSvwt2NiUJ2E3YTbCwFW8HCo/EqbKy1tbAVBMEDxNrCStFG
+ wvrPRkgQIjgwzMebeY+ZNxA4TJuWWxMBy845sbGoNjs3rwVfCNJEC50EddPNTk6Pxqk4Pu+oUuttWGXx
+ v9GYWHZNqNKEI2bWyQkvCQ+u5bKKd4VD5oqeED4T7nXkgsIPSjeK/Ko45XNAZYaceGxYOCSspcrYKGNz
+ xbGEB4S7EpYt+YHZIicUryu20nnz557qhQ3L9sy00mV2MMY4k0yhYZBnlTQ5wrLaorjEZD9awd/u+6fE
+ ZYhrFVMcI2Sw0H0/6g9+d+sm+/uKSQ1RqH32vPduCG5DYcvzvo48r3AM1U9waZf8mUMY+hB9q6R1HUDz
+ BpxflTRjBy42oe0xqzu6L1XLDCST8HYq3zQHrTdQv1Ds7Wefk3uIS1cT17C3Dz0pyV6s8O668t7+POP3
+ R/QbeWVyqQwXJNgAAAAJcEhZcwAACw0AAAsNAe0HwCwAAAAHdElNRQfoBw4QKSrn520hAAAAg0lEQVQo
+ U53M7QrCMAyF4V7lbLtVRfxAxtwQFMSLf03Tdm4/HLIDh5DyNGZVqN6weUH1RHfXgxukN93HRIB9CL7L
+ FGQ78K30CvVZevx+wMqFCFwBFwU0B5k7mWGCI/DxwimBZq+AUMM2NdMUvRDmQBv8HJZMwSIsUZhxflrO
+ 3/B3jPkAexOGRyThvYIAAAAASUVORK5CYII=
+
+
AAABAAEAICAQAAEABADoAgAAFgAAACgAAAAgAAAAQAAAAAEABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
diff --git a/Windows/SettingsWindow.Designer.cs b/Windows/SettingsWindow.Designer.cs
index dce424c..ca6f762 100644
--- a/Windows/SettingsWindow.Designer.cs
+++ b/Windows/SettingsWindow.Designer.cs
@@ -30,6 +30,7 @@ private void InitializeComponent()
{
components = new System.ComponentModel.Container();
groupBoxGeneral = new GroupBox();
+ checkDiscordBackup = new CheckBox();
checkShowWinLose = new CheckBox();
checkSaveTerrorsNote = new CheckBox();
checkSaveTerrors = new CheckBox();
@@ -64,6 +65,7 @@ private void InitializeComponent()
//
groupBoxGeneral.AutoSize = true;
groupBoxGeneral.AutoSizeMode = AutoSizeMode.GrowAndShrink;
+ groupBoxGeneral.Controls.Add(checkDiscordBackup);
groupBoxGeneral.Controls.Add(checkShowWinLose);
groupBoxGeneral.Controls.Add(checkSaveTerrorsNote);
groupBoxGeneral.Controls.Add(checkSaveTerrors);
@@ -74,29 +76,41 @@ private void InitializeComponent()
groupBoxGeneral.ForeColor = Color.White;
groupBoxGeneral.Location = new Point(8, 8);
groupBoxGeneral.Name = "groupBoxGeneral";
- groupBoxGeneral.Size = new Size(268, 129);
+ groupBoxGeneral.Size = new Size(268, 148);
groupBoxGeneral.TabIndex = 0;
groupBoxGeneral.TabStop = false;
groupBoxGeneral.Text = "General";
//
+ // checkDiscordBackup
+ //
+ checkDiscordBackup.Dock = DockStyle.Top;
+ checkDiscordBackup.Location = new Point(3, 127);
+ checkDiscordBackup.Name = "checkDiscordBackup";
+ checkDiscordBackup.Padding = new Padding(3, 0, 3, 0);
+ checkDiscordBackup.Size = new Size(262, 18);
+ checkDiscordBackup.TabIndex = 6;
+ checkDiscordBackup.Tag = "DiscordWebhookEnabled|Automatically saves your new codes to a Discord channel using a webhook integration.";
+ checkDiscordBackup.Text = "Auto Discord Backup (Webhook)";
+ checkDiscordBackup.UseVisualStyleBackColor = true;
+ //
// checkShowWinLose
//
checkShowWinLose.Dock = DockStyle.Top;
checkShowWinLose.ForeColor = Color.PowderBlue;
- checkShowWinLose.Location = new Point(3, 108);
+ checkShowWinLose.Location = new Point(3, 109);
checkShowWinLose.Name = "checkShowWinLose";
checkShowWinLose.Padding = new Padding(21, 0, 3, 0);
checkShowWinLose.Size = new Size(262, 18);
checkShowWinLose.TabIndex = 5;
- checkShowWinLose.Tag = "ShowWinLose|Entries will show a [W] or [L] tag.";
- checkShowWinLose.Text = "Show Win/Lose Tags";
+ checkShowWinLose.Tag = "ShowWinLose|Entries will show a [R], [W] or [D] tag based on the source that triggered the save.";
+ checkShowWinLose.Text = "Show [R][W][D] Tags";
checkShowWinLose.UseVisualStyleBackColor = true;
//
// checkSaveTerrorsNote
//
checkSaveTerrorsNote.Dock = DockStyle.Top;
checkSaveTerrorsNote.ForeColor = Color.PowderBlue;
- checkSaveTerrorsNote.Location = new Point(3, 90);
+ checkSaveTerrorsNote.Location = new Point(3, 91);
checkSaveTerrorsNote.Name = "checkSaveTerrorsNote";
checkSaveTerrorsNote.Padding = new Padding(21, 0, 3, 0);
checkSaveTerrorsNote.Size = new Size(262, 18);
@@ -108,7 +122,7 @@ private void InitializeComponent()
// checkSaveTerrors
//
checkSaveTerrors.Dock = DockStyle.Top;
- checkSaveTerrors.Location = new Point(3, 72);
+ checkSaveTerrors.Location = new Point(3, 73);
checkSaveTerrors.Name = "checkSaveTerrors";
checkSaveTerrors.Padding = new Padding(3, 0, 3, 0);
checkSaveTerrors.Size = new Size(262, 18);
@@ -120,7 +134,7 @@ private void InitializeComponent()
// checkPlayerNames
//
checkPlayerNames.Dock = DockStyle.Top;
- checkPlayerNames.Location = new Point(3, 54);
+ checkPlayerNames.Location = new Point(3, 55);
checkPlayerNames.Name = "checkPlayerNames";
checkPlayerNames.Padding = new Padding(3, 0, 3, 0);
checkPlayerNames.Size = new Size(262, 18);
@@ -132,7 +146,7 @@ private void InitializeComponent()
// checkAutoCopy
//
checkAutoCopy.Dock = DockStyle.Top;
- checkAutoCopy.Location = new Point(3, 36);
+ checkAutoCopy.Location = new Point(3, 37);
checkAutoCopy.Name = "checkAutoCopy";
checkAutoCopy.Padding = new Padding(3, 0, 3, 0);
checkAutoCopy.Size = new Size(262, 18);
@@ -144,7 +158,7 @@ private void InitializeComponent()
// checkSkipParsedLogs
//
checkSkipParsedLogs.Dock = DockStyle.Top;
- checkSkipParsedLogs.Location = new Point(3, 18);
+ checkSkipParsedLogs.Location = new Point(3, 19);
checkSkipParsedLogs.Name = "checkSkipParsedLogs";
checkSkipParsedLogs.Padding = new Padding(3, 0, 3, 0);
checkSkipParsedLogs.Size = new Size(262, 18);
@@ -161,9 +175,9 @@ private void InitializeComponent()
groupBoxNotifications.Controls.Add(checkXSOverlay);
groupBoxNotifications.Dock = DockStyle.Top;
groupBoxNotifications.ForeColor = Color.White;
- groupBoxNotifications.Location = new Point(8, 137);
+ groupBoxNotifications.Location = new Point(8, 156);
groupBoxNotifications.Name = "groupBoxNotifications";
- groupBoxNotifications.Size = new Size(268, 57);
+ groupBoxNotifications.Size = new Size(268, 58);
groupBoxNotifications.TabIndex = 2;
groupBoxNotifications.TabStop = false;
groupBoxNotifications.Text = "Notifications";
@@ -172,7 +186,7 @@ private void InitializeComponent()
//
checkPlayAudio.AutoCheck = false;
checkPlayAudio.Dock = DockStyle.Top;
- checkPlayAudio.Location = new Point(3, 36);
+ checkPlayAudio.Location = new Point(3, 37);
checkPlayAudio.Name = "checkPlayAudio";
checkPlayAudio.Padding = new Padding(3, 0, 3, 0);
checkPlayAudio.Size = new Size(262, 18);
@@ -186,7 +200,7 @@ private void InitializeComponent()
// checkXSOverlay
//
checkXSOverlay.Dock = DockStyle.Top;
- checkXSOverlay.Location = new Point(3, 18);
+ checkXSOverlay.Location = new Point(3, 19);
checkXSOverlay.Name = "checkXSOverlay";
checkXSOverlay.Padding = new Padding(3, 0, 3, 0);
checkXSOverlay.Size = new Size(262, 18);
@@ -205,9 +219,9 @@ private void InitializeComponent()
groupBox1.Controls.Add(check24Hour);
groupBox1.Dock = DockStyle.Top;
groupBox1.ForeColor = Color.White;
- groupBox1.Location = new Point(8, 194);
+ groupBox1.Location = new Point(8, 214);
groupBox1.Name = "groupBox1";
- groupBox1.Size = new Size(268, 93);
+ groupBox1.Size = new Size(268, 94);
groupBox1.TabIndex = 3;
groupBox1.TabStop = false;
groupBox1.Text = "Time Formatting";
@@ -215,7 +229,7 @@ private void InitializeComponent()
// checkShowDate
//
checkShowDate.Dock = DockStyle.Top;
- checkShowDate.Location = new Point(3, 72);
+ checkShowDate.Location = new Point(3, 73);
checkShowDate.Name = "checkShowDate";
checkShowDate.Padding = new Padding(3, 0, 3, 0);
checkShowDate.Size = new Size(262, 18);
@@ -227,7 +241,7 @@ private void InitializeComponent()
// checkInvertMD
//
checkInvertMD.Dock = DockStyle.Top;
- checkInvertMD.Location = new Point(3, 54);
+ checkInvertMD.Location = new Point(3, 55);
checkInvertMD.Name = "checkInvertMD";
checkInvertMD.Padding = new Padding(3, 0, 3, 0);
checkInvertMD.Size = new Size(262, 18);
@@ -239,7 +253,7 @@ private void InitializeComponent()
// checkShowSeconds
//
checkShowSeconds.Dock = DockStyle.Top;
- checkShowSeconds.Location = new Point(3, 36);
+ checkShowSeconds.Location = new Point(3, 37);
checkShowSeconds.Name = "checkShowSeconds";
checkShowSeconds.Padding = new Padding(3, 0, 3, 0);
checkShowSeconds.Size = new Size(262, 18);
@@ -251,7 +265,7 @@ private void InitializeComponent()
// check24Hour
//
check24Hour.Dock = DockStyle.Top;
- check24Hour.Location = new Point(3, 18);
+ check24Hour.Location = new Point(3, 19);
check24Hour.Name = "check24Hour";
check24Hour.Padding = new Padding(3, 0, 3, 0);
check24Hour.Size = new Size(262, 18);
@@ -266,7 +280,7 @@ private void InitializeComponent()
btnCheckForUpdates.FlatAppearance.BorderColor = Color.FromArgb(122, 122, 122);
btnCheckForUpdates.FlatStyle = FlatStyle.Flat;
btnCheckForUpdates.ForeColor = Color.White;
- btnCheckForUpdates.Location = new Point(8, 332);
+ btnCheckForUpdates.Location = new Point(8, 356);
btnCheckForUpdates.Name = "btnCheckForUpdates";
btnCheckForUpdates.Size = new Size(209, 24);
btnCheckForUpdates.TabIndex = 4;
@@ -281,7 +295,7 @@ private void InitializeComponent()
btnOpenData.FlatAppearance.BorderColor = Color.FromArgb(122, 122, 122);
btnOpenData.FlatStyle = FlatStyle.Flat;
btnOpenData.ForeColor = Color.White;
- btnOpenData.Location = new Point(223, 332);
+ btnOpenData.Location = new Point(223, 356);
btnOpenData.Name = "btnOpenData";
btnOpenData.Size = new Size(53, 24);
btnOpenData.TabIndex = 5;
@@ -294,26 +308,26 @@ private void InitializeComponent()
//
ctxData.Items.AddRange(new ToolStripItem[] { setDataLocationToolStripMenuItem });
ctxData.Name = "ctxData";
- ctxData.Size = new Size(215, 48);
+ ctxData.Size = new Size(193, 26);
//
// setDataLocationToolStripMenuItem
//
setDataLocationToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { ctxItemPickFolder, ctxItemResetToDefault });
setDataLocationToolStripMenuItem.Name = "setDataLocationToolStripMenuItem";
- setDataLocationToolStripMenuItem.Size = new Size(214, 22);
+ setDataLocationToolStripMenuItem.Size = new Size(192, 22);
setDataLocationToolStripMenuItem.Text = "Custom Data Location";
//
// ctxItemPickFolder
//
ctxItemPickFolder.Name = "ctxItemPickFolder";
- ctxItemPickFolder.Size = new Size(186, 22);
+ ctxItemPickFolder.Size = new Size(157, 22);
ctxItemPickFolder.Text = "Pick Folder";
ctxItemPickFolder.Click += ctxItemPickFolder_Click;
//
// ctxItemResetToDefault
//
ctxItemResetToDefault.Name = "ctxItemResetToDefault";
- ctxItemResetToDefault.Size = new Size(186, 22);
+ ctxItemResetToDefault.Size = new Size(157, 22);
ctxItemResetToDefault.Text = "Reset to Default";
ctxItemResetToDefault.Click += ctxItemResetToDefault_Click;
//
@@ -330,9 +344,9 @@ private void InitializeComponent()
groupBox2.Controls.Add(checkColorObjectives);
groupBox2.Dock = DockStyle.Top;
groupBox2.ForeColor = Color.White;
- groupBox2.Location = new Point(8, 287);
+ groupBox2.Location = new Point(8, 308);
groupBox2.Name = "groupBox2";
- groupBox2.Size = new Size(268, 39);
+ groupBox2.Size = new Size(268, 40);
groupBox2.TabIndex = 6;
groupBox2.TabStop = false;
groupBox2.Text = "Style";
@@ -340,7 +354,7 @@ private void InitializeComponent()
// checkColorObjectives
//
checkColorObjectives.Dock = DockStyle.Top;
- checkColorObjectives.Location = new Point(3, 18);
+ checkColorObjectives.Location = new Point(3, 19);
checkColorObjectives.Name = "checkColorObjectives";
checkColorObjectives.Padding = new Padding(3, 0, 3, 0);
checkColorObjectives.Size = new Size(262, 18);
@@ -356,7 +370,7 @@ private void InitializeComponent()
AutoSize = true;
AutoSizeMode = AutoSizeMode.GrowAndShrink;
BackColor = Color.FromArgb(46, 52, 64);
- ClientSize = new Size(284, 364);
+ ClientSize = new Size(284, 388);
Controls.Add(groupBox2);
Controls.Add(btnOpenData);
Controls.Add(btnCheckForUpdates);
@@ -410,5 +424,6 @@ private void InitializeComponent()
private ToolStripMenuItem setDataLocationToolStripMenuItem;
private ToolStripMenuItem ctxItemPickFolder;
private ToolStripMenuItem ctxItemResetToDefault;
+ private CheckBox checkDiscordBackup;
}
}
\ No newline at end of file
diff --git a/Windows/SettingsWindow.cs b/Windows/SettingsWindow.cs
index 233d7bc..27a637e 100644
--- a/Windows/SettingsWindow.cs
+++ b/Windows/SettingsWindow.cs
@@ -1,6 +1,7 @@
using System.Diagnostics;
using ToNSaveManager.Extensions;
using ToNSaveManager.Models;
+using ToNSaveManager.Utils.Discord;
using Timer = System.Windows.Forms.Timer;
namespace ToNSaveManager.Windows
@@ -62,6 +63,9 @@ private void SettingsWindow_Load(object sender, EventArgs e)
checkShowWinLose.CheckedChanged += TimeFormat_CheckedChanged;
checkSaveTerrors.CheckedChanged += checkSaveTerrors_CheckedChanged;
checkSaveTerrors_CheckedChanged(checkSaveTerrors, e);
+
+ // Discord Backups
+ checkDiscordBackup.CheckedChanged += CheckDiscordBackup_CheckedChanged;
}
private void SettingsWindow_FormClosed(object sender, FormClosedEventArgs e)
@@ -87,6 +91,36 @@ private void checkSaveTerrors_CheckedChanged(object? sender, EventArgs e)
TimeFormat_CheckedChanged(sender, e);
}
+ private void CheckDiscordBackup_CheckedChanged(object? sender, EventArgs e)
+ {
+ if (checkDiscordBackup.Checked)
+ {
+ string url = Settings.Get.DiscordWebhookURL ?? string.Empty;
+ EditResult edit = EditWindow.Show(Settings.Get.DiscordWebhookURL ?? string.Empty, "Discord Webhook URL", this);
+ if (edit.Accept && !edit.Text.Equals(url, StringComparison.Ordinal))
+ {
+ url = edit.Text.Trim();
+
+ if (!string.IsNullOrWhiteSpace(url)) {
+ bool valid = DSWebHook.ValidateURL(url);
+
+ if (valid) {
+ Settings.Get.DiscordWebhookURL = url;
+ Settings.Export();
+ } else {
+ MessageBox.Show($"The URL your provided does not match a discord webhook url.\n\nMake sure you created your webhook and copied the url correctly.", "Invalid Webhook URL", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ } else {
+ Settings.Get.DiscordWebhookURL = null;
+ }
+ }
+
+ if (string.IsNullOrEmpty(Settings.Get.DiscordWebhookURL)) checkDiscordBackup.Checked = false;
+ }
+
+ MainWindow.Instance?.SetBackupButton(checkDiscordBackup.Checked);
+ }
+
private void btnCheckForUpdates_Click(object sender, EventArgs e)
{
if (Program.StartCheckForUpdate(true)) this.Close();
diff --git a/Windows/SettingsWindow.resx b/Windows/SettingsWindow.resx
index 4f83590..693fb3e 100644
--- a/Windows/SettingsWindow.resx
+++ b/Windows/SettingsWindow.resx
@@ -18,7 +18,7 @@
System.Resources.ResXResourceReader, System.Windows.Forms, ...
System.Resources.ResXResourceWriter, System.Windows.Forms, ...
this is my long stringthis is a comment
- Blue
+ Blue
[base64 mime encoded serialized .NET Framework object]
diff --git a/Windows/UpdateWindow.cs b/Windows/UpdateWindow.cs
index a4a86fe..17156dd 100644
--- a/Windows/UpdateWindow.cs
+++ b/Windows/UpdateWindow.cs
@@ -41,6 +41,22 @@ public static void RunPostUpdateCheck(string[] args)
try
{
+ using (Process currentProcess = Process.GetCurrentProcess())
+ {
+ Process[] processes = Process.GetProcessesByName(currentProcess.ProcessName);
+ foreach (Process process in processes)
+ {
+ using (process)
+ {
+ if (process.Id != currentProcess.Id)
+ {
+ process.Kill();
+ process.WaitForExit();
+ }
+ }
+ }
+ }
+
if (Directory.Exists(temp))
Directory.Delete(temp, true);
}
@@ -57,6 +73,7 @@ private void BackgroundWr_DoWork(object? sender, DoWorkEventArgs e)
try
{
+
if (File.Exists(TempFileLocation))
File.Delete(TempFileLocation);