SEBWIN-342: Removed UI dependencies from notifications.

This commit is contained in:
dbuechel 2019-09-04 14:11:19 +02:00
parent 12f44edc0b
commit 363f751f55
25 changed files with 87 additions and 217 deletions

View file

@ -9,16 +9,15 @@
namespace SafeExamBrowser.Client.Contracts
{
/// <summary>
/// Controls the lifetime and functionality of a notification which is part of the <see cref="ITaskbar"/>.
/// Controls the lifetime and functionality of a notification which can be activated via the UI.
/// </summary>
public interface INotificationController
{
// TODO
///// <summary>
///// Registers the taskbar notification.
///// </summary>
//void RegisterNotification(INotificationControl notification);
/// <summary>
/// Executes the notification functionality.
/// </summary>
void Activate();
/// <summary>
/// Instructs the controller to shut down and release all used resources.
/// </summary>

View file

@ -31,13 +31,12 @@ namespace SafeExamBrowser.Client.UnitTests.Notifications
[TestMethod]
public void MustCloseWindowWhenTerminating()
{
var button = new NotificationButtonMock();
var window = new Mock<IWindow>();
var sut = new AboutNotificationController(appConfig.Object, uiFactory.Object);
uiFactory.Setup(u => u.CreateAboutWindow(It.IsAny<AppConfig>())).Returns(window.Object);
sut.RegisterNotification(button);
button.Click();
sut.Activate();
sut.Terminate();
window.Verify(w => w.Close());
@ -46,34 +45,22 @@ namespace SafeExamBrowser.Client.UnitTests.Notifications
[TestMethod]
public void MustOpenOnlyOneWindow()
{
var button = new NotificationButtonMock();
var window = new Mock<IWindow>();
var sut = new AboutNotificationController(appConfig.Object, uiFactory.Object);
uiFactory.Setup(u => u.CreateAboutWindow(It.IsAny<AppConfig>())).Returns(window.Object);
sut.RegisterNotification(button);
button.Click();
button.Click();
button.Click();
button.Click();
button.Click();
sut.Activate();
sut.Activate();
sut.Activate();
sut.Activate();
sut.Activate();
uiFactory.Verify(u => u.CreateAboutWindow(It.IsAny<AppConfig>()), Times.Once);
window.Verify(u => u.Show(), Times.Once);
window.Verify(u => u.BringToForeground(), Times.Exactly(4));
}
[TestMethod]
public void MustSubscribeToClickEvent()
{
var button = new NotificationButtonMock();
var sut = new AboutNotificationController(appConfig.Object, uiFactory.Object);
sut.RegisterNotification(button);
Assert.IsTrue(button.HasSubscribed);
}
[TestMethod]
public void MustNotFailToTerminateIfNotStarted()
{

View file

@ -31,13 +31,12 @@ namespace SafeExamBrowser.Client.UnitTests.Notifications
[TestMethod]
public void MustCloseWindowWhenTerminating()
{
var button = new NotificationButtonMock();
var window = new Mock<IWindow>();
var sut = new LogNotificationController(logger.Object, uiFactory.Object);
uiFactory.Setup(u => u.CreateLogWindow(It.IsAny<ILogger>())).Returns(window.Object);
sut.RegisterNotification(button);
button.Click();
sut.Activate();
sut.Terminate();
window.Verify(w => w.Close());
@ -46,34 +45,22 @@ namespace SafeExamBrowser.Client.UnitTests.Notifications
[TestMethod]
public void MustOpenOnlyOneWindow()
{
var button = new NotificationButtonMock();
var window = new Mock<IWindow>();
var sut = new LogNotificationController(logger.Object, uiFactory.Object);
uiFactory.Setup(u => u.CreateLogWindow(It.IsAny<ILogger>())).Returns(window.Object);
sut.RegisterNotification(button);
button.Click();
button.Click();
button.Click();
button.Click();
button.Click();
sut.Activate();
sut.Activate();
sut.Activate();
sut.Activate();
sut.Activate();
uiFactory.Verify(u => u.CreateLogWindow(It.IsAny<ILogger>()), Times.Once);
window.Verify(u => u.Show(), Times.Once);
window.Verify(u => u.BringToForeground(), Times.Exactly(4));
}
[TestMethod]
public void MustSubscribeToClickEvent()
{
var button = new NotificationButtonMock();
var sut = new LogNotificationController(logger.Object, uiFactory.Object);
sut.RegisterNotification(button);
Assert.IsTrue(button.HasSubscribed);
}
[TestMethod]
public void MustNotFailToTerminateIfNotStarted()
{

View file

@ -1,40 +0,0 @@
/*
* Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET)
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
using SafeExamBrowser.UserInterface.Contracts.Shell;
using SafeExamBrowser.UserInterface.Contracts.Shell.Events;
namespace SafeExamBrowser.Client.UnitTests.Notifications
{
class NotificationButtonMock : INotificationControl
{
private NotificationControlClickedEventHandler clicked;
public bool HasSubscribed;
public bool HasUnsubscribed;
public event NotificationControlClickedEventHandler Clicked
{
add
{
clicked += value;
HasSubscribed = true;
}
remove
{
clicked -= value;
HasUnsubscribed = true;
}
}
public void Click()
{
clicked?.Invoke();
}
}
}

View file

@ -71,17 +71,19 @@ namespace SafeExamBrowser.Client.UnitTests.Operations
uiFactory = new Mock<IUserInterfaceFactory>();
wirelessAdapter = new Mock<IWirelessAdapter>();
uiFactory.Setup(u => u.CreateNotificationControl(It.IsAny<INotificationInfo>(), It.IsAny<Location>())).Returns(new Mock<INotificationControl>().Object);
uiFactory
.Setup(u => u.CreateNotificationControl(It.IsAny<INotificationController>(), It.IsAny<INotificationInfo>(), It.IsAny<Location>()))
.Returns(new Mock<INotificationControl>().Object);
sut = new ShellOperation(
actionCenter.Object,
activators,
actionCenterSettings,
audio.Object,
logger.Object,
aboutInfo.Object,
aboutController.Object,
keyboard.Object,
logger.Object,
logInfo.Object,
logController.Object,
powerSupply.Object,
@ -175,7 +177,9 @@ namespace SafeExamBrowser.Client.UnitTests.Operations
taskbarSettings.EnableTaskbar = true;
taskbarSettings.ShowApplicationLog = false;
uiFactory.Setup(f => f.CreateNotificationControl(It.Is<INotificationInfo>(i => i == logInfo.Object), It.IsAny<Location>())).Returns(logControl.Object);
uiFactory
.Setup(f => f.CreateNotificationControl(It.IsAny<INotificationController>(), It.Is<INotificationInfo>(i => i == logInfo.Object), It.IsAny<Location>()))
.Returns(logControl.Object);
sut.Perform();

View file

@ -95,7 +95,6 @@
<Compile Include="Communication\ClientHostTests.cs" />
<Compile Include="Notifications\AboutNotificationControllerTests.cs" />
<Compile Include="Notifications\LogNotificationControllerTests.cs" />
<Compile Include="Notifications\NotificationButtonMock.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ClientControllerTests.cs" />
</ItemGroup>

View file

@ -275,10 +275,10 @@ namespace SafeExamBrowser.Client
activators,
configuration.Settings.ActionCenter,
audio,
logger,
aboutInfo,
aboutController,
keyboard,
logger,
logInfo,
logController,
powerSupply,

View file

@ -9,14 +9,12 @@
using SafeExamBrowser.Client.Contracts;
using SafeExamBrowser.Configuration.Contracts;
using SafeExamBrowser.UserInterface.Contracts;
using SafeExamBrowser.UserInterface.Contracts.Shell;
using SafeExamBrowser.UserInterface.Contracts.Windows;
namespace SafeExamBrowser.Client.Notifications
{
internal class AboutNotificationController : INotificationController
{
private INotificationControl notification;
private AppConfig appConfig;
private IUserInterfaceFactory uiFactory;
private IWindow window;
@ -27,25 +25,13 @@ namespace SafeExamBrowser.Client.Notifications
this.uiFactory = uiFactory;
}
public void RegisterNotification(INotificationControl notification)
public void Activate()
{
this.notification = notification;
notification.Clicked += Notification_Clicked;
}
public void Terminate()
{
window?.Close();
}
private void Notification_Clicked()
{
if (window == null)
if (window == default(IWindow))
{
window = uiFactory.CreateAboutWindow(appConfig);
window.Closing += () => window = null;
window.Closing += () => window = default(IWindow);
window.Show();
}
else
@ -53,5 +39,10 @@ namespace SafeExamBrowser.Client.Notifications
window.BringToForeground();
}
}
public void Terminate()
{
window?.Close();
}
}
}

View file

@ -9,14 +9,12 @@
using SafeExamBrowser.Client.Contracts;
using SafeExamBrowser.Logging.Contracts;
using SafeExamBrowser.UserInterface.Contracts;
using SafeExamBrowser.UserInterface.Contracts.Shell;
using SafeExamBrowser.UserInterface.Contracts.Windows;
namespace SafeExamBrowser.Client.Notifications
{
internal class LogNotificationController : INotificationController
{
private INotificationControl notification;
private ILogger logger;
private IUserInterfaceFactory uiFactory;
private IWindow window;
@ -27,21 +25,9 @@ namespace SafeExamBrowser.Client.Notifications
this.uiFactory = uiFactory;
}
public void RegisterNotification(INotificationControl notification)
public void Activate()
{
this.notification = notification;
notification.Clicked += Notification_Clicked;
}
public void Terminate()
{
window?.Close();
}
private void Notification_Clicked()
{
if (window == null)
if (window == default(IWindow))
{
window = uiFactory.CreateLogWindow(logger);
@ -53,5 +39,10 @@ namespace SafeExamBrowser.Client.Notifications
window.BringToForeground();
}
}
public void Terminate()
{
window?.Close();
}
}
}

View file

@ -30,10 +30,10 @@ namespace SafeExamBrowser.Client.Operations
private IEnumerable<IActionCenterActivator> activators;
private ActionCenterSettings actionCenterSettings;
private IAudio audio;
private ILogger logger;
private INotificationInfo aboutInfo;
private INotificationController aboutController;
private IKeyboard keyboard;
private ILogger logger;
private INotificationInfo logInfo;
private INotificationController logController;
private IPowerSupply powerSupply;
@ -53,10 +53,10 @@ namespace SafeExamBrowser.Client.Operations
IEnumerable<IActionCenterActivator> activators,
ActionCenterSettings actionCenterSettings,
IAudio audio,
ILogger logger,
INotificationInfo aboutInfo,
INotificationController aboutController,
IKeyboard keyboard,
ILogger logger,
INotificationInfo logInfo,
INotificationController logController,
IPowerSupply powerSupply,
@ -181,10 +181,7 @@ namespace SafeExamBrowser.Client.Operations
{
if (actionCenterSettings.ShowApplicationInfo)
{
var notification = uiFactory.CreateNotificationControl(aboutInfo, Location.ActionCenter);
// TODO aboutController.RegisterNotification(notification);
actionCenter.AddNotificationControl(notification);
actionCenter.AddNotificationControl(uiFactory.CreateNotificationControl(aboutController, aboutInfo, Location.ActionCenter));
}
}
@ -192,10 +189,7 @@ namespace SafeExamBrowser.Client.Operations
{
if (taskbarSettings.ShowApplicationInfo)
{
var notification = uiFactory.CreateNotificationControl(aboutInfo, Location.Taskbar);
// TODO aboutController.RegisterNotification(notification);
taskbar.AddNotificationControl(notification);
taskbar.AddNotificationControl(uiFactory.CreateNotificationControl(aboutController, aboutInfo, Location.Taskbar));
}
}
@ -229,10 +223,7 @@ namespace SafeExamBrowser.Client.Operations
{
if (actionCenterSettings.ShowApplicationLog)
{
var notification = uiFactory.CreateNotificationControl(logInfo, Location.ActionCenter);
// TODO logController.RegisterNotification(notification);
actionCenter.AddNotificationControl(notification);
actionCenter.AddNotificationControl(uiFactory.CreateNotificationControl(logController, logInfo, Location.ActionCenter));
}
}
@ -240,10 +231,7 @@ namespace SafeExamBrowser.Client.Operations
{
if (taskbarSettings.ShowApplicationLog)
{
var notification = uiFactory.CreateNotificationControl(logInfo, Location.Taskbar);
// TODO logController.RegisterNotification(notification);
taskbar.AddNotificationControl(notification);
taskbar.AddNotificationControl(uiFactory.CreateNotificationControl(logController, logInfo, Location.Taskbar));
}
}

View file

@ -58,9 +58,9 @@ namespace SafeExamBrowser.UserInterface.Contracts
IWindow CreateLogWindow(ILogger logger);
/// <summary>
/// Creates a notification control for the specified location, initialized with the given notification information.
/// Creates a notification control for the given notification, initialized for the specified location.
/// </summary>
INotificationControl CreateNotificationControl(INotificationInfo info, Location location);
INotificationControl CreateNotificationControl(INotificationController controller, INotificationInfo info, Location location);
/// <summary>
/// Creates a password dialog with the given message and title.

View file

@ -67,9 +67,7 @@
<Compile Include="MessageBox\MessageBoxResult.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Shell\Events\ActivatorEventHandler.cs" />
<Compile Include="Shell\Events\NotificationControlClickedEventHandler.cs" />
<Compile Include="Shell\Events\QuitButtonClickedEventHandler.cs" />
<Compile Include="Shell\Events\WirelessNetworkSelectedEventHandler.cs" />
<Compile Include="Shell\IActionCenter.cs" />
<Compile Include="Shell\IActionCenterActivator.cs" />
<Compile Include="Shell\IApplicationControl.cs" />

View file

@ -1,15 +0,0 @@
/*
* Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET)
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
namespace SafeExamBrowser.UserInterface.Contracts.Shell.Events
{
/// <summary>
/// Indicates that the user clicked on a <see cref="INotificationControl"/> in the shell.
/// </summary>
public delegate void NotificationControlClickedEventHandler();
}

View file

@ -1,17 +0,0 @@
/*
* Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET)
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
using System;
namespace SafeExamBrowser.UserInterface.Contracts.Shell.Events
{
/// <summary>
/// Indicates that a particular wireless network has been selected by the user.
/// </summary>
public delegate void WirelessNetworkSelectedEventHandler(Guid id);
}

View file

@ -6,8 +6,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
using SafeExamBrowser.UserInterface.Contracts.Shell.Events;
namespace SafeExamBrowser.UserInterface.Contracts.Shell
{
/// <summary>
@ -15,9 +13,5 @@ namespace SafeExamBrowser.UserInterface.Contracts.Shell
/// </summary>
public interface INotificationControl
{
/// <summary>
/// Event fired when the user clicked on the notification control.
/// </summary>
event NotificationControlClickedEventHandler Clicked;
}
}

View file

@ -14,7 +14,7 @@
</ResourceDictionary>
</UserControl.Resources>
<Grid Background="{StaticResource ActionCenterDarkBrush}" Height="64" Margin="2">
<Button x:Name="IconButton" Click="Icon_Click" Padding="2" Template="{StaticResource ActionCenterButton}">
<Button x:Name="IconButton" Click="IconButton_Click" Padding="2" Template="{StaticResource ActionCenterButton}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="2*" />

View file

@ -10,24 +10,25 @@ using System.Windows;
using System.Windows.Controls;
using SafeExamBrowser.Client.Contracts;
using SafeExamBrowser.UserInterface.Contracts.Shell;
using SafeExamBrowser.UserInterface.Contracts.Shell.Events;
using SafeExamBrowser.UserInterface.Shared.Utilities;
namespace SafeExamBrowser.UserInterface.Desktop.Controls
{
public partial class ActionCenterNotificationButton : UserControl, INotificationControl
{
public event NotificationControlClickedEventHandler Clicked;
private INotificationController controller;
public ActionCenterNotificationButton(INotificationInfo info)
public ActionCenterNotificationButton(INotificationController controller, INotificationInfo info)
{
this.controller = controller;
InitializeComponent();
InitializeNotificationIcon(info);
}
private void Icon_Click(object sender, RoutedEventArgs e)
private void IconButton_Click(object sender, RoutedEventArgs e)
{
Clicked?.Invoke();
controller.Activate();
}
private void InitializeNotificationIcon(INotificationInfo info)

View file

@ -14,6 +14,6 @@
</ResourceDictionary>
</UserControl.Resources>
<Grid>
<Button x:Name="IconButton" Background="{StaticResource BackgroundBrush}" Click="Icon_Click" Padding="7.5" Template="{StaticResource TaskbarButton}" Width="40" />
<Button x:Name="IconButton" Background="{StaticResource BackgroundBrush}" Click="IconButton_Click" Padding="7.5" Template="{StaticResource TaskbarButton}" Width="40" />
</Grid>
</UserControl>

View file

@ -10,24 +10,25 @@ using System.Windows;
using System.Windows.Controls;
using SafeExamBrowser.Client.Contracts;
using SafeExamBrowser.UserInterface.Contracts.Shell;
using SafeExamBrowser.UserInterface.Contracts.Shell.Events;
using SafeExamBrowser.UserInterface.Shared.Utilities;
namespace SafeExamBrowser.UserInterface.Desktop.Controls
{
public partial class TaskbarNotificationButton : UserControl, INotificationControl
{
public event NotificationControlClickedEventHandler Clicked;
private INotificationController controller;
public TaskbarNotificationButton(INotificationInfo info)
public TaskbarNotificationButton(INotificationController controller, INotificationInfo info)
{
this.controller = controller;
InitializeComponent();
InitializeNotificationIcon(info);
}
private void Icon_Click(object sender, RoutedEventArgs e)
private void IconButton_Click(object sender, RoutedEventArgs e)
{
Clicked?.Invoke();
controller.Activate();
}
private void InitializeNotificationIcon(INotificationInfo info)

View file

@ -109,15 +109,15 @@ namespace SafeExamBrowser.UserInterface.Desktop
return logWindow;
}
public INotificationControl CreateNotificationControl(INotificationInfo info, Location location)
public INotificationControl CreateNotificationControl(INotificationController controller, INotificationInfo info, Location location)
{
if (location == Location.ActionCenter)
{
return new ActionCenterNotificationButton(info);
return new ActionCenterNotificationButton(controller, info);
}
else
{
return new TaskbarNotificationButton(info);
return new TaskbarNotificationButton(controller, info);
}
}

View file

@ -14,7 +14,7 @@
</ResourceDictionary>
</UserControl.Resources>
<Grid Background="{StaticResource ActionCenterDarkBrush}" Height="82" Margin="2">
<Button x:Name="IconButton" Click="Icon_Click" Padding="2" Template="{StaticResource ActionCenterButton}">
<Button x:Name="IconButton" Click="IconButton_Click" Padding="2" Template="{StaticResource ActionCenterButton}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="2*" />

View file

@ -10,24 +10,25 @@ using System.Windows;
using System.Windows.Controls;
using SafeExamBrowser.Client.Contracts;
using SafeExamBrowser.UserInterface.Contracts.Shell;
using SafeExamBrowser.UserInterface.Contracts.Shell.Events;
using SafeExamBrowser.UserInterface.Shared.Utilities;
namespace SafeExamBrowser.UserInterface.Mobile.Controls
{
public partial class ActionCenterNotificationButton : UserControl, INotificationControl
{
public event NotificationControlClickedEventHandler Clicked;
private INotificationController controller;
public ActionCenterNotificationButton(INotificationInfo info)
public ActionCenterNotificationButton(INotificationController controller, INotificationInfo info)
{
this.controller = controller;
InitializeComponent();
InitializeNotificationIcon(info);
}
private void Icon_Click(object sender, RoutedEventArgs e)
private void IconButton_Click(object sender, RoutedEventArgs e)
{
Clicked?.Invoke();
controller.Activate();
}
private void InitializeNotificationIcon(INotificationInfo info)

View file

@ -14,6 +14,6 @@
</ResourceDictionary>
</UserControl.Resources>
<Grid>
<Button x:Name="IconButton" Background="{StaticResource BackgroundBrush}" Click="Icon_Click" Padding="7.5" Template="{StaticResource TaskbarButton}" Width="60" />
<Button x:Name="IconButton" Background="{StaticResource BackgroundBrush}" Click="IconButton_Click" Padding="7.5" Template="{StaticResource TaskbarButton}" Width="60" />
</Grid>
</UserControl>

View file

@ -10,24 +10,25 @@ using System.Windows;
using System.Windows.Controls;
using SafeExamBrowser.Client.Contracts;
using SafeExamBrowser.UserInterface.Contracts.Shell;
using SafeExamBrowser.UserInterface.Contracts.Shell.Events;
using SafeExamBrowser.UserInterface.Shared.Utilities;
namespace SafeExamBrowser.UserInterface.Mobile.Controls
{
public partial class TaskbarNotificationButton : UserControl, INotificationControl
{
public event NotificationControlClickedEventHandler Clicked;
private INotificationController controller;
public TaskbarNotificationButton(INotificationInfo info)
public TaskbarNotificationButton(INotificationController controller, INotificationInfo info)
{
this.controller = controller;
InitializeComponent();
InitializeNotificationIcon(info);
}
private void Icon_Click(object sender, RoutedEventArgs e)
private void IconButton_Click(object sender, RoutedEventArgs e)
{
Clicked?.Invoke();
controller.Activate();
}
private void InitializeNotificationIcon(INotificationInfo info)

View file

@ -109,15 +109,15 @@ namespace SafeExamBrowser.UserInterface.Mobile
return logWindow;
}
public INotificationControl CreateNotificationControl(INotificationInfo info, Location location)
public INotificationControl CreateNotificationControl(INotificationController controller, INotificationInfo info, Location location)
{
if (location == Location.ActionCenter)
{
return new ActionCenterNotificationButton(info);
return new ActionCenterNotificationButton(controller, info);
}
else
{
return new TaskbarNotificationButton(info);
return new TaskbarNotificationButton(controller, info);
}
}