Skip to content

Commit

Permalink
Merge pull request #3 from Novack/main
Browse files Browse the repository at this point in the history
Added system tray icon
  • Loading branch information
amilich authored Aug 30, 2023
2 parents 9efa7f8 + 803c9c7 commit 896a909
Show file tree
Hide file tree
Showing 6 changed files with 458 additions and 73 deletions.
92 changes: 20 additions & 72 deletions skiffWindowsApp/Skiff Desktop/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
@@ -1,28 +1,11 @@
using Microsoft.Web.WebView2.Core;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Text.Json;
using System.Text.Json.Serialization;
using static System.Net.Mime.MediaTypeNames;
using ToastNotifications;
using ToastNotifications.Lifetime;
using ToastNotifications.Position;
using ToastNotifications.Messages;
using ToastNotifications.Messages.Core;
using ToastNotifications.Core;
using CustomNotificationsExample.CustomMessage;

Expand All @@ -33,8 +16,16 @@ namespace Skiff_Desktop
/// </summary>
public partial class MainWindow : Window
{
// Counter and action not yet updated. We need messaging from server or webview.
// Use placeholder tray menu items to demo this.
public int UnreadCount { get; private set; }
public Action UnreadCounterChanged;

private string baseURL = "https://app.skiff.com/";
private Notifier _notifier;
private TrayController _trayController;
private MessageProcessor _messageProcessor;


public MainWindow()
{
Expand All @@ -54,9 +45,12 @@ public MainWindow()
cfg.DisplayOptions.Width = 360;
cfg.DisplayOptions.TopMost = true;
});

_trayController = new TrayController(this);
_messageProcessor = new MessageProcessor(this);
}

private void ShowToastNotification(string title, string message)
internal void ShowToastNotification(string title, string message)
{
var options = new MessageOptions { FreezeOnMouseEnter = true };
_notifier.ShowCustomMessage(title, message, options);
Expand All @@ -67,57 +61,7 @@ protected override void OnClosed(EventArgs e)
_notifier.Dispose();
base.OnClosed(e);
}

private void CoreWebView2_WebMessageReceived(object sender, CoreWebView2WebMessageReceivedEventArgs e)
{
try
{
string rawMessage = e.TryGetWebMessageAsString();
// Deserialize the received message
var receivedMessage = JsonSerializer.Deserialize<ReceivedMessage>(rawMessage);
// Check if the type is "newMessageNotifications"
if (receivedMessage.Type == "newMessageNotifications")
{
foreach (var notification in receivedMessage.Data.NotificationData)
{
Debug.WriteLine($"Displaying toast with title: { notification.Title} and body: { notification.Body}");

// show toast
// ToastNotification toast = new ToastNotification()
ShowToastNotification(notification.Title, notification.Body);
}
}
else
{
Debug.WriteLine("Message type is not ‘newMessageNotifications’. Skipping.");
}
}
catch (Exception ex)
{
Debug.WriteLine($"Failed to process message: { ex.Message}");
}
}

public class ReceivedMessage
{
[JsonPropertyName("type")]
public string Type { get; set; }
[JsonPropertyName("data")]
public NotificationDataWrapper Data { get; set; }
}
public class NotificationDataWrapper
{
[JsonPropertyName("notificationData")]
public List<NotificationItem> NotificationData { get; set; }
}
public class NotificationItem
{
[JsonPropertyName("title")]
public string Title { get; set; }
[JsonPropertyName("body")]
public string Body { get; set; }
}


private async Task InitializeBrowser()
{
// When installing the app webview attempts to create a folder with cache folders in root app directory
Expand All @@ -139,7 +83,7 @@ private async Task InitializeBrowser()

// this is needed to allow the webview to communicate with the app
// right now, only for sending notifications
WebView2.CoreWebView2.WebMessageReceived += CoreWebView2_WebMessageReceived;
WebView2.CoreWebView2.WebMessageReceived += _messageProcessor.CoreWebView2_WebMessageReceived;
WebView2.CoreWebView2.Settings.IsWebMessageEnabled = true; // Make sure this is set to true

await WebView2.CoreWebView2.AddScriptToExecuteOnDocumentCreatedAsync("window.IsSkiffWindowsDesktop = true;");
Expand Down Expand Up @@ -184,8 +128,6 @@ private void OpenInDefaultBrowser(string uri)
}
}



private void WebView2_NavigationStarting(object sender, CoreWebView2NavigationStartingEventArgs e)
{
if (!e.Uri.StartsWith(baseURL))
Expand All @@ -196,5 +138,11 @@ private void WebView2_NavigationStarting(object sender, CoreWebView2NavigationSt
OpenInDefaultBrowser(e.Uri);
}
}

internal void UpdateUnreadCount(int newTotal)
{
UnreadCount = newTotal;
UnreadCounterChanged?.Invoke();
}
}
}
103 changes: 103 additions & 0 deletions skiffWindowsApp/Skiff Desktop/MessageProcessor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
using Microsoft.Web.WebView2.Core;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text.Json.Serialization;
using System.Text.Json;

namespace Skiff_Desktop
{
public enum MessageTypes
{
newMessageNotifications,
unreadMailCount,
}

internal class MessageProcessor
{
private MainWindow _mainWindow;


public MessageProcessor(MainWindow mainWindow)
{
_mainWindow = mainWindow;
}

internal void CoreWebView2_WebMessageReceived(object sender, CoreWebView2WebMessageReceivedEventArgs e)
{
try
{
string rawMessage = e.TryGetWebMessageAsString();

JsonSerializerOptions options = new JsonSerializerOptions
{
Converters =
{
new JsonStringEnumConverter(JsonNamingPolicy.CamelCase)
}
};

var receivedMessage = JsonSerializer.Deserialize<ReceivedMessage>(rawMessage, options);

switch (receivedMessage.MsgType)
{
case MessageTypes.newMessageNotifications:
var notificationsPayload = JsonSerializer.Deserialize<NotificationDataWrapper>(receivedMessage.Data.ToString());
foreach (var notification in notificationsPayload.NotificationData)
{
Debug.WriteLine($"Displaying toast with title: {notification.Title} and body: {notification.Body}");
_mainWindow.ShowToastNotification(notification.Title, notification.Body);
}
break;

case MessageTypes.unreadMailCount:
var counterPayload = JsonSerializer.Deserialize<UnreadCountDataWrapper>(receivedMessage.Data.ToString());
Debug.WriteLine($"Updating unread mail count: {counterPayload.UnreadCount}.");
_mainWindow.UpdateUnreadCount(counterPayload.UnreadCount);
break;

default:
Debug.WriteLine("Message type is not ‘newMessageNotifications’. Skipping.");
break;
}
}
catch (Exception ex)
{
Debug.WriteLine($"Failed to process message: {ex.Message}");
}
}


#region Data Wrappers & Helpers

public class ReceivedMessage
{
[JsonPropertyName("type")]
public MessageTypes MsgType { get; set; }
[JsonPropertyName("data")]
public Object Data { get; set; }
}

public class NotificationDataWrapper
{
[JsonPropertyName("notificationData")]
public List<NotificationItem> NotificationData { get; set; }
}

public class NotificationItem
{
[JsonPropertyName("title")]
public string Title { get; set; }
[JsonPropertyName("body")]
public string Body { get; set; }
}

public class UnreadCountDataWrapper
{
[JsonPropertyName("numUnread")]
public int UnreadCount { get; set; }
}

#endregion
}
}
73 changes: 73 additions & 0 deletions skiffWindowsApp/Skiff Desktop/Properties/Resources.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 896a909

Please sign in to comment.