From b6ee48efe8d25d2d188e0746b4e4d30a8f214fde Mon Sep 17 00:00:00 2001 From: Xavier Foucrier Date: Sun, 15 Sep 2024 15:16:56 +0200 Subject: [PATCH 01/36] Explicitely use NodeJS 20 in CI build --- .github/workflows/ci.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 952ce85..5004596 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,6 +22,11 @@ jobs: - name: Checkout the repository uses: actions/checkout@v4 + - name: Setup NodeJS + uses: actions/setup-node@v4 + with: + node-version: 20 + - name: Setup MSBuild uses: microsoft/setup-msbuild@v2 From 42789ae4e6527181b6e7eaac3c1c62eb8d7edfa4 Mon Sep 17 00:00:00 2001 From: Xavier Foucrier Date: Fri, 22 Nov 2024 18:45:14 +0100 Subject: [PATCH 02/36] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20refactor=20`sync-lab?= =?UTF-8?q?els`=20workflow?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/{ => issues}/labels.yml | 20 ++++++++++++++++---- .github/workflows/sync-labels.yml | 12 +++++++++--- 2 files changed, 25 insertions(+), 7 deletions(-) rename .github/{ => issues}/labels.yml (71%) diff --git a/.github/labels.yml b/.github/issues/labels.yml similarity index 71% rename from .github/labels.yml rename to .github/issues/labels.yml index 388191c..f4e64e4 100644 --- a/.github/labels.yml +++ b/.github/issues/labels.yml @@ -1,3 +1,9 @@ +- name: a11y + description: about accessibility + color: fef2c0 +- name: await test repository + description: waiting for a minimal test repository + color: 5319e7 - name: bug description: bug to fix color: fbca04 @@ -9,7 +15,7 @@ color: 00209a - name: critical description: critical failure to fix as soon as possible - color: d93f0b + color: b60205 - name: dependencies description: update/upgrade one or more dependency color: 0366d6 @@ -19,14 +25,20 @@ - name: documentation description: regarding the project documentation color: 27d19b +- name: duplicate + description: a similar issue already exists + color: ededed - name: feature description: feature request to implement color: 1d76db - name: help description: need help, any contribution are welcome color: 5319e7 +- name: source map + description: about source mapping + color: ebe4da - name: motion - description: motion request + description: about motion and animation color: 32deca - name: optimization description: optimization request @@ -34,9 +46,9 @@ - name: post-it description: reminder or todo color: fcf49c -- name: platform +- name: environment description: regarding the environment or target platform color: f1f1f1 - name: wontfix description: negligible issue or that will never be fixed - color: 444444 + color: 000000 diff --git a/.github/workflows/sync-labels.yml b/.github/workflows/sync-labels.yml index e86ae02..0742b78 100644 --- a/.github/workflows/sync-labels.yml +++ b/.github/workflows/sync-labels.yml @@ -1,14 +1,18 @@ # Github workflow to automatically sync labels in a declarative way # https://github.com/micnncim/action-label-syncer -name: Sync labels +name: 🏷️ synchronize labels on: push: branches: - main paths: - - '.github/labels.yml' + - .github/issues/labels.yml + +permissions: + contents: write + issues: write jobs: labels: @@ -16,5 +20,7 @@ jobs: steps: - uses: actions/checkout@v4 - uses: micnncim/action-label-syncer@v1 + with: + manifest: .github/issues/labels.yml env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_TOKEN: ${{ github.token }} From 29e943613799dd2d17ac67b1280d36c64ff7ad84 Mon Sep 17 00:00:00 2001 From: Xavier Foucrier Date: Fri, 22 Nov 2024 18:56:06 +0100 Subject: [PATCH 03/36] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20refactor=20`ci`=20wo?= =?UTF-8?q?rkflow?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/ci.yml | 48 +++++++++++++++++++++++++++++++++------- 1 file changed, 40 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5004596..ff2c16a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,6 +1,6 @@ # Github workflow for Continuous Integration -name: CI +name: 🤖 continuous integration on: push: @@ -13,7 +13,7 @@ on: - dev jobs: - build: + build-debug: runs-on: windows-latest defaults: run: @@ -22,11 +22,6 @@ jobs: - name: Checkout the repository uses: actions/checkout@v4 - - name: Setup NodeJS - uses: actions/setup-node@v4 - with: - node-version: 20 - - name: Setup MSBuild uses: microsoft/setup-msbuild@v2 @@ -40,11 +35,48 @@ jobs: run: | msbuild.exe InboxNotifier.sln /p:configuration="Debug" /p:platform="Any CPU" /m + build-x86: + runs-on: windows-latest + needs: build-debug + defaults: + run: + working-directory: code + steps: + - name: Checkout the repository + uses: actions/checkout@v4 + + - name: Setup MSBuild + uses: microsoft/setup-msbuild@v2 + + - name: Setup NuGet + uses: NuGet/setup-nuget@v2 + + - name: Restore NuGet packages + run: nuget restore InboxNotifier.sln + - name: Build solution — Release 32 bits (x86) run: | msbuild.exe InboxNotifier.sln /p:configuration="Release x86" /p:platform="Any CPU" /m + build-x64: + runs-on: windows-latest + needs: build-x86 + defaults: + run: + working-directory: code + steps: + - name: Checkout the repository + uses: actions/checkout@v4 + + - name: Setup MSBuild + uses: microsoft/setup-msbuild@v2 + + - name: Setup NuGet + uses: NuGet/setup-nuget@v2 + + - name: Restore NuGet packages + run: nuget restore InboxNotifier.sln + - name: Build solution — Release 64 bits (x64) run: | msbuild.exe InboxNotifier.sln /p:configuration="Release x64" /p:platform="Any CPU" /m - From 52a161ba2ab4df20ec25aa856f6f8d029b9b1fc6 Mon Sep 17 00:00:00 2001 From: Xavier Foucrier Date: Fri, 22 Nov 2024 19:04:57 +0100 Subject: [PATCH 04/36] =?UTF-8?q?=F0=9F=93=A6=20update=20HtmlAgilityPack?= =?UTF-8?q?=20to=201.11.71?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/InboxNotifier.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/InboxNotifier.csproj b/code/InboxNotifier.csproj index ff74fa9..c906fc2 100644 --- a/code/InboxNotifier.csproj +++ b/code/InboxNotifier.csproj @@ -230,7 +230,7 @@ 1.67.0.3287 - 1.11.60 + 1.11.71 2.0.17 From 06fe8f32e8c42bd3fd0b91e0a1a99b90c4b18008 Mon Sep 17 00:00:00 2001 From: Xavier Foucrier Date: Fri, 22 Nov 2024 19:08:17 +0100 Subject: [PATCH 05/36] =?UTF-8?q?=F0=9F=93=A6=20update=20Google.Apis.Gmail?= =?UTF-8?q?.v1=20to=201.68.0.3427?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/InboxNotifier.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/InboxNotifier.csproj b/code/InboxNotifier.csproj index c906fc2..dc9b39e 100644 --- a/code/InboxNotifier.csproj +++ b/code/InboxNotifier.csproj @@ -227,7 +227,7 @@ - 1.67.0.3287 + 1.68.0.3427 1.11.71 From 40ff0e5eb9bf5e21a2ebae0289064fbbe2e141c4 Mon Sep 17 00:00:00 2001 From: Xavier Foucrier Date: Fri, 22 Nov 2024 19:18:10 +0100 Subject: [PATCH 06/36] =?UTF-8?q?=F0=9F=90=9B=20fix=20obsolete=20method?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/Gmail.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/Gmail.cs b/code/Gmail.cs index 310459b..b1ad7c1 100644 --- a/code/Gmail.cs +++ b/code/Gmail.cs @@ -139,7 +139,7 @@ public async Task RefreshToken() { // refresh the token and update the token delivery date and time on the interface try { - if (Credential.Token.IsExpired(Credential.Flow.Clock)) { + if (Credential.Token.IsStale) { if (await Credential.RefreshTokenAsync(new CancellationToken())) { UI.labelTokenDelivery.Text = Credential.Token.IssuedUtc.ToLocalTime().ToString(); } From 4adcf394ebac4644b4e3b379a994e783184da976 Mon Sep 17 00:00:00 2001 From: Xavier Foucrier Date: Fri, 22 Nov 2024 19:40:24 +0100 Subject: [PATCH 07/36] =?UTF-8?q?=E2=AC=86=EF=B8=8F=20upgrade=20log4net=20?= =?UTF-8?q?to=203.0.3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/InboxNotifier.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/InboxNotifier.csproj b/code/InboxNotifier.csproj index dc9b39e..f1c9229 100644 --- a/code/InboxNotifier.csproj +++ b/code/InboxNotifier.csproj @@ -233,7 +233,7 @@ 1.11.71 - 2.0.17 + 3.0.3 13.0.3 From efa36ee914b595074f4122c17d07a90af9d7db73 Mon Sep 17 00:00:00 2001 From: Xavier Foucrier Date: Fri, 22 Nov 2024 22:38:40 +0100 Subject: [PATCH 08/36] =?UTF-8?q?=E2=9C=8F=EF=B8=8F=20update=20visual=20st?= =?UTF-8?q?udio=20version=20number?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/Main.de.resx | 56 +++++++++++++++++++++++------------------------ code/Main.en.resx | 2 +- code/Main.resx | 2 +- code/Main.ru.resx | 2 +- 4 files changed, 31 insertions(+), 31 deletions(-) diff --git a/code/Main.de.resx b/code/Main.de.resx index c330624..9ad83bd 100644 --- a/code/Main.de.resx +++ b/code/Main.de.resx @@ -1,17 +1,17 @@  - @@ -535,7 +535,7 @@ Open Source, veröffentlicht unter der MIT-Lizenz 153, 34 - Visual Studio 17.8.3, C# + Visual Studio 17.12.1, C# Entwickelt von Xavier Foucrier diff --git a/code/Main.en.resx b/code/Main.en.resx index 853f3e4..2493539 100644 --- a/code/Main.en.resx +++ b/code/Main.en.resx @@ -529,7 +529,7 @@ Open Source, distributed under MIT License 150, 34 - Visual Studio 17.8.3, C# + Visual Studio 17.12.1, C# Developed by Xavier Foucrier diff --git a/code/Main.resx b/code/Main.resx index 95acbf1..7b448ca 100644 --- a/code/Main.resx +++ b/code/Main.resx @@ -1142,7 +1142,7 @@ de réception comme lus. linkVersion - Visual Studio 17.8.3, C# + Visual Studio 17.12.1, C# Développé par Xavier Foucrier diff --git a/code/Main.ru.resx b/code/Main.ru.resx index 4ccae10..e4aef1e 100644 --- a/code/Main.ru.resx +++ b/code/Main.ru.resx @@ -557,7 +557,7 @@ 148, 34 - Visual Studio 17.8.3, C# + Visual Studio 17.12.1, C# Разработано Xavier Foucrier From c92d89185e4df08bc74fb52fded7c8052157e6b5 Mon Sep 17 00:00:00 2001 From: Xavier Foucrier Date: Mon, 25 Nov 2024 00:15:30 +0100 Subject: [PATCH 09/36] =?UTF-8?q?=F0=9F=A9=B9=20fix=20synchronization=20lo?= =?UTF-8?q?op?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fix #216. --- code/Inbox.cs | 85 ++++++++++++++++++++------------------------ code/Notification.cs | 17 +++++++++ 2 files changed, 55 insertions(+), 47 deletions(-) diff --git a/code/Inbox.cs b/code/Inbox.cs index b45b74b..f4fd066 100644 --- a/code/Inbox.cs +++ b/code/Inbox.cs @@ -127,16 +127,19 @@ public async Task Sync(bool manual = true, bool token = false) { // manage the spam notification if (Settings.Default.SpamNotification) { - // exit if a spam is already detected - if (!userAction && UI.NotificationService.Tag == "#spam") { + // get the "spam" label + Label spam = await User.Labels.Get("me", "SPAM").ExecuteAsync(); + + // exit the sync if the number of unread spams is the same as before + if (!userAction && (spam.ThreadsUnread == UnreadSpams) && UnreadSpams != 0) { return; } - // get the "spam" label - Label spam = await User.Labels.Get("me", "SPAM").ExecuteAsync(); + // save the number of unread spams + UnreadSpams = spam.ThreadsUnread; // manage unread spams - if (spam.ThreadsUnread > 0) { + if (UnreadSpams > 0) { // play a sound on unread spams if (Settings.Default.AudioNotification) { @@ -144,14 +147,14 @@ public async Task Sync(bool manual = true, bool token = false) { } // display a balloon tip in the systray with the total of unread threads - UI.NotificationService.Tip($"{spam.ThreadsUnread} {(spam.ThreadsUnread > 1 ? Translation.unreadSpams : Translation.unreadSpam)}", Translation.newUnreadSpam, Notification.Type.Error); + UI.NotificationService.Tip($"{UnreadSpams} {(UnreadSpams > 1 ? Translation.unreadSpams : Translation.unreadSpam)}", Translation.newUnreadSpam, Notification.Type.Error); // set the notification icon and text UI.notifyIcon.Icon = Resources.spam; - UI.notifyIcon.Text = $"{spam.ThreadsUnread} {(spam.ThreadsUnread > 1 ? Translation.unreadSpams : Translation.unreadSpam)}"; + UI.notifyIcon.Text = $"{UnreadSpams} {(UnreadSpams > 1 ? Translation.unreadSpams : Translation.unreadSpam)}"; // enable the mark as read menu item - UI.menuItemMarkAsRead.Text = $"{Translation.markAsRead} ({spam.ThreadsUnread})"; + UI.menuItemMarkAsRead.Text = $"{Translation.markAsRead} ({UnreadSpams})"; UI.menuItemMarkAsRead.Enabled = true; // update the tag @@ -162,15 +165,21 @@ public async Task Sync(bool manual = true, bool token = false) { } // exit the sync if the number of unread threads is the same as before - if (!userAction && (Box.ThreadsUnread == UnreadThreads)) { + if (!userAction && (Box.ThreadsUnread == UnreadThreads) && UnreadThreads != 0) { return; } + // reset notification service + UI.NotificationService.Reset(); + + // save the number of unread threads + UnreadThreads = Box.ThreadsUnread; + // manage unread threads - if (Box.ThreadsUnread > 0) { + if (UnreadThreads > 0) { // set the notification icon - UI.notifyIcon.Icon = Box.ThreadsUnread <= Settings.Default.UNSTACK_BOUNDARY ? Resources.mails : Resources.stack; + UI.notifyIcon.Icon = UnreadThreads <= Settings.Default.UNSTACK_BOUNDARY ? Resources.mails : Resources.stack; // manage message notification if (Settings.Default.MessageNotification) { @@ -204,7 +213,7 @@ public async Task Sync(bool manual = true, bool token = false) { })).ExecuteAsync(); // display a balloon tip in the systray with the total of unread threads and message details, depending on the user privacy setting - if (Box.ThreadsUnread == 1 && Settings.Default.PrivacyNotification != (uint)Notification.Privacy.All) { + if (UnreadThreads == 1 && Settings.Default.PrivacyNotification != (uint)Notification.Privacy.All) { string subject = ""; string from = ""; @@ -221,7 +230,7 @@ public async Task Sync(bool manual = true, bool token = false) { from = match.Captures[0].Value.Replace(" <", "").Replace("\"", ""); } else { match = Regex.Match(value, "?"); - from = match.Length != 0 ? match.Value.ToLower().Replace("<", "").Replace(">", "") : value.Replace(match.Value, $"{Box.ThreadsUnread} {Translation.unreadMessage}"); + from = match.Length != 0 ? match.Value.ToLower().Replace("<", "").Replace(">", "") : value.Replace(match.Value, $"{UnreadThreads} {Translation.unreadMessage}"); } } } @@ -241,32 +250,20 @@ public async Task Sync(bool manual = true, bool token = false) { UI.NotificationService.Tip(from, subject); } else { - UI.NotificationService.Tip($"{Box.ThreadsUnread} {(Box.ThreadsUnread > 1 ? Translation.unreadMessages : Translation.unreadMessage)}", Translation.newUnreadMessage); + UI.NotificationService.Tip($"{UnreadThreads} {(UnreadThreads > 1 ? Translation.unreadMessages : Translation.unreadMessage)}", Translation.newUnreadMessage); } // update the notification tag to allow the user to directly display the specified view (inbox/message/spam) in a browser - UI.NotificationService.Tag = $"#inbox{(Box.ThreadsUnread == 1 ? $"/{message.Id}" : "")}"; + UI.NotificationService.Tag = $"#inbox{(UnreadThreads == 1 ? $"/{message.Id}" : "")}"; } // display the notification text - UI.notifyIcon.Text = $"{Box.ThreadsUnread} {(Box.ThreadsUnread > 1 ? Translation.unreadMessages : Translation.unreadMessage)}"; + UI.notifyIcon.Text = $"{UnreadThreads} {(UnreadThreads > 1 ? Translation.unreadMessages : Translation.unreadMessage)}"; // enable the mark as read menu item - UI.menuItemMarkAsRead.Text = $"{Translation.markAsRead} ({Box.ThreadsUnread})"; + UI.menuItemMarkAsRead.Text = $"{Translation.markAsRead} ({UnreadThreads})"; UI.menuItemMarkAsRead.Enabled = true; - } else { - - // restore the default systray icon and text - UI.notifyIcon.Icon = Resources.normal; - UI.notifyIcon.Text = Translation.noMessage; - - // disable the mark as read menu item - UI.menuItemMarkAsRead.Text = Translation.markAsRead; - UI.menuItemMarkAsRead.Enabled = false; } - - // save the number of unread threads - UnreadThreads = Box.ThreadsUnread; } catch (IOException exception) { // log the exception from mscorlib: sometimes the process can not access the token response file because it is used by another process @@ -310,9 +307,9 @@ public async Task MarkAsRead() { }; // check for unread spams - bool unreadSpams = UI.NotificationService.Tag == "#spam"; + bool spams = UnreadSpams > 0; - if (unreadSpams) { + if (spams) { filter.Add("SPAM"); } @@ -343,29 +340,16 @@ public async Task MarkAsRead() { Box = await User.Labels.Get("me", "INBOX").ExecuteAsync(); // update the statistics only when there is no unread spams - if (!unreadSpams) { + if (!spams) { await UpdateStatistics().ConfigureAwait(false); } } // sync the inbox again if the user has just mark spams as read - if (unreadSpams) { + if (spams) { await Sync().ConfigureAwait(false); } else { - - // restore the default systray icon and text - UI.notifyIcon.Icon = Resources.normal; - UI.notifyIcon.Text = Translation.noMessage; - - // clean the tag - UI.NotificationService.Tag = null; - - // reset the number of unread threads - UnreadThreads = 0; - - // disable the mark as read menu item - UI.menuItemMarkAsRead.Text = Translation.markAsRead; - UI.menuItemMarkAsRead.Enabled = false; + UI.NotificationService.Reset(); } } catch (TokenResponseException exception) { @@ -523,6 +507,13 @@ public int? UnreadThreads { get; set; } = 0; + /// + /// Unread spams + /// + public int? UnreadSpams { + get; set; + } = 0; + /// /// Number of automatic reconnection attempts /// diff --git a/code/Notification.cs b/code/Notification.cs index 9c2a34b..10822fd 100644 --- a/code/Notification.cs +++ b/code/Notification.cs @@ -221,6 +221,23 @@ public async Task Resume() { await UI.GmailService.Inbox.Sync(); } + /// + /// Reset the notification area + /// + public void Reset() { + + // restore the default systray icon and text + UI.notifyIcon.Icon = Resources.normal; + UI.notifyIcon.Text = Translation.noMessage; + + // clean the tag + UI.NotificationService.Tag = null; + + // disable the mark as read menu item + UI.menuItemMarkAsRead.Text = Translation.markAsRead; + UI.menuItemMarkAsRead.Enabled = false; + } + /// /// Return the Gmail base URL depending on the notification behavior /// From d97e11c0bf816e106088bfbd608006a74a7cfe65 Mon Sep 17 00:00:00 2001 From: Xavier Foucrier Date: Mon, 25 Nov 2024 22:31:14 +0100 Subject: [PATCH 10/36] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20dispose=20cancellati?= =?UTF-8?q?on=20when=20it=20is=20no=20longer=20needed?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/Gmail.cs | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/code/Gmail.cs b/code/Gmail.cs index b1ad7c1..fb31084 100644 --- a/code/Gmail.cs +++ b/code/Gmail.cs @@ -188,21 +188,22 @@ private static async Task AuthorizationBroker() { using (FileStream stream = new FileStream($"{Path.GetDirectoryName(Application.ExecutablePath)}/client_secret.json", FileMode.Open, FileAccess.Read)) { // define a cancellation token source - CancellationTokenSource cancellation = new CancellationTokenSource(); - cancellation.CancelAfter(TimeSpan.FromSeconds(Settings.Default.OAUTH_TIMEOUT)); - - // wait for the user validation, only if the user has not already authorized the application - UserCredential credential = await GoogleWebAuthorizationBroker.AuthorizeAsync( - GoogleClientSecrets.FromStream(stream).Secrets, - new string[] { GmailService.Scope.GmailModify }, - "user", - cancellation.Token, - new FileDataStore(Core.ApplicationDataFolder, true), - new LocalServerCodeReceiver(Resources.oauth_message) - ); - - // return the user credential - return credential; + using (CancellationTokenSource cancellation = new CancellationTokenSource()) { + cancellation.CancelAfter(TimeSpan.FromSeconds(Settings.Default.OAUTH_TIMEOUT)); + + // wait for the user validation, only if the user has not already authorized the application + UserCredential credential = await GoogleWebAuthorizationBroker.AuthorizeAsync( + GoogleClientSecrets.FromStream(stream).Secrets, + new string[] { GmailService.Scope.GmailModify }, + "user", + cancellation.Token, + new FileDataStore(Core.ApplicationDataFolder, true), + new LocalServerCodeReceiver(Resources.oauth_message) + ); + + // return the user credential + return credential; + } } } From c2d73ad757d9bf07f6010c9a3fc9fad121198aaf Mon Sep 17 00:00:00 2001 From: Xavier Foucrier Date: Mon, 25 Nov 2024 22:32:20 +0100 Subject: [PATCH 11/36] =?UTF-8?q?=F0=9F=92=84=20improve=20oauth=20message?= =?UTF-8?q?=20rendering?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/Resources/oauth/message.html | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/code/Resources/oauth/message.html b/code/Resources/oauth/message.html index 9845d0c..8ecb903 100644 --- a/code/Resources/oauth/message.html +++ b/code/Resources/oauth/message.html @@ -24,8 +24,8 @@ height: 100vh; margin: 0; background: var(--contrast-color) linear-gradient(to bottom right, var(--contrast-color), var(--darken-color)); - font-family: 'Inter UI', Arial, sans-serif; - font-size: 15px; + font-family: var(--font); + font-size: 1.2em; color: var(--base-color); text-align: left; user-select: none; @@ -44,12 +44,13 @@ } small { - font-size: 10px; + font-size: 12px; opacity: 0.5; } .box { - max-width: 500px; + max-width: 550px; + padding: 50px; } .message { From efc1946dbd4093a39c8e286bd28bfd73f47bc6ff Mon Sep 17 00:00:00 2001 From: Xavier Foucrier Date: Tue, 26 Nov 2024 13:51:03 +0100 Subject: [PATCH 12/36] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20move=20`ringtone`=20?= =?UTF-8?q?to=20notification=20class?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/Inbox.cs | 25 ------------------------- code/Notification.cs | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 25 deletions(-) diff --git a/code/Inbox.cs b/code/Inbox.cs index f4fd066..e8aeeeb 100644 --- a/code/Inbox.cs +++ b/code/Inbox.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using System.Media; using System.Net; using System.Text.RegularExpressions; using System.Threading.Tasks; @@ -141,11 +140,6 @@ public async Task Sync(bool manual = true, bool token = false) { // manage unread spams if (UnreadSpams > 0) { - // play a sound on unread spams - if (Settings.Default.AudioNotification) { - SystemSounds.Exclamation.Play(); - } - // display a balloon tip in the systray with the total of unread threads UI.NotificationService.Tip($"{UnreadSpams} {(UnreadSpams > 1 ? Translation.unreadSpams : Translation.unreadSpam)}", Translation.newUnreadSpam, Notification.Type.Error); @@ -184,25 +178,6 @@ public async Task Sync(bool manual = true, bool token = false) { // manage message notification if (Settings.Default.MessageNotification) { - // play a sound on unread threads - if (Settings.Default.AudioNotification) { - - // play a ringtone based on user setting - if (Settings.Default.Ringtone) { - - // switch to the default ringtone if the audio file can't be found - if (File.Exists(Settings.Default.RingtoneFile)) { - using (SoundPlayer player = new SoundPlayer(Settings.Default.RingtoneFile)) { - player.Play(); - } - } else { - Settings.Default.Ringtone = false; - } - } else { - SystemSounds.Asterisk.Play(); - } - } - // get the message details UsersResource.MessagesResource.ListRequest messages = User.Messages.List("me"); messages.LabelIds = "UNREAD"; diff --git a/code/Notification.cs b/code/Notification.cs index 10822fd..e700d6d 100644 --- a/code/Notification.cs +++ b/code/Notification.cs @@ -1,5 +1,7 @@ using System; using System.Diagnostics; +using System.IO; +using System.Media; using System.Threading.Tasks; using System.Windows.Forms; using notifier.Languages; @@ -65,6 +67,9 @@ public Notification(ref Main form) { /// How long the notification is displayed public void Tip(string title, string text, Type icon = Type.Info, int duration = 450) { UI.notifyIcon.ShowBalloonTip(duration, title, text, (ToolTipIcon)icon); + + // play audio based on balloon type + Ringtone(icon); } /// @@ -238,6 +243,41 @@ public void Reset() { UI.menuItemMarkAsRead.Enabled = false; } + /// + /// Play ringtone based on displayed notification + /// + /// + private void Ringtone(Type type = Type.Info) { + if (!Settings.Default.AudioNotification) { + return; + } + + // + switch (type) { + case Type.Info: + + // play a ringtone based on user setting + if (Settings.Default.Ringtone) { + + // switch to the default ringtone if the audio file can't be found + if (File.Exists(Settings.Default.RingtoneFile)) { + using (SoundPlayer player = new SoundPlayer(Settings.Default.RingtoneFile)) { + player.Play(); + } + } else { + Settings.Default.Ringtone = false; + } + } else { + SystemSounds.Asterisk.Play(); + } + + break; + case Type.Error: + SystemSounds.Exclamation.Play(); + break; + } + } + /// /// Return the Gmail base URL depending on the notification behavior /// From 914018905c9171089e1800f72ed44e0573d3fd39 Mon Sep 17 00:00:00 2001 From: Xavier Foucrier Date: Tue, 26 Nov 2024 13:52:21 +0100 Subject: [PATCH 13/36] =?UTF-8?q?=E2=9C=8F=EF=B8=8F=20fill=20missing=20com?= =?UTF-8?q?ments?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/Notification.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/Notification.cs b/code/Notification.cs index e700d6d..7c1982a 100644 --- a/code/Notification.cs +++ b/code/Notification.cs @@ -246,13 +246,13 @@ public void Reset() { /// /// Play ringtone based on displayed notification /// - /// + /// Type of the ringtone private void Ringtone(Type type = Type.Info) { if (!Settings.Default.AudioNotification) { return; } - // + // play audio based on type switch (type) { case Type.Info: From 94a7102c54921250bd759e7bfb4bb703d19f7685 Mon Sep 17 00:00:00 2001 From: Xavier Foucrier Date: Tue, 26 Nov 2024 21:14:30 +0100 Subject: [PATCH 14/36] =?UTF-8?q?=E2=9C=8F=EF=B8=8F=20use=20named=20parame?= =?UTF-8?q?ter=20instead?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/Computer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/Computer.cs b/code/Computer.cs index 902eca8..b6e88d7 100644 --- a/code/Computer.cs +++ b/code/Computer.cs @@ -88,7 +88,7 @@ public void BindSessionSwitch() { } // synchronize the inbox and renew the token - await UI.GmailService.Inbox.Sync(true, true); + await UI.GmailService.Inbox.Sync(token: true); // enable the timer properly UI.timer.Enabled = true; From 8d966f888194673412c01596ac7ae3bca64036a6 Mon Sep 17 00:00:00 2001 From: Xavier Foucrier Date: Tue, 26 Nov 2024 21:24:03 +0100 Subject: [PATCH 15/36] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20refactor=20inbox=20`?= =?UTF-8?q?sync`=20core=20method?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/Inbox.cs | 270 +++++++++++++++++++++++++++++--------------------- code/Main.cs | 2 +- 2 files changed, 158 insertions(+), 114 deletions(-) diff --git a/code/Inbox.cs b/code/Inbox.cs index e8aeeeb..1204542 100644 --- a/code/Inbox.cs +++ b/code/Inbox.cs @@ -16,6 +16,14 @@ class Inbox { #region #attributes + /// + /// Synchronization action + /// + public enum SyncAction : uint { + Automatic = 0, + Manual = 1 + } + /// /// Main user resource /// @@ -46,9 +54,9 @@ public Inbox(ref Main form) { /// /// Asynchronous method used to synchronize the user inbox /// - /// Indicate if the synchronization come's from the timer tick or has been manually triggered + /// Indicate if the synchronization come's from the timer tick or has been manually triggered by the user /// Indicate if the Gmail token need to be refreshed - public async Task Sync(bool manual = true, bool token = false) { + public async Task Sync(SyncAction action = SyncAction.Manual, bool token = false) { // do a small ping on the update service await UI.UpdateService.Ping(); @@ -58,8 +66,8 @@ public async Task Sync(bool manual = true, bool token = false) { return; } - // temp variable - bool userAction = manual; + // store last user action + Action = action; // update the synchronization time Time = DateTime.Now; @@ -73,12 +81,12 @@ public async Task Sync(bool manual = true, bool token = false) { // reset reconnection count and prevent the application from displaying continuous warning icon when a timertick synchronization occurs after a reconnection attempt if (ReconnectionAttempts != 0) { - userAction = true; + Action = SyncAction.Manual; ReconnectionAttempts = 0; } - // disable the timeout when the user do a manual synchronization - if (userAction && UI.NotificationService.Paused) { + // resume notification service when the user do a manual synchronization + if (Action == SyncAction.Manual && UI.NotificationService.Paused) { await UI.NotificationService.Resume(); return; @@ -103,7 +111,7 @@ public async Task Sync(bool manual = true, bool token = false) { UI.menuItemSettings.Enabled = true; // display the sync icon, but only on manual synchronization - if (userAction) { + if (Action == SyncAction.Manual) { UI.notifyIcon.Icon = Resources.sync; UI.notifyIcon.Text = Translation.sync; } @@ -119,148 +127,177 @@ public async Task Sync(bool manual = true, bool token = false) { Box = await User.Labels.Get("me", "INBOX").ExecuteAsync(); // update the statistics - if (userAction) { + if (Action == SyncAction.Manual) { await UpdateStatistics().ConfigureAwait(false); } - // manage the spam notification - if (Settings.Default.SpamNotification) { - - // get the "spam" label - Label spam = await User.Labels.Get("me", "SPAM").ExecuteAsync(); - - // exit the sync if the number of unread spams is the same as before - if (!userAction && (spam.ThreadsUnread == UnreadSpams) && UnreadSpams != 0) { - return; - } + // synchronize inbox spams + if (await SyncSpams()) { + return; + } - // save the number of unread spams - UnreadSpams = spam.ThreadsUnread; + // synchronize inbox threads + if (await SyncThreads()) { + return; + } + } catch (IOException exception) { - // manage unread spams - if (UnreadSpams > 0) { + // log the exception from mscorlib: sometimes the process can not access the token response file because it is used by another process + Core.Log($"IOException: {exception.Message}"); + } catch (TokenResponseException exception) { - // display a balloon tip in the systray with the total of unread threads - UI.NotificationService.Tip($"{UnreadSpams} {(UnreadSpams > 1 ? Translation.unreadSpams : Translation.unreadSpam)}", Translation.newUnreadSpam, Notification.Type.Error); + // restart if the application has no Gmail grant access anymore + if (exception.Error.Error == "invalid_grant") { + Core.RestartApplication(); + } + } catch (Exception exception) { - // set the notification icon and text - UI.notifyIcon.Icon = Resources.spam; - UI.notifyIcon.Text = $"{UnreadSpams} {(UnreadSpams > 1 ? Translation.unreadSpams : Translation.unreadSpam)}"; + // display a balloon tip in the systray + UI.notifyIcon.Icon = Resources.warning; + UI.notifyIcon.Text = Translation.syncError; + UI.NotificationService.Tip(Translation.error, Translation.syncErrorOccured, Notification.Type.Warning, 1500); - // enable the mark as read menu item - UI.menuItemMarkAsRead.Text = $"{Translation.markAsRead} ({UnreadSpams})"; - UI.menuItemMarkAsRead.Enabled = true; + // log the error + Core.Log($"Sync: {exception.Message}"); + } finally { + UI.notifyIcon.Text = $"{UI.notifyIcon.Text.Split('\n')[0]}\n{Translation.syncTime.Replace("{time}", Time.ToLongTimeString())}"; + } + } - // update the tag - UI.NotificationService.Tag = "#spam"; + /// + /// Asynchronous method used to synchronize the inbox spams + /// + /// Whether or not unread spams are present in the inbox + private async Task SyncSpams() { + if (!Settings.Default.SpamNotification) { + return false; + } - return; - } - } + // get the "spam" label + Label spam = await User.Labels.Get("me", "SPAM").ExecuteAsync(); - // exit the sync if the number of unread threads is the same as before - if (!userAction && (Box.ThreadsUnread == UnreadThreads) && UnreadThreads != 0) { - return; - } + // exit the sync if the number of unread spams is the same as before + if (Action == SyncAction.Automatic && (spam.ThreadsUnread == UnreadSpams) && UnreadSpams != 0) { + return true; + } - // reset notification service - UI.NotificationService.Reset(); + // save the number of unread spams + UnreadSpams = spam.ThreadsUnread; - // save the number of unread threads - UnreadThreads = Box.ThreadsUnread; + // manage unread spams + if (UnreadSpams > 0) { - // manage unread threads - if (UnreadThreads > 0) { + // display a balloon tip in the systray with the total of unread threads + UI.NotificationService.Tip($"{UnreadSpams} {(UnreadSpams > 1 ? Translation.unreadSpams : Translation.unreadSpam)}", Translation.newUnreadSpam, Notification.Type.Error); - // set the notification icon - UI.notifyIcon.Icon = UnreadThreads <= Settings.Default.UNSTACK_BOUNDARY ? Resources.mails : Resources.stack; + // set the notification icon and text + UI.notifyIcon.Icon = Resources.spam; + UI.notifyIcon.Text = $"{UnreadSpams} {(UnreadSpams > 1 ? Translation.unreadSpams : Translation.unreadSpam)}"; - // manage message notification - if (Settings.Default.MessageNotification) { + // enable the mark as read menu item + UI.menuItemMarkAsRead.Text = $"{Translation.markAsRead} ({UnreadSpams})"; + UI.menuItemMarkAsRead.Enabled = true; - // get the message details - UsersResource.MessagesResource.ListRequest messages = User.Messages.List("me"); - messages.LabelIds = "UNREAD"; - messages.MaxResults = 1; + // update the tag + UI.NotificationService.Tag = "#spam"; - Message message = await User.Messages.Get("me", await messages.ExecuteAsync().ContinueWith(m => { - return m.Result.Messages.First().Id; - })).ExecuteAsync(); + return true; + } - // display a balloon tip in the systray with the total of unread threads and message details, depending on the user privacy setting - if (UnreadThreads == 1 && Settings.Default.PrivacyNotification != (uint)Notification.Privacy.All) { - string subject = ""; - string from = ""; + return false; + } - foreach (MessagePartHeader header in message.Payload.Headers) { - string name = header.Name.ToLower(); - string value = header.Value; + /// + /// Asynchronous method used to synchronize the inbox threads + /// + /// Whether or not unread threads are present in the inbox + private async Task SyncThreads() { - if (name == "subject") { - subject = string.IsNullOrEmpty(value) ? Translation.newUnreadMessage : value; - } else if (name == "from") { - Match match = Regex.Match(value, ".* <"); + // exit the sync if the number of unread threads is the same as before + if (Action == SyncAction.Automatic && (Box.ThreadsUnread == UnreadThreads) && UnreadThreads != 0) { + return false; + } - if (match.Length != 0) { - from = match.Captures[0].Value.Replace(" <", "").Replace("\"", ""); - } else { - match = Regex.Match(value, "?"); - from = match.Length != 0 ? match.Value.ToLower().Replace("<", "").Replace(">", "") : value.Replace(match.Value, $"{UnreadThreads} {Translation.unreadMessage}"); - } + // reset notification service + UI.NotificationService.Reset(); + + // save the number of unread threads + UnreadThreads = Box.ThreadsUnread; + + // manage unread threads + if (UnreadThreads > 0) { + + // set the notification icon + UI.notifyIcon.Icon = UnreadThreads <= Settings.Default.UNSTACK_BOUNDARY ? Resources.mails : Resources.stack; + + // manage message notification + if (Settings.Default.MessageNotification) { + + // get the message details + UsersResource.MessagesResource.ListRequest messages = User.Messages.List("me"); + messages.LabelIds = "UNREAD"; + messages.MaxResults = 1; + + Message message = await User.Messages.Get("me", await messages.ExecuteAsync().ContinueWith(m => { + return m.Result.Messages.First().Id; + })).ExecuteAsync(); + + // display a balloon tip in the systray with the total of unread threads and message details, depending on the user privacy setting + if (UnreadThreads == 1 && Settings.Default.PrivacyNotification != (uint)Notification.Privacy.All) { + string subject = ""; + string from = ""; + + foreach (MessagePartHeader header in message.Payload.Headers) { + string name = header.Name.ToLower(); + string value = header.Value; + + if (name == "subject") { + subject = string.IsNullOrEmpty(value) ? Translation.newUnreadMessage : value; + } else if (name == "from") { + Match match = Regex.Match(value, ".* <"); + + if (match.Length != 0) { + from = match.Captures[0].Value.Replace(" <", "").Replace("\"", ""); + } else { + match = Regex.Match(value, "?"); + from = match.Length != 0 ? match.Value.ToLower().Replace("<", "").Replace(">", "") : value.Replace(match.Value, $"{UnreadThreads} {Translation.unreadMessage}"); } } + } - if (Settings.Default.PrivacyNotification == (uint)Notification.Privacy.None) { - subject = string.IsNullOrEmpty(message.Snippet) ? Translation.newUnreadMessage : WebUtility.HtmlDecode(message.Snippet); - } + if (Settings.Default.PrivacyNotification == (uint)Notification.Privacy.None) { + subject = string.IsNullOrEmpty(message.Snippet) ? Translation.newUnreadMessage : WebUtility.HtmlDecode(message.Snippet); + } - // detect if the message contains attachments - if (message.Payload.Parts != null && message.Payload.MimeType == "multipart/mixed") { - int attachments = message.Payload.Parts.Where(part => !string.IsNullOrEmpty(part.Filename)).Count(); + // detect if the message contains attachments + if (message.Payload.Parts != null && message.Payload.MimeType == "multipart/mixed") { + int attachments = message.Payload.Parts.Where(part => !string.IsNullOrEmpty(part.Filename)).Count(); - if (attachments > 0) { - from = $"{(from.Length > 48 ? from.Substring(0, 48) : from)} - {attachments} {(attachments > 1 ? Translation.attachments : Translation.attachment)}"; - } + if (attachments > 0) { + from = $"{(from.Length > 48 ? from.Substring(0, 48) : from)} - {attachments} {(attachments > 1 ? Translation.attachments : Translation.attachment)}"; } - - UI.NotificationService.Tip(from, subject); - } else { - UI.NotificationService.Tip($"{UnreadThreads} {(UnreadThreads > 1 ? Translation.unreadMessages : Translation.unreadMessage)}", Translation.newUnreadMessage); } - // update the notification tag to allow the user to directly display the specified view (inbox/message/spam) in a browser - UI.NotificationService.Tag = $"#inbox{(UnreadThreads == 1 ? $"/{message.Id}" : "")}"; + UI.NotificationService.Tip(from, subject); + } else { + UI.NotificationService.Tip($"{UnreadThreads} {(UnreadThreads > 1 ? Translation.unreadMessages : Translation.unreadMessage)}", Translation.newUnreadMessage); } - // display the notification text - UI.notifyIcon.Text = $"{UnreadThreads} {(UnreadThreads > 1 ? Translation.unreadMessages : Translation.unreadMessage)}"; - - // enable the mark as read menu item - UI.menuItemMarkAsRead.Text = $"{Translation.markAsRead} ({UnreadThreads})"; - UI.menuItemMarkAsRead.Enabled = true; + // update the notification tag to allow the user to directly display the specified view (inbox/message/spam) in a browser + UI.NotificationService.Tag = $"#inbox{(UnreadThreads == 1 ? $"/{message.Id}" : "")}"; } - } catch (IOException exception) { - // log the exception from mscorlib: sometimes the process can not access the token response file because it is used by another process - Core.Log($"IOException: {exception.Message}"); - } catch (TokenResponseException exception) { + // display the notification text + UI.notifyIcon.Text = $"{UnreadThreads} {(UnreadThreads > 1 ? Translation.unreadMessages : Translation.unreadMessage)}"; - // restart if the application has no Gmail grant access anymore - if (exception.Error.Error == "invalid_grant") { - Core.RestartApplication(); - } - } catch (Exception exception) { - - // display a balloon tip in the systray - UI.notifyIcon.Icon = Resources.warning; - UI.notifyIcon.Text = Translation.syncError; - UI.NotificationService.Tip(Translation.error, Translation.syncErrorOccured, Notification.Type.Warning, 1500); + // enable the mark as read menu item + UI.menuItemMarkAsRead.Text = $"{Translation.markAsRead} ({UnreadThreads})"; + UI.menuItemMarkAsRead.Enabled = true; - // log the error - Core.Log($"Sync: {exception.Message}"); - } finally { - UI.notifyIcon.Text = $"{UI.notifyIcon.Text.Split('\n')[0]}\n{Translation.syncTime.Replace("{time}", Time.ToLongTimeString())}"; + return true; } + + return false; } /// @@ -468,6 +505,13 @@ public async Task UpdateStatistics() { #region #accessors + /// + /// Last synchronization action + /// + public SyncAction Action { + get; set; + } = SyncAction.Automatic; + /// /// Last synchronization time /// diff --git a/code/Main.cs b/code/Main.cs index 7b59209..1205c72 100644 --- a/code/Main.cs +++ b/code/Main.cs @@ -533,7 +533,7 @@ private async void timer_Tick(object sender, EventArgs e) { } // synchronize the inbox - await GmailService.Inbox.Sync(false); + await GmailService.Inbox.Sync(Inbox.SyncAction.Automatic); } /// From 996da2c1f89339e0bef6e51f77622a61ba3c9cb0 Mon Sep 17 00:00:00 2001 From: Xavier Foucrier Date: Fri, 29 Nov 2024 12:28:48 +0100 Subject: [PATCH 16/36] =?UTF-8?q?=F0=9F=92=84=20fix=20website=20link=20are?= =?UTF-8?q?a?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/Main.de.resx | 56 ++++++++++++++++---------------- code/Main.en.resx | 74 +++++++++++++++++++++--------------------- code/Main.resx | 2 +- code/Main.ru.resx | 82 +++++++++++++++++++++++------------------------ 4 files changed, 107 insertions(+), 107 deletions(-) diff --git a/code/Main.de.resx b/code/Main.de.resx index 9ad83bd..5d38a34 100644 --- a/code/Main.de.resx +++ b/code/Main.de.resx @@ -1,17 +1,17 @@  - @@ -529,7 +529,7 @@ als gelesen markiert. Open Source, veröffentlicht unter der MIT-Lizenz - 41, 15 + 42, 15 153, 34 diff --git a/code/Main.en.resx b/code/Main.en.resx index 2493539..82f1c41 100644 --- a/code/Main.en.resx +++ b/code/Main.en.resx @@ -117,6 +117,9 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + General + 194, 108 @@ -143,6 +146,9 @@ at the next application startup. Language: + + Behavior + 157, 17 @@ -167,11 +173,11 @@ at the next application startup. Ask before leaving the application - - Behavior + + Account - - General + + Statistics 38, 13 @@ -185,8 +191,8 @@ at the next application startup. Inbox - - Statistics + + Authentication 83, 13 @@ -203,11 +209,8 @@ at the next application startup. Sign out - - Authentication - - - Account + + Behavior do nothing @@ -261,8 +264,8 @@ will mark all inbox messages as read. Upon receipt of multiple messages, this option will automatically open the inbox. - - Behavior + + Mail @@ -309,8 +312,8 @@ will automatically open the inbox. Sound notification - - Mail + + Privacy 172, 13 @@ -336,8 +339,11 @@ will automatically open the inbox. Display all message content - - Privacy + + Schedule + + + Time slot 47, 13 @@ -399,8 +405,8 @@ will automatically open the inbox. sunday - - Time slot + + Behavior 195, 17 @@ -420,11 +426,11 @@ will automatically open the inbox. Enable scheduled synchronization - - Behavior + + Updates - - Schedule + + Availability 165, 99 @@ -459,8 +465,8 @@ will automatically open the inbox. Last checked: - - Availability + + Behavior 13, 84 @@ -496,11 +502,8 @@ will automatically open the inbox. Enable automatic update checking - - Behavior - - - Updates + + About @@ -523,7 +526,7 @@ will automatically open the inbox. Open Source, distributed under MIT License - 39, 15 + 40, 15 150, 34 @@ -551,9 +554,6 @@ a Tokyo-based designer and developer Development - - About - 223, 13 @@ -596,6 +596,9 @@ a Tokyo-based designer and developer Mark as read + + Do not disturb + Disable @@ -611,9 +614,6 @@ a Tokyo-based designer and developer Indefinitely - - Do not disturb - Open diff --git a/code/Main.resx b/code/Main.resx index 7b448ca..4b0a8a3 100644 --- a/code/Main.resx +++ b/code/Main.resx @@ -1864,7 +1864,7 @@ prochain démarrage de l'application. 2, 3, 2, 3 - 40, 15 + 41, 15 NoControl diff --git a/code/Main.ru.resx b/code/Main.ru.resx index e4aef1e..c7edfd3 100644 --- a/code/Main.ru.resx +++ b/code/Main.ru.resx @@ -117,6 +117,12 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Общее + + + Интерфейс + 178, 109 @@ -143,8 +149,8 @@ Язык: - - Интерфейс + + Поведение 167, 17 @@ -170,11 +176,11 @@ Спрашивать при выходе из приложения - - Поведение + + Аккаунт - - Общее + + Статистика 67, 13 @@ -194,8 +200,8 @@ Входящие - - Статистика + + Проверка подлинности 99, 13 @@ -215,11 +221,11 @@ Выйти - - Проверка подлинности + + Уведомление - - Аккаунт + + Поведение ничего не делать @@ -274,8 +280,8 @@ При получении нескольких сообщений эта опция автоматически откроет папку "Входящие". - - Поведение + + Почта @@ -325,10 +331,10 @@ Звуковое уведомление - - Почта + + Конфиденциальность - + Уведомление @@ -355,11 +361,11 @@ Показывать всё содержимое сообщения - - Уведомление + + Расписание - - Конфиденциальность + + Временной интервал 70, 13 @@ -421,8 +427,8 @@ воскресенье - - Временной интервал + + Поведение @@ -464,11 +470,11 @@ Включить синхронизацию по расписанию - - Поведение + + Обновления - - Расписание + + Доступность 172, 99 @@ -503,8 +509,8 @@ Последняя проверка: - - Доступность + + Поведение 112, 17 @@ -524,11 +530,8 @@ Включить автоматическую проверку обновлений - - Поведение - - - Обновления + + Инфо @@ -551,7 +554,7 @@ Открытый исходный код, лицензия MIT - 38, 15 + 39, 15 148, 34 @@ -591,9 +594,6 @@ Версия - - Инфо - 237, 13 @@ -633,6 +633,9 @@ Отметить как прочитанное + + Не беспокоить + Отключить @@ -651,9 +654,6 @@ Бессрочно - - Не беспокоить - Открыть From 46abecfbb941ee6f7b0a54a5dc8be2a3e1f8ecea Mon Sep 17 00:00:00 2001 From: Xavier Foucrier Date: Fri, 29 Nov 2024 12:41:57 +0100 Subject: [PATCH 17/36] =?UTF-8?q?=E2=9A=A1=EF=B8=8F=20improve=20the=20way?= =?UTF-8?q?=20application=20restart=20is=20running?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/Core.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/code/Core.cs b/code/Core.cs index 0c54878..e3a75df 100644 --- a/code/Core.cs +++ b/code/Core.cs @@ -1,6 +1,7 @@ using System; using System.Diagnostics; using System.IO; +using System.Threading.Tasks; using System.Windows.Forms; using notifier.Properties; @@ -34,13 +35,15 @@ static Core() { public static void RestartApplication() { // start a new process - Process.Start(new ProcessStartInfo("cmd.exe", $"/C ping 127.0.0.1 -n 2 && \"{Application.ExecutablePath}\"") { + Process.Start(new ProcessStartInfo { + FileName = Application.ExecutablePath, + UseShellExecute = true, WindowStyle = ProcessWindowStyle.Hidden, CreateNoWindow = true }); - // exit the application - Application.Exit(); + // exit the environment + Environment.Exit(0); } /// From a72f8369683452de2d13f284d1dc2fe116c1937b Mon Sep 17 00:00:00 2001 From: Xavier Foucrier Date: Fri, 29 Nov 2024 13:08:49 +0100 Subject: [PATCH 18/36] =?UTF-8?q?=E2=9A=A1=EF=B8=8F=20improve=20restart=20?= =?UTF-8?q?after=20an=20application=20update?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/Update.cs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/code/Update.cs b/code/Update.cs index 5ccaec9..5b3e28b 100644 --- a/code/Update.cs +++ b/code/Update.cs @@ -218,12 +218,18 @@ public async Task Download() { // start the setup installer when the download has complete and exit the current application client.DownloadFileCompleted += (object source, AsyncCompletedEventArgs target) => { - Process.Start(new ProcessStartInfo("cmd.exe", $"/C ping 127.0.0.1 -n 2 && \"{updatepath}\" {(Settings.Default.UpdateQuiet ? "/verysilent" : "")}") { + + // start a new process + Process.Start(new ProcessStartInfo { + FileName = updatepath, + UseShellExecute = true, WindowStyle = ProcessWindowStyle.Hidden, - CreateNoWindow = true + CreateNoWindow = true, + Arguments = Settings.Default.UpdateQuiet ? "/verysilent" : "" }); - Application.Exit(); + // exit the environment + Environment.Exit(0); }; // ensure that the Github package URI is callable From 5968f9d1febcd2dad44e0df551544b80cbef9d81 Mon Sep 17 00:00:00 2001 From: Xavier Foucrier Date: Fri, 29 Nov 2024 15:12:03 +0100 Subject: [PATCH 19/36] =?UTF-8?q?=F0=9F=94=92=20use=20tls=201.3=20to=20inc?= =?UTF-8?q?rease=20security=20with=20github?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/Update.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/Update.cs b/code/Update.cs index 5b3e28b..6b77edf 100644 --- a/code/Update.cs +++ b/code/Update.cs @@ -114,8 +114,8 @@ public async Task Ping() { public async Task Check(bool verbose = true, bool startup = false) { try { - // using tls 1.2 as security protocol to contact Github.com - ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; + // using tls 1.3 as security protocol to contact Github.com + ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls13; // get the latest tag in the Github repository tags webpage HttpResponseMessage response = await Http.GetAsync($"{Settings.Default.GITHUB_REPOSITORY}/tags"); From 1c238b002342eb2a2cc47646baf5a0da716625f3 Mon Sep 17 00:00:00 2001 From: Xavier Foucrier Date: Fri, 29 Nov 2024 16:43:15 +0100 Subject: [PATCH 20/36] =?UTF-8?q?=E2=9C=A8=20properly=20store=20major/mino?= =?UTF-8?q?r/patch=20core=20versions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/Core.cs | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/code/Core.cs b/code/Core.cs index e3a75df..91fa74c 100644 --- a/code/Core.cs +++ b/code/Core.cs @@ -22,11 +22,11 @@ static Core() { // initialize the application version number, based on scheme Semantic Versioning - https://semver.org string[] ProductVersion = Application.ProductVersion.Split('.'); - string VersionMajor = ProductVersion[0]; - string VersionMinor = ProductVersion[1]; - string VersionPatch = ProductVersion[2]; + MajorVersion = int.Parse(ProductVersion[0]); + MinorVersion = int.Parse(ProductVersion[1]); + PatchVersion = int.Parse(ProductVersion[2]); - Version = $"v{VersionMajor}.{VersionMinor}.{VersionPatch}"; + Version = $"v{MajorVersion}.{MinorVersion}.{PatchVersion}"; } /// @@ -74,6 +74,27 @@ public static string Version { get; } = ""; + /// + /// Major application version number + /// + public static int MajorVersion { + get; + } = 0; + + /// + /// Minor application version number + /// + public static int MinorVersion { + get; + } = 0; + + /// + /// Patch application version number + /// + public static int PatchVersion { + get; + } = 0; + #endregion } } \ No newline at end of file From d18b5d2b7e4d17733245f2e4b4a491395e982ea9 Mon Sep 17 00:00:00 2001 From: Xavier Foucrier Date: Fri, 29 Nov 2024 16:53:56 +0100 Subject: [PATCH 21/36] =?UTF-8?q?=E2=9C=8F=EF=B8=8F=20update=20visual=20st?= =?UTF-8?q?udio=20version=20number?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/Main.de.resx | 2 +- code/Main.en.resx | 2 +- code/Main.resx | 2 +- code/Main.ru.resx | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/code/Main.de.resx b/code/Main.de.resx index 5d38a34..1739a54 100644 --- a/code/Main.de.resx +++ b/code/Main.de.resx @@ -535,7 +535,7 @@ Open Source, veröffentlicht unter der MIT-Lizenz 153, 34 - Visual Studio 17.12.1, C# + Visual Studio 17.12.2, C# Entwickelt von Xavier Foucrier diff --git a/code/Main.en.resx b/code/Main.en.resx index 82f1c41..a83de72 100644 --- a/code/Main.en.resx +++ b/code/Main.en.resx @@ -532,7 +532,7 @@ Open Source, distributed under MIT License 150, 34 - Visual Studio 17.12.1, C# + Visual Studio 17.12.2, C# Developed by Xavier Foucrier diff --git a/code/Main.resx b/code/Main.resx index 4b0a8a3..3db90c1 100644 --- a/code/Main.resx +++ b/code/Main.resx @@ -1142,7 +1142,7 @@ de réception comme lus. linkVersion - Visual Studio 17.12.1, C# + Visual Studio 17.12.2, C# Développé par Xavier Foucrier diff --git a/code/Main.ru.resx b/code/Main.ru.resx index c7edfd3..b8560f4 100644 --- a/code/Main.ru.resx +++ b/code/Main.ru.resx @@ -560,7 +560,7 @@ 148, 34 - Visual Studio 17.12.1, C# + Visual Studio 17.12.2, C# Разработано Xavier Foucrier From 7c244441be0dee279937eb95119cf5e9670295b3 Mon Sep 17 00:00:00 2001 From: Xavier Foucrier Date: Fri, 29 Nov 2024 23:59:48 +0100 Subject: [PATCH 22/36] =?UTF-8?q?=E2=9A=A1=20use=20github=20api=20instead?= =?UTF-8?q?=20to=20get=20the=20last=20release?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/Update.cs | 36 ++++++++++++++++-------------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/code/Update.cs b/code/Update.cs index 6b77edf..9da800e 100644 --- a/code/Update.cs +++ b/code/Update.cs @@ -5,9 +5,10 @@ using System.IO; using System.Net; using System.Net.Http; +using System.Net.Http.Headers; using System.Threading.Tasks; using System.Windows.Forms; -using HtmlAgilityPack; +using Newtonsoft.Json.Linq; using notifier.Languages; using notifier.Properties; @@ -31,6 +32,11 @@ private enum Period : uint { /// private readonly HttpClient Http = new HttpClient(); + /// + /// Github API endpoint + /// + private readonly string GithubEndPoint = "https://api.github.com/repos/xavierfoucrier/inbox-notifier/releases"; + /// /// Reference to the main interface /// @@ -114,28 +120,18 @@ public async Task Ping() { public async Task Check(bool verbose = true, bool startup = false) { try { - // using tls 1.3 as security protocol to contact Github.com - ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls13; - - // get the latest tag in the Github repository tags webpage - HttpResponseMessage response = await Http.GetAsync($"{Settings.Default.GITHUB_REPOSITORY}/tags"); - - HtmlAgilityPack.HtmlDocument document = new HtmlAgilityPack.HtmlDocument(); - document.LoadHtml(await response.Content.ReadAsStringAsync()); + // define user agent + Http.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("InboxNotifier", Core.Version)); - HtmlNode node = document.DocumentNode.SelectSingleNode("//a[contains(@href, 'releases/tag/v')]"); + // request the open Github API + HttpResponseMessage httpResponse = await Http.GetAsync(GithubEndPoint); + httpResponse.EnsureSuccessStatusCode(); - if (node == null) { - - // indicate to the user that the update service is not reachable for the moment - if (verbose) { - UI.NotificationService.Tip(Translation.updateServiceName, Translation.updateServiceUnreachable, Notification.Type.Warning, 1500); - } - - return; - } + string responseBody = await httpResponse.Content.ReadAsStringAsync(); + JArray releases = JArray.Parse(responseBody); - string release = node.InnerText.Trim(); + // get the most recent release version + string release = releases.First["tag_name"].ToString(); // store the latest update datetime control Settings.Default.UpdateControl = DateTime.Now; From 9642adc8afef5dba860bc5d2a393911450c17416 Mon Sep 17 00:00:00 2001 From: Xavier Foucrier Date: Sat, 30 Nov 2024 00:37:20 +0100 Subject: [PATCH 23/36] =?UTF-8?q?=F0=9F=93=A6=20remove=20log4net=20package?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/App.config | 4 ---- code/InboxNotifier.csproj | 3 --- 2 files changed, 7 deletions(-) diff --git a/code/App.config b/code/App.config index 51414ad..8ad4fa8 100644 --- a/code/App.config +++ b/code/App.config @@ -89,10 +89,6 @@ - - - - diff --git a/code/InboxNotifier.csproj b/code/InboxNotifier.csproj index f1c9229..8f5a9e5 100644 --- a/code/InboxNotifier.csproj +++ b/code/InboxNotifier.csproj @@ -232,9 +232,6 @@ 1.11.71 - - 3.0.3 - 13.0.3 From a1c505e8380269176e632216f062155d5752f919 Mon Sep 17 00:00:00 2001 From: Xavier Foucrier Date: Sat, 30 Nov 2024 00:39:45 +0100 Subject: [PATCH 24/36] =?UTF-8?q?=F0=9F=93=A6=20remove=20HtmlAgilityPack?= =?UTF-8?q?=20package?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/InboxNotifier.csproj | 3 --- 1 file changed, 3 deletions(-) diff --git a/code/InboxNotifier.csproj b/code/InboxNotifier.csproj index 8f5a9e5..ce5249f 100644 --- a/code/InboxNotifier.csproj +++ b/code/InboxNotifier.csproj @@ -229,9 +229,6 @@ 1.68.0.3427 - - 1.11.71 - 13.0.3 From a7c5e29118cfd6d985643fe45f1418452b6283a6 Mon Sep 17 00:00:00 2001 From: Xavier Foucrier Date: Sat, 30 Nov 2024 21:35:22 +0100 Subject: [PATCH 25/36] =?UTF-8?q?=E2=9C=8F=EF=B8=8F=20rename=20endpoint=20?= =?UTF-8?q?property?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/Update.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/code/Update.cs b/code/Update.cs index 9da800e..13afe27 100644 --- a/code/Update.cs +++ b/code/Update.cs @@ -33,9 +33,9 @@ private enum Period : uint { private readonly HttpClient Http = new HttpClient(); /// - /// Github API endpoint + /// Update endpoint /// - private readonly string GithubEndPoint = "https://api.github.com/repos/xavierfoucrier/inbox-notifier/releases"; + private readonly string EndPoint = "https://api.github.com/repos/xavierfoucrier/inbox-notifier/releases"; /// /// Reference to the main interface @@ -124,7 +124,7 @@ public async Task Check(bool verbose = true, bool startup = false) { Http.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("InboxNotifier", Core.Version)); // request the open Github API - HttpResponseMessage httpResponse = await Http.GetAsync(GithubEndPoint); + HttpResponseMessage httpResponse = await Http.GetAsync(EndPoint); httpResponse.EnsureSuccessStatusCode(); string responseBody = await httpResponse.Content.ReadAsStringAsync(); From 6e682cf835a13b01f3af06d905d6f61f2ea62e76 Mon Sep 17 00:00:00 2001 From: Xavier Foucrier Date: Mon, 2 Dec 2024 17:23:35 +0100 Subject: [PATCH 26/36] =?UTF-8?q?=E2=9A=A1=20only=20get=20`release`=20vers?= =?UTF-8?q?ion=20type?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/Update.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/code/Update.cs b/code/Update.cs index 13afe27..228d45f 100644 --- a/code/Update.cs +++ b/code/Update.cs @@ -3,6 +3,7 @@ using System.ComponentModel; using System.Diagnostics; using System.IO; +using System.Linq; using System.Net; using System.Net.Http; using System.Net.Http.Headers; @@ -130,8 +131,8 @@ public async Task Check(bool verbose = true, bool startup = false) { string responseBody = await httpResponse.Content.ReadAsStringAsync(); JArray releases = JArray.Parse(responseBody); - // get the most recent release version - string release = releases.First["tag_name"].ToString(); + // filter by releases only (exclude pre-releases) + string release = releases.Where(version => !(bool)version["prerelease"]).First()["tag_name"].ToString(); // store the latest update datetime control Settings.Default.UpdateControl = DateTime.Now; From 5d157bff83850e6cd770e1231da3017dac265f0a Mon Sep 17 00:00:00 2001 From: Xavier Foucrier Date: Tue, 3 Dec 2024 00:41:31 +0100 Subject: [PATCH 27/36] =?UTF-8?q?=F0=9F=8C=90=20add=20new=20translation=20?= =?UTF-8?q?for=20available=20major=20update?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/Languages/Translation.Designer.cs | 11 ++++++++++- code/Languages/Translation.de.resx | 3 +++ code/Languages/Translation.en.resx | 3 +++ code/Languages/Translation.resx | 3 +++ code/Languages/Translation.ru.resx | 3 +++ 5 files changed, 22 insertions(+), 1 deletion(-) diff --git a/code/Languages/Translation.Designer.cs b/code/Languages/Translation.Designer.cs index 2649caf..5d05037 100644 --- a/code/Languages/Translation.Designer.cs +++ b/code/Languages/Translation.Designer.cs @@ -19,7 +19,7 @@ namespace notifier.Languages { // à l'aide d'un outil, tel que ResGen ou Visual Studio. // Pour ajouter ou supprimer un membre, modifiez votre fichier .ResX, puis réexécutez ResGen // avec l'option /str ou régénérez votre projet VS. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] internal class Translation { @@ -531,6 +531,15 @@ internal static string mutexError { } } + /// + /// Recherche une chaîne localisée semblable à Une nouvelle version majeure de l'application est disponible sur Github : {version}. + /// + internal static string newMajorVersion { + get { + return ResourceManager.GetString("newMajorVersion", resourceCulture); + } + } + /// /// Recherche une chaîne localisée semblable à Double-cliquez sur l'icône pour accéder à votre boîte de réception.. /// diff --git a/code/Languages/Translation.de.resx b/code/Languages/Translation.de.resx index 0630629..fd34a86 100644 --- a/code/Languages/Translation.de.resx +++ b/code/Languages/Translation.de.resx @@ -282,6 +282,9 @@ Möchten Sie ihr Gmail Konto wirklich abmelden und die Anwendung neu starten? + + Eine neuere Hauptversion der Anwendung auf Github ist verfügbar: {version} + Doppelklicken Sie auf das Symbol, um auf Ihren Posteingang zuzugreifen. diff --git a/code/Languages/Translation.en.resx b/code/Languages/Translation.en.resx index e596038..858883b 100644 --- a/code/Languages/Translation.en.resx +++ b/code/Languages/Translation.en.resx @@ -282,6 +282,9 @@ Do you really want to disconnect your Gmail account and restart the application This option is not enabled on this type of application. + + A newer major version of the application is available on Github: {version} + Double-click the icon to access your inbox. diff --git a/code/Languages/Translation.resx b/code/Languages/Translation.resx index 3d07699..587f647 100644 --- a/code/Languages/Translation.resx +++ b/code/Languages/Translation.resx @@ -282,6 +282,9 @@ Voulez-vous vraiment déconnecter votre compte Google et redémarrer l'applicati Cette option n'est pas activée sur ce type d'application. + + Une nouvelle version majeure de l'application est disponible sur Github : {version} + Double-cliquez sur l'icône pour accéder à votre boîte de réception. diff --git a/code/Languages/Translation.ru.resx b/code/Languages/Translation.ru.resx index 2bf2f52..76adf74 100644 --- a/code/Languages/Translation.ru.resx +++ b/code/Languages/Translation.ru.resx @@ -282,6 +282,9 @@ Эта опция не включена для данного типа приложения. + + Более новая версия приложения доступна на Github: {version} + Дважды щёлкните по значку для доступа к папке "Входящие". From 0a397c4dbbb3b13a884926b0de7cf8e96c84c3ad Mon Sep 17 00:00:00 2001 From: Xavier Foucrier Date: Wed, 4 Dec 2024 00:41:45 +0100 Subject: [PATCH 28/36] =?UTF-8?q?=F0=9F=92=84=20focus=20the=20update=20but?= =?UTF-8?q?ton=20after=20balloon=20tip=20interaction?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/Notification.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/code/Notification.cs b/code/Notification.cs index 7c1982a..a445793 100644 --- a/code/Notification.cs +++ b/code/Notification.cs @@ -95,6 +95,7 @@ public async Task Interaction(bool balloon = false) { UI.WindowState = FormWindowState.Normal; UI.Focus(); UI.tabControl.SelectTab("tabPageUpdate"); + UI.buttonCheckForUpdate.Focus(); Tag = null; return; From f6fa07e759f34bcd13cc7795b44806913ecbde05 Mon Sep 17 00:00:00 2001 From: Xavier Foucrier Date: Wed, 4 Dec 2024 00:43:18 +0100 Subject: [PATCH 29/36] =?UTF-8?q?=E2=9C=A8=20don't=20rely=20on=20tag=20whe?= =?UTF-8?q?n=20checking=20for=20updates?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/Notification.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/Notification.cs b/code/Notification.cs index a445793..15e5f1f 100644 --- a/code/Notification.cs +++ b/code/Notification.cs @@ -89,7 +89,7 @@ public async Task Interaction(bool balloon = false) { } // display the form and focus the update tab - if (balloon && Tag == "update") { + if (balloon && UI.UpdateService.UpdateAvailable) { UI.Visible = true; UI.ShowInTaskbar = true; UI.WindowState = FormWindowState.Normal; From e1e3db58de36e2e7faa882bb7b6e0bf8547e8a91 Mon Sep 17 00:00:00 2001 From: Xavier Foucrier Date: Wed, 4 Dec 2024 11:06:47 +0100 Subject: [PATCH 30/36] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20set=20accessors=20de?= =?UTF-8?q?fault=20value?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/Update.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/Update.cs b/code/Update.cs index 228d45f..0a6ca3b 100644 --- a/code/Update.cs +++ b/code/Update.cs @@ -263,7 +263,7 @@ public async Task Download() { /// public bool UpdateAvailable { get; set; - } + } = false; /// /// Latest release version available @@ -277,7 +277,7 @@ public string ReleaseAvailable { /// public bool Updating { get; set; - } + } = false; #endregion } From 845c350727192120b871593e832157380eea1388 Mon Sep 17 00:00:00 2001 From: Xavier Foucrier Date: Wed, 4 Dec 2024 14:49:40 +0100 Subject: [PATCH 31/36] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20improve=20inbox=20sy?= =?UTF-8?q?nc=20at=20startup?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/Gmail.cs | 7 ++++--- code/Update.cs | 5 ----- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/code/Gmail.cs b/code/Gmail.cs index fb31084..7d0c756 100644 --- a/code/Gmail.cs +++ b/code/Gmail.cs @@ -123,12 +123,13 @@ public async Task Authentication() { // enable the main timer UI.timer.Enabled = true; - // synchronize the user mailbox, after checking for update depending on the user settings, or by default after the asynchronous authentication + // check for update depending on the user settings if (Settings.Default.UpdateService && Update.IsPeriodSetToStartup()) { await UI.UpdateService.Check(!Settings.Default.UpdateDownload, true); - } else { - await Inbox.Sync(); } + + // synchronize the user mailbox + await Inbox.Sync(); } /// diff --git a/code/Update.cs b/code/Update.cs index 0a6ca3b..3101b99 100644 --- a/code/Update.cs +++ b/code/Update.cs @@ -175,11 +175,6 @@ public async Task Check(bool verbose = true, bool startup = false) { // restore default update button state UI.buttonCheckForUpdate.Enabled = true; - - // synchronize the inbox if the updates has been checked at startup after asynchronous authentication - if (startup) { - await UI.GmailService.Inbox.Sync(); - } } } From 1a8337952c09c255940990d4b18782d7c805ef13 Mon Sep 17 00:00:00 2001 From: Xavier Foucrier Date: Wed, 4 Dec 2024 15:20:29 +0100 Subject: [PATCH 32/36] =?UTF-8?q?=E2=9C=A8=20manage=20major=20updates=20to?= =?UTF-8?q?=20prevent=20breaking=20changes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/Main.cs | 7 ++++++- code/Update.cs | 41 ++++++++++++++++++++++++++++++++++++++--- 2 files changed, 44 insertions(+), 4 deletions(-) diff --git a/code/Main.cs b/code/Main.cs index 1205c72..292c7f7 100644 --- a/code/Main.cs +++ b/code/Main.cs @@ -588,7 +588,12 @@ private async void buttonCheckForUpdate_Click(object sender, EventArgs e) { WindowState = FormWindowState.Minimized; ShowInTaskbar = false; Visible = false; - await UpdateService.Download(); + + if (UpdateService.MajorUpdateAvailable) { + UpdateService.ShowGithubRelease(); + } else { + await UpdateService.Download(); + } } else { await UpdateService.Check(); } diff --git a/code/Update.cs b/code/Update.cs index 3101b99..e9f0ca7 100644 --- a/code/Update.cs +++ b/code/Update.cs @@ -7,6 +7,7 @@ using System.Net; using System.Net.Http; using System.Net.Http.Headers; +using System.Text.RegularExpressions; using System.Threading.Tasks; using System.Windows.Forms; using Newtonsoft.Json.Linq; @@ -153,11 +154,26 @@ public async Task Check(bool verbose = true, bool startup = false) { // update the check for update button text UI.buttonCheckForUpdate.Text = Translation.updateNow; + // check for major version changes + int major = int.Parse(Regex.Match(release, @"v(\d+)").Groups[1].Value); + + if (major > Core.MajorVersion) { + + // store the major update state + MajorUpdateAvailable = true; + + // notify the user about new major release + if (verbose) { + UI.NotificationService.Tip(Translation.updateServiceName, Translation.newMajorVersion.Replace("{version}", ReleaseAvailable), Notification.Type.Info, 1500); + } + } else { + // download the update package automatically or ask the user, depending on the user setting and verbosity if (verbose) { - UI.NotificationService.Tip(Translation.updateServiceName, Translation.newVersion.Replace("{version}", ReleaseAvailable), Notification.Type.Info, 1500); - } else if (Settings.Default.UpdateDownload) { - await Download().ConfigureAwait(false); + UI.NotificationService.Tip(Translation.updateServiceName, Translation.newVersion.Replace("{version}", ReleaseAvailable), Notification.Type.Info, 1500); + } else if (Settings.Default.UpdateDownload) { + await Download().ConfigureAwait(false); + } } } else if (verbose && !startup) { MessageBox.Show(Translation.latestVersion, Translation.updateServiceName, MessageBoxButtons.OK, MessageBoxIcon.Information); @@ -249,6 +265,18 @@ public async Task Download() { } } + /// + /// Show the Github release page in a browser + /// + public void ShowGithubRelease() { + + // open the release link in a browser + Process.Start($"{Settings.Default.GITHUB_REPOSITORY}/releases/tag/{ReleaseAvailable}"); + + // restore default update button state + UI.buttonCheckForUpdate.Enabled = true; + } + #endregion #region #accessors @@ -260,6 +288,13 @@ public bool UpdateAvailable { get; set; } = false; + /// + /// Flag defining if a major update is available + /// + public bool MajorUpdateAvailable { + get; set; + } = false; + /// /// Latest release version available /// From cff00e4888e0f98894db52bb66c79127a4ce9e88 Mon Sep 17 00:00:00 2001 From: Xavier Foucrier Date: Wed, 4 Dec 2024 15:58:26 +0100 Subject: [PATCH 33/36] =?UTF-8?q?=F0=9F=90=9B=20fix=20notification=20inter?= =?UTF-8?q?action=20when=20an=20update=20is=20available?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/Notification.cs | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/code/Notification.cs b/code/Notification.cs index 15e5f1f..a03fa6d 100644 --- a/code/Notification.cs +++ b/code/Notification.cs @@ -78,18 +78,8 @@ public void Tip(string title, string text, Type icon = Type.Info, int duration = /// Define if the interaction is provided by the balloon tip public async Task Interaction(bool balloon = false) { - // by default, always open the gmail inbox in a browser if the interaction is provided by a double click on the systray icon - if (Tag == null) { - - if (!balloon) { - Process.Start($"{GetBaseURL()}/#inbox"); - } - - return; - } - // display the form and focus the update tab - if (balloon && UI.UpdateService.UpdateAvailable) { + if (balloon && UI.UpdateService.UpdateAvailable && (Tag == "update" || Tag == null)) { UI.Visible = true; UI.ShowInTaskbar = true; UI.WindowState = FormWindowState.Normal; @@ -101,6 +91,16 @@ public async Task Interaction(bool balloon = false) { return; } + // by default, always open the gmail inbox in a browser if the interaction is provided by a double click on the systray icon + if (Tag == null) { + + if (!balloon) { + Process.Start($"{GetBaseURL()}/#inbox"); + } + + return; + } + // do nothing if the notification behavior is set to "do nothing" if (balloon && Settings.Default.NotificationBehavior == (uint)Behavior.DoNothing) { return; From a923c324868817099a3e88e17e75e92222436771 Mon Sep 17 00:00:00 2001 From: Xavier Foucrier Date: Wed, 4 Dec 2024 16:12:53 +0100 Subject: [PATCH 34/36] =?UTF-8?q?=E2=9C=8F=EF=B8=8F=20fix=20code=20indenta?= =?UTF-8?q?tion?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/Update.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/code/Update.cs b/code/Update.cs index e9f0ca7..22e217f 100644 --- a/code/Update.cs +++ b/code/Update.cs @@ -166,10 +166,10 @@ public async Task Check(bool verbose = true, bool startup = false) { if (verbose) { UI.NotificationService.Tip(Translation.updateServiceName, Translation.newMajorVersion.Replace("{version}", ReleaseAvailable), Notification.Type.Info, 1500); } - } else { + } else { - // download the update package automatically or ask the user, depending on the user setting and verbosity - if (verbose) { + // download the update package automatically or ask the user, depending on the user setting and verbosity + if (verbose) { UI.NotificationService.Tip(Translation.updateServiceName, Translation.newVersion.Replace("{version}", ReleaseAvailable), Notification.Type.Info, 1500); } else if (Settings.Default.UpdateDownload) { await Download().ConfigureAwait(false); From 7b27b7fa7059e19b90e13df07b4c799e69041378 Mon Sep 17 00:00:00 2001 From: Xavier Foucrier Date: Wed, 4 Dec 2024 16:13:10 +0100 Subject: [PATCH 35/36] =?UTF-8?q?=F0=9F=94=A5=20remove=20useless=20namespa?= =?UTF-8?q?ce?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/Core.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/code/Core.cs b/code/Core.cs index 91fa74c..6822feb 100644 --- a/code/Core.cs +++ b/code/Core.cs @@ -1,7 +1,6 @@ using System; using System.Diagnostics; using System.IO; -using System.Threading.Tasks; using System.Windows.Forms; using notifier.Properties; From 1b2267469e6cfc5ccca44ac78fd675749926f055 Mon Sep 17 00:00:00 2001 From: Xavier Foucrier Date: Wed, 4 Dec 2024 16:51:16 +0100 Subject: [PATCH 36/36] =?UTF-8?q?=F0=9F=94=96=20bump=20version?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- code/Properties/AssemblyInfo.cs | 4 ++-- setup/setup.iss | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 0dd3952..86d9fae 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ Note that this version of the .NET Framework **evolve in time**: the application #### Setup installer The setup installer contains both `32 bits (x86)` and `64 bits (x64)` versions: this is the better way to install Windows application and allow you to **cleanly install/uninstall** the application with ease. -* :package: [Inbox Notifier 3.11.0](https://github.com/xavierfoucrier/inbox-notifier/releases/download/v3.11.0/Inbox.Notifier.3.11.0.exe) +* :package: [Inbox Notifier 3.15.0](https://github.com/xavierfoucrier/inbox-notifier/releases/download/v3.15.0/Inbox.Notifier.3.15.0.exe) > Note that you will need **administrator rights** to properly complete the installation. diff --git a/code/Properties/AssemblyInfo.cs b/code/Properties/AssemblyInfo.cs index d634213..d00db16 100644 --- a/code/Properties/AssemblyInfo.cs +++ b/code/Properties/AssemblyInfo.cs @@ -37,6 +37,6 @@ // Vous pouvez spécifier toutes les valeurs ou indiquer les numéros de build et de révision par défaut // en utilisant '*', comme indiqué ci-dessous : // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("3.11.0.0")] -[assembly: AssemblyFileVersion("3.11.0.0")] +[assembly: AssemblyVersion("3.15.0.0")] +[assembly: AssemblyFileVersion("3.15.0.0")] [assembly: NeutralResourcesLanguageAttribute("fr-FR")] \ No newline at end of file diff --git a/setup/setup.iss b/setup/setup.iss index f8c55c5..6a3b654 100644 --- a/setup/setup.iss +++ b/setup/setup.iss @@ -1,5 +1,5 @@ #define MyAppName "Inbox Notifier" -#define MyAppVersion "3.11.0" +#define MyAppVersion "3.15.0" #define MyAppYear GetDateTimeString('yyyy', '', ''); #define MyAppPublisher "Xavier Foucrier" #define MyAppURL "https://github.com/xavierfoucrier/inbox-notifier"