Added base decoding logic + notification logic.

This commit is contained in:
Patrick Fic
2020-01-17 11:03:11 -08:00
parent 572f409176
commit 3357a8a564
11 changed files with 659 additions and 11 deletions

View File

@@ -0,0 +1,178 @@
<Window x:Class="BodyshopUploader.Utils.Growls.GrowlNotification"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:BodyshopUploader.Utils.Growls"
mc:Ignorable="d"
SizeToContent="WidthAndHeight"
AllowsTransparency="True"
WindowStyle="None"
ShowInTaskbar="False"
Topmost="True"
UseLayoutRounding="True"
Title="BodyshopUploader Notification"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
TextElement.Foreground="{DynamicResource MaterialDesignBody}"
TextElement.FontWeight="Regular"
TextElement.FontSize="13"
TextOptions.TextFormattingMode="Ideal"
TextOptions.TextRenderingMode="Auto"
Background="Transparent"
FontFamily="{DynamicResource MaterialDesignFont}">
<Window.Resources>
<Storyboard x:Key="CollapseStoryboard">
<DoubleAnimation From="100"
To="0"
Storyboard.TargetProperty="Height"
Duration="0:0:0.5" />
</Storyboard>
<DataTemplate x:Key="MessageTemplate"
DataType="Model:Notification">
<Grid x:Name="NotificationWindow"
Tag="{Binding Path=Id}"
MouseLeftButtonDown="NotificationWindow_MouseLeftButtonDown"
Background="Transparent"
SizeChanged="NotificationWindowSizeChanged">
<Border Name="border"
Background="#2a3345"
BorderThickness="0"
CornerRadius="10"
Margin="10">
<Border.Effect>
<DropShadowEffect ShadowDepth="0"
Opacity="0.8"
BlurRadius="10" />
</Border.Effect>
<Grid Height="100"
Width="380"
Margin="6">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Image Grid.RowSpan="2"
Source="../../favicon.ico"
Margin="4"
Width="24"></Image>
<TextBlock Grid.Column="1"
Text="{Binding Path=Title}"
TextOptions.TextRenderingMode="ClearType"
TextOptions.TextFormattingMode="Display"
Foreground="White"
FontFamily="Arial"
FontSize="14"
FontWeight="Bold"
VerticalAlignment="Center"
Margin="2,4,4,2"
TextWrapping="Wrap"
TextTrimming="CharacterEllipsis" />
<!--<Button x:Name="CloseButton" Grid.Column="1" Width="16" Height="16" HorizontalAlignment="Right" Margin="0,0,12,0" />-->
<Button x:Name="CloseButton"
Grid.Column="1"
Style="{StaticResource MaterialDesignFloatingActionMiniAccentButton}"
HorizontalAlignment="Right"
Width="24"
Height="24">
<materialDesign:PackIcon Kind="Close"
Height="16"
Width="16" />
</Button>
<TextBlock Grid.Row="1"
Grid.Column="1"
Text="{Binding Path=Subtitle}"
TextOptions.TextRenderingMode="ClearType"
TextOptions.TextFormattingMode="Display"
Foreground="White"
FontFamily="Arial"
FontSize="14"
FontWeight="Bold"
VerticalAlignment="Center"
Margin="2,4,4,2"
TextWrapping="Wrap"
TextTrimming="CharacterEllipsis" />
<TextBlock Grid.Row="2"
Grid.Column="1"
Text="{Binding Path=Message}"
TextOptions.TextRenderingMode="ClearType"
TextOptions.TextFormattingMode="Display"
Foreground="White"
FontFamily="Arial"
VerticalAlignment="Center"
Margin="2,2,4,4"
TextWrapping="Wrap"
TextTrimming="CharacterEllipsis" />
</Grid>
</Border>
</Grid>
<DataTemplate.Triggers>
<EventTrigger RoutedEvent="Window.Loaded"
SourceName="NotificationWindow">
<BeginStoryboard x:Name="FadeInStoryBoard">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="NotificationWindow"
From="0.01"
To="1"
Storyboard.TargetProperty="Opacity"
Duration="0:0:1" />
<DoubleAnimation Storyboard.TargetName="NotificationWindow"
From="1"
To="0"
Storyboard.TargetProperty="Opacity"
Duration="0:0:2"
BeginTime="0:0:3" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<Trigger Property="IsMouseOver"
Value="True">
<Trigger.EnterActions>
<SeekStoryboard Offset="0:0:1"
BeginStoryboardName="FadeInStoryBoard" />
<PauseStoryboard BeginStoryboardName="FadeInStoryBoard" />
</Trigger.EnterActions>
<Trigger.ExitActions>
<SeekStoryboard Offset="0:0:1"
BeginStoryboardName="FadeInStoryBoard" />
<ResumeStoryboard BeginStoryboardName="FadeInStoryBoard"></ResumeStoryboard>
</Trigger.ExitActions>
</Trigger>
<EventTrigger RoutedEvent="Button.Click"
SourceName="CloseButton">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="NotificationWindow"
From="1"
To="0"
Storyboard.TargetProperty="(Grid.Opacity)"
Duration="0:0:0" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<Trigger SourceName="NotificationWindow"
Property="Opacity"
Value="0">
<Setter TargetName="NotificationWindow"
Property="Visibility"
Value="Hidden"></Setter>
<Trigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource CollapseStoryboard}" />
</Trigger.EnterActions>
</Trigger>
</DataTemplate.Triggers>
</DataTemplate>
</Window.Resources>
<ItemsControl x:Name="NotificationsControl"
FocusVisualStyle="{x:Null}"
ItemsSource="{Binding .}"
ItemTemplate="{StaticResource MessageTemplate}" />
</Window>

View File

@@ -0,0 +1,91 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
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.Shapes;
namespace BodyshopUploader.Utils.Growls
{
public partial class GrowlNotification
{
private const byte MAX_NOTIFICATIONS = 4;
private int count;
public Notifications Notifications = new Notifications();
private readonly Notifications buffer = new Notifications();
public ViewModels.MainViewModel ShellVm;
public GrowlNotification(ViewModels.MainViewModel shellViewModel)
{
InitializeComponent();
ShellVm = shellViewModel;
NotificationsControl.DataContext = Notifications;
var desktopWorkingArea = System.Windows.SystemParameters.WorkArea;
this.Left = desktopWorkingArea.Right - 425;
//this.Top = desktopWorkingArea.Bottom - 425;
this.Top = 50;
}
public void AddNotification(Notification notification)
{
notification.Id = count++;
if (Notifications.Count + 1 > MAX_NOTIFICATIONS)
buffer.Add(notification);
else
Notifications.Add(notification);
//Show window if there're notifications
if (Notifications.Count > 0 && !IsActive)
Show();
}
public void RemoveNotification(Notification notification)
{
if (Notifications.Contains(notification))
Notifications.Remove(notification);
if (buffer.Count > 0)
{
Notifications.Add(buffer[0]);
buffer.RemoveAt(0);
}
//Close window if there's nothing to show
if (Notifications.Count < 1)
Hide();
}
private void NotificationWindowSizeChanged(object sender, SizeChangedEventArgs e)
{
if (e.NewSize.Height != 0.0)
return;
var element = sender as Grid;
RemoveNotification(Notifications.First(
n => n.Id == Int32.Parse(element.Tag.ToString())));
}
private void NotificationWindow_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
Notification n = (Notification)((Grid)sender).DataContext;
BringWindowToFront();
RemoveNotification(n);
}
static void BringWindowToFront()
{
var currentProcess = Process.GetCurrentProcess();
var processes = Process.GetProcessesByName(currentProcess.ProcessName);
var process = processes.FirstOrDefault(p => p.Id == currentProcess.Id);
if (process == null) return;
SetForegroundWindow(process.MainWindowHandle);
}
[DllImport("user32.dll")]
static extern bool SetForegroundWindow(IntPtr hWnd);
}
}

View File

@@ -0,0 +1,102 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BodyshopUploader.Utils.Growls
{
public class Notification : INotifyPropertyChanged
{
private string message;
public string Message
{
get { return message; }
set
{
if (message == value) return;
message = value;
OnPropertyChanged("Message");
}
}
private int id;
public int Id
{
get { return id; }
set
{
if (id == value) return;
id = value;
OnPropertyChanged("Id");
}
}
private int threadid;
public int ThreadId
{
get { return threadid; }
set
{
if (threadid == value) return;
threadid = value;
OnPropertyChanged("ThreadId");
}
}
private string imageUrl;
public string ImageUrl
{
get { return imageUrl; }
set
{
if (imageUrl == value) return;
imageUrl = value;
OnPropertyChanged("ImageUrl");
}
}
private string title;
public string Title
{
get { return title; }
set
{
if (title == value) return;
title = value;
OnPropertyChanged("Title");
}
}
private string subtitle;
public string Subtitle
{
get { return subtitle; }
set
{
if (subtitle == value) return;
subtitle = value;
OnPropertyChanged("Subtitle");
}
}
protected virtual void OnPropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
public event PropertyChangedEventHandler PropertyChanged;
}
public class Notifications : ObservableCollection<Notification> { }
}