Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Notifications UI web view2 #13096

Merged
merged 25 commits into from
Jul 19, 2022
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
1fdee8c
Create the notifications button
filipeotero Jun 23, 2022
bd41dbb
Notification ui popup
filipeotero Jun 23, 2022
e23ca7a
fit webview2 into the popup
filipeotero Jun 28, 2022
a423ff2
pointer tooltip and shadow
filipeotero Jun 29, 2022
1a9105e
ViewExtension project
filipeotero Jun 29, 2022
a5a0d8a
creation of viewextension
filipeotero Jun 30, 2022
f4a8cad
Inserting the notification ui into the NotificationsExtension
filipeotero Jun 30, 2022
b90db12
Load local files
filipeotero Jul 5, 2022
013b4a2
Unit tests
filipeotero Jul 9, 2022
249de12
Notifications Icon
filipeotero Jul 9, 2022
c85c3df
Merge branch 'master' into NotificationsUI-WebView2
filipeotero Jul 9, 2022
5bc90a0
Removing old created notifications center
filipeotero Jul 11, 2022
c6af7fd
Code refactor
filipeotero Jul 11, 2022
5d628de
Reverting dynamo sln
filipeotero Jul 11, 2022
f88183e
Assigning comments
filipeotero Jul 11, 2022
f6d542f
PR comments
filipeotero Jul 12, 2022
2ebf363
Addressing comments
filipeotero Jul 13, 2022
9db5809
updates
QilongTang Jul 13, 2022
f204809
Addressing comments
filipeotero Jul 14, 2022
a89c775
Merge branch 'NotificationsUI-WebView2' of https://github.com/filipeo…
filipeotero Jul 14, 2022
db945bf
inserting npm install notifications package
filipeotero Jul 15, 2022
82f3acb
misspelling fix
filipeotero Jul 18, 2022
91ee8e6
commenting npm build command
filipeotero Jul 18, 2022
bc5588c
undoing npm command comment
filipeotero Jul 19, 2022
6d758ec
Commenting npm command and adding the js bundle file
filipeotero Jul 19, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions src/DynamoCoreWpf/Controls/ShortcutToolbar.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
xmlns:um="clr-namespace:Dynamo.Updates"
xmlns:updateManager="clr-namespace:Dynamo.Updates;assembly=DynamoCore"
xmlns:p="clr-namespace:Dynamo.Wpf.Properties"
xmlns:fa="http://schemas.fontawesome.io/icons/"
mc:Ignorable="d"
Height="Auto"
Width="Auto"
Expand Down Expand Up @@ -139,6 +140,29 @@
<Menu HorizontalAlignment="Right"
Style="{StaticResource MainMenu}"
IsMainMenu="True">
<MenuItem Name="MenuItem">
<MenuItem.Header>
<Button x:Name="notificationsButton"
BorderBrush="Transparent"
Background="Transparent">
<DockPanel>
<fa:FontAwesome Margin="0,0,20,0" DockPanel.Dock="Bottom" Icon="BellOutline" Foreground="{StaticResource Blue400Brush}" FontSize="20px"/>
<Border DockPanel.Dock="Top" Background="{StaticResource Blue400Brush}" CornerRadius="2"
Padding="2" Height="15" Width="15" VerticalAlignment="Center"
HorizontalAlignment="Center">
<!--TODO insert data bind for the notifications -->
<TextBlock
FontFamily="{StaticResource ArtifaktElementRegular}"
Foreground="White"
FontWeight="Bold"
TextAlignment="Center"
FontSize="9">99
QilongTang marked this conversation as resolved.
Show resolved Hide resolved
</TextBlock>
</Border>
</DockPanel>
</Button>
</MenuItem.Header>
</MenuItem>
<MenuItem Name="exportMenu"
Cursor="Hand"
Focusable="False"
Expand Down
1 change: 0 additions & 1 deletion src/DynamoCoreWpf/Controls/ShortcutToolbar.xaml.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
Expand Down
1 change: 1 addition & 0 deletions src/DynamoCoreWpf/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
[assembly: InternalsVisibleTo("LintingViewExtension")]
[assembly: InternalsVisibleTo("GraphMetadataViewExtension")]
[assembly: InternalsVisibleTo("PackageDetailsViewExtension")]
[assembly: InternalsVisibleTo("Notifications")]
[assembly: InternalsVisibleTo("IronPythonTests")]
[assembly: InternalsVisibleTo("DynamoPackagesWPF")]

Expand Down
8 changes: 6 additions & 2 deletions src/DynamoCoreWpf/Utilities/ResourceUtilities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -263,8 +263,12 @@ internal static Stream LoadResourceByUrl(string url)
return textStream;
}


internal static string ConvertToBase64(Stream stream)
/// <summary>
/// This method converts a stream to base64 string
/// </summary>
/// <param name="stream"></param>
/// <returns></returns>
public static string ConvertToBase64(Stream stream)
QilongTang marked this conversation as resolved.
Show resolved Hide resolved
{
byte[] bytes;
using (var memoryStream = new MemoryStream())
Expand Down
2 changes: 2 additions & 0 deletions src/DynamoCoreWpf/Views/Core/DynamoView.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ public partial class DynamoView : Window, IDisposable

private FileTrustWarning fileTrustWarningPopup = null;

internal ShortcutToolbar ShortcutBar { get { return shortcutBar; } }

/// <summary>
/// Constructor
/// </summary>
Expand Down
107 changes: 107 additions & 0 deletions src/Notifications/NotificationCenterController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
using Dynamo.Controls;
using Dynamo.Notifications.View;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;

namespace Dynamo.Notifications
{
public class NotificationCenterController
{
NotificationUI notificationUIPopup;
DynamoView dynamoView;
Button notificationsButton;

private static int notificationPopupHorizontalOffset = -285;
private static int notificationPopupVerticalOffset = 10;

private static string htmlEmbeddedFile = "Dynamo.Notifications.Web.index.html";
private static string fontEmbeddedFile = "Dynamo.Notifications.Web.ArtifaktElement-Regular.woff";
private static string jsEmbeddedFile = "Dynamo.Notifications.Web.index.bundle.js";

public NotificationCenterController(DynamoView dynamoView)
{
var shortcutBar = dynamoView.ShortcutBar;
var notificationsButton = (Button)shortcutBar.FindName("notificationsButton");

notificationUIPopup = new NotificationUI();
notificationUIPopup.IsOpen = false;
notificationUIPopup.PlacementTarget = notificationsButton;
notificationUIPopup.Placement = PlacementMode.Bottom;
notificationUIPopup.HorizontalOffset = notificationPopupHorizontalOffset;
notificationUIPopup.VerticalOffset = notificationPopupVerticalOffset;

this.dynamoView = dynamoView;
this.notificationsButton = notificationsButton;

this.dynamoView.SizeChanged += DynamoView_SizeChanged;
this.dynamoView.LocationChanged += DynamoView_LocationChanged;
this.notificationsButton.Click += NotificationsButton_Click;

notificationUIPopup.webView.EnsureCoreWebView2Async();
notificationUIPopup.webView.CoreWebView2InitializationCompleted += WebView_CoreWebView2InitializationCompleted;
QilongTang marked this conversation as resolved.
Show resolved Hide resolved
}

private void WebView_CoreWebView2InitializationCompleted(object sender, Microsoft.Web.WebView2.Core.CoreWebView2InitializationCompletedEventArgs e)
{
var assembly = Assembly.GetExecutingAssembly();
string htmlString = string.Empty;

using (Stream stream = assembly.GetManifestResourceStream(htmlEmbeddedFile))
using (StreamReader reader = new StreamReader(stream))
{
htmlString = reader.ReadToEnd();
}

using (Stream stream = assembly.GetManifestResourceStream(jsEmbeddedFile))
using (StreamReader reader = new StreamReader(stream))
{
var jsString = reader.ReadToEnd();
htmlString = htmlString.Replace("#mainJs", jsString);
}

using (Stream stream = assembly.GetManifestResourceStream(fontEmbeddedFile))
{
var resourceBase64 = Utilities.ResourceUtilities.ConvertToBase64(stream);
htmlString = htmlString.Replace("#fontStyle", resourceBase64);
}

if(notificationUIPopup.webView.CoreWebView2 != null)
notificationUIPopup.webView.CoreWebView2.NavigateToString(htmlString);
}

internal void Dispose()
{
notificationUIPopup.webView.CoreWebView2InitializationCompleted -= WebView_CoreWebView2InitializationCompleted;
dynamoView.SizeChanged -= DynamoView_SizeChanged;
dynamoView.LocationChanged -= DynamoView_LocationChanged;
notificationsButton.Click -= NotificationsButton_Click;
}

private void DynamoView_LocationChanged(object sender, EventArgs e)
{
notificationUIPopup.Placement = PlacementMode.Bottom;
notificationUIPopup.UpdatePopupLocation();
}

private void DynamoView_SizeChanged(object sender, SizeChangedEventArgs e)
{
notificationUIPopup.Placement = PlacementMode.Bottom;
notificationUIPopup.UpdatePopupLocation();
}

private void NotificationsButton_Click(object sender, RoutedEventArgs e)
{
notificationUIPopup.IsOpen = !notificationUIPopup.IsOpen;
if (notificationUIPopup.IsOpen)
notificationUIPopup.webView.Focus();
}
}
}
19 changes: 19 additions & 0 deletions src/Notifications/Notifications.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,20 @@
<RootNamespace>Dynamo.Notifications</RootNamespace>
<AssemblyName>Notifications</AssemblyName>
</PropertyGroup>
<ItemGroup>
<None Remove="View\NotificationUI.xaml" />
<None Remove="Web\ArtifaktElement-Regular.woff" />
<None Remove="Web\index.bundle.js" />
<None Remove="Web\index.html" />
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is something we need to work on. I would love to avoid hard copy of the existing component.

</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Web\ArtifaktElement-Regular.woff" />
<EmbeddedResource Include="Web\index.bundle.js" />
<EmbeddedResource Include="Web\index.html" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="FontAwesome.WPF" Version="4.7.0.9" />
<PackageReference Include="Microsoft.Web.WebView2" Version="1.0.1264.42" />
<Reference Include="Microsoft.Practices.Prism">
<HintPath>..\..\extern\prism\Microsoft.Practices.Prism.dll</HintPath>
<Private>False</Private>
Expand Down Expand Up @@ -44,6 +56,10 @@
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="View\NotificationUI.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>
<ItemGroup>
<Compile Update="Properties\Resources.Designer.cs">
Expand All @@ -56,6 +72,9 @@
<DesignTime>True</DesignTime>
<DependentUpon>Resources.en-US.resx</DependentUpon>
</Compile>
<Compile Update="View\NotificationUI.xaml.cs">
<DependentUpon>NotificationUI.xaml</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Update="Properties\Resources.resx">
Expand Down
53 changes: 53 additions & 0 deletions src/Notifications/NotificationsUIViewModel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
using System.Windows;
using System.Windows.Media;
using Dynamo.ViewModels;

namespace Dynamo.Notifications
{
class NotificationsUIViewModel : ViewModelBase
{
public PointCollection TooltipPointerPoints { get; set; }

//Direction of the shadow shown in the Popup
public double ShadowTooltipDirection { get; set; } = 90;

//This value will describe the needed space for drawing pointers inside the Popup
public int PopupBordersOffSet { get; set; } = 15;

/// <summary>
/// Popup Width, by default it will have an exaggerated Width to accommodate localized languages
/// TODO it should really be responsive either using grid of auto canvas:
/// https://stackoverflow.com/questions/855334/wpf-how-to-make-canvas-auto-resize
/// </summary>
public double PopupRectangleWidth { get; set; } = 310;
Copy link
Contributor

@reddyashish reddyashish Jul 12, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we calculate this using dynamo window width instead of having a fixed value?


/// <summary>
/// Popup Height, by default it will have a Height of 568
/// </summary>
public double PopupRectangleHeight { get; set; } = 568;

double PointerWidth = 25;
QilongTang marked this conversation as resolved.
Show resolved Hide resolved

public NotificationsUIViewModel()
{
var PointerVerticalOffset = PopupRectangleHeight / 8;

//First X,Y coordinate
double pointX1 = PopupRectangleWidth - PointerWidth;
double pointY1 = PopupBordersOffSet;

////Second X,Y coordinate
double pointX2 = PopupRectangleWidth;
double pointY2 = PopupBordersOffSet;

////Third X,Y coordinate
double pointX3 = PopupRectangleWidth - PointerWidth / 2;
double pointY3 = 0;

//Creating the pointer pointing to the Run section of Dynamo
TooltipPointerPoints = new PointCollection(new[] { new Point(pointX1, pointY1),
new Point(pointX2, pointY2),
new Point(pointX3, pointY3)});
}
}
}
11 changes: 11 additions & 0 deletions src/Notifications/NotificationsViewExtension.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using Dynamo.Controls;
using Dynamo.Logging;
using Dynamo.ViewModels;
using Dynamo.Wpf.Extensions;
Expand All @@ -18,6 +19,7 @@ public class NotificationsViewExtension : IViewExtension, INotifyPropertyChanged
private Action<Logging.NotificationMessage> notificationHandler;
private ObservableCollection<Logging.NotificationMessage> notifications;
private bool disposed;
private NotificationCenterController notificationCenterController;
/// <summary>
/// Notifications data collection. PropertyChanged event is raised to help dealing WPF bind dispose.
/// </summary>
Expand Down Expand Up @@ -65,6 +67,7 @@ public void Dispose()
BindingOperations.ClearAllBindings(notificationsMenuItem.CountLabel);
notificationsMenuItem = null;
disposed = true;
notificationCenterController.Dispose();
}
}

Expand Down Expand Up @@ -98,6 +101,14 @@ public void Loaded(ViewLoadedParams viewStartupParams)
(notificationsMenuItem.MenuItem.Parent as ContentControl).Content = null;
//place the menu into the DynamoMenu
viewStartupParams.dynamoMenu.Items.Add(notificationsMenuItem.MenuItem);

LoadNotificationCenter();
}

private void LoadNotificationCenter()
{
var dynamoView = viewLoadedParams.DynamoWindow as DynamoView;
var notificationCenterController = new NotificationCenterController(dynamoView);
}

internal void AddNotifications()
Expand Down
78 changes: 78 additions & 0 deletions src/Notifications/View/NotificationUI.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
<Popup x:Class="Dynamo.Notifications.View.NotificationUI"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:ui="clr-namespace:Dynamo.UI;assembly=DynamoCoreWpf"
xmlns:controls="clr-namespace:Dynamo.Controls;assembly=DynamoCoreWpf"
xmlns:p="clr-namespace:Dynamo.Wpf.Properties;assembly=DynamoCoreWpf"
xmlns:fa="http://schemas.fontawesome.io/icons/"
xmlns:wv2="clr-namespace:Microsoft.Web.WebView2.Wpf;assembly=Microsoft.Web.WebView2.Wpf"
mc:Ignorable="d"
AllowsTransparency="True"
Opacity="0.5"
Width="340"
Height="598">
QilongTang marked this conversation as resolved.
Show resolved Hide resolved
<Popup.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ui:SharedResourceDictionary Source="{x:Static ui:SharedDictionaryManager.DynamoConvertersDictionaryUri}" />
<ui:SharedResourceDictionary Source="{x:Static ui:SharedDictionaryManager.DynamoModernDictionaryUri}" />
</ResourceDictionary.MergedDictionaries>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
<controls:PointsToPathConverter x:Key="PointsToPathConverter"/>
</ResourceDictionary>
</Popup.Resources>
<Canvas Background="Transparent"
Name="RootLayout" >
<Path x:Name="PopupPathRectangle"
Style="{StaticResource PoupPathRectangleStyle}">
<Path.Data>
<RectangleGeometry x:Name="BackgroundRectangle">
</RectangleGeometry>
</Path.Data>
<!--This effect will show a 4px shadow of 20% of tranparency with a angle of 135 grades-->
<Path.Effect>
<DropShadowEffect Opacity="0.2"
Color="Black"
ShadowDepth="4"
BlurRadius="4"
Direction="135"/>
</Path.Effect>
</Path>

<Path x:Name="PopupPathRectangleShadow"
Style="{StaticResource PoupPathRectangleStyle}">
<Path.Data>
<RectangleGeometry Rect="{Binding ElementName=BackgroundRectangle, Path=Rect}">
</RectangleGeometry>
</Path.Data>
<!--This effect will show a 4px shadow of 20% of tranparency with a angle of 315 grades-->
<Path.Effect>
<DropShadowEffect Opacity="0.2"
Color="Black"
ShadowDepth="4"
BlurRadius="4"
Direction="315"/>
</Path.Effect>
</Path>

<!--This Path will draw on the Canvas the pointer (a triangle)-->
<Path x:Name="TooltipPointer"
Data="{Binding Path=TooltipPointerPoints, Converter={StaticResource PointsToPathConverter}}"
Style="{StaticResource PoupPathPointerStyle}">
<Path.Effect>
<DropShadowEffect Opacity="0.2"
Color="Black"
ShadowDepth="4"
BlurRadius="4"
Direction="{Binding Path=ShadowTooltipDirection}"/>
</Path.Effect>
</Path>

<Grid x:Name="mainPopupGrid" Background="White"
Width="{Binding PopupRectangleWidth}">
<wv2:WebView2 Name="webView" ></wv2:WebView2>
</Grid>
</Canvas>
</Popup>
Loading