SEBWIN-405: Implemented mobile versions for exam selection and server failure dialog.

This commit is contained in:
Damian Büchel 2020-07-31 22:17:10 +02:00
parent 4af0cc0d48
commit 6997d3a5f5
7 changed files with 352 additions and 8 deletions

View file

@ -54,8 +54,6 @@ namespace SafeExamBrowser.Client.Operations
Context.AppConfig.ServerExamId,
Context.AppConfig.ServerOauth2Token,
Context.Settings.Server);
// TODO: Add action center and taskbar notifications
}
return result;
@ -70,8 +68,6 @@ namespace SafeExamBrowser.Client.Operations
logger.Info("Finalizing server...");
StatusChanged?.Invoke(TextKey.OperationStatus_FinalizeServer);
// TODO: Stop action center and taskbar notifications
server.StopConnectivity();
}

View file

@ -149,6 +149,9 @@
<Compile Include="Controls\Taskview\WindowControl.xaml.cs">
<DependentUpon>WindowControl.xaml</DependentUpon>
</Compile>
<Compile Include="Windows\ExamSelectionDialog.xaml.cs">
<DependentUpon>ExamSelectionDialog.xaml</DependentUpon>
</Compile>
<Compile Include="Windows\FileSystemDialog.xaml.cs">
<DependentUpon>FileSystemDialog.xaml</DependentUpon>
</Compile>
@ -172,6 +175,9 @@
<Compile Include="Windows\RuntimeWindow.xaml.cs">
<DependentUpon>RuntimeWindow.xaml</DependentUpon>
</Compile>
<Compile Include="Windows\ServerFailureDialog.xaml.cs">
<DependentUpon>ServerFailureDialog.xaml</DependentUpon>
</Compile>
<Compile Include="Windows\SplashScreen.xaml.cs">
<DependentUpon>SplashScreen.xaml</DependentUpon>
</Compile>
@ -374,6 +380,10 @@
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Windows\ExamSelectionDialog.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Windows\FileSystemDialog.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
@ -474,6 +484,10 @@
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Windows\ServerFailureDialog.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Windows\SplashScreen.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>

View file

@ -84,8 +84,7 @@ namespace SafeExamBrowser.UserInterface.Mobile
public IExamSelectionDialog CreateExamSelectionDialog(IEnumerable<Exam> exams)
{
// TODO
throw new System.NotImplementedException();
return Application.Current.Dispatcher.Invoke(() => new ExamSelectionDialog(exams, text));
}
public ISystemControl CreateKeyboardLayoutControl(IKeyboard keyboard, Location location)
@ -170,8 +169,7 @@ namespace SafeExamBrowser.UserInterface.Mobile
public IServerFailureDialog CreateServerFailureDialog(string info, bool showFallback)
{
// TODO
throw new System.NotImplementedException();
return Application.Current.Dispatcher.Invoke(() => new ServerFailureDialog(info, showFallback, text));
}
public ISplashScreen CreateSplashScreen(AppConfig appConfig = null)

View file

@ -0,0 +1,61 @@
<Window x:Class="SafeExamBrowser.UserInterface.Mobile.Windows.ExamSelectionDialog"
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:fa="http://schemas.fontawesome.io/icons/"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:SafeExamBrowser.UserInterface.Mobile.Windows"
mc:Ignorable="d" Background="Transparent" Height="750" Width="1000" FontSize="16" ResizeMode="NoResize" Topmost="True" AllowsTransparency="True" WindowStyle="None">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="../Templates/Colors.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Grid Background="#66000000">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid Grid.Row="0" />
<Grid Grid.Row="1" Background="White">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<fa:ImageAwesome Grid.Column="0" Foreground="LightGray" Icon="PencilSquareOutline" Margin="50" Width="75" />
<Grid Grid.Column="1" Margin="0,0,50,50">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" x:Name="Message" Margin="0,25" TextWrapping="WrapWithOverflow" VerticalAlignment="Bottom" />
<ListBox Grid.Row="1" x:Name="ExamList" Cursor="Hand">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<TextBlock FontWeight="Bold" Text="{Binding Name}" />
<StackPanel Orientation="Horizontal">
<TextBlock Margin="0,0,5,0" Text="{Binding Id}" />
<TextBlock Margin="0,0,5,0" Text="-" />
<TextBlock FontStyle="Italic" Text="{Binding LmsName}" />
</StackPanel>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Grid>
</Grid>
<Grid Grid.Row="2" Background="{StaticResource BackgroundBrush}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<WrapPanel Orientation="Horizontal" Margin="50,25" HorizontalAlignment="Right" VerticalAlignment="Center">
<Button x:Name="SelectButton" Cursor="Hand" Margin="10,0" Padding="10,5" MinWidth="75" IsEnabled="False" />
<Button x:Name="CancelButton" Cursor="Hand" Padding="10,5" MinWidth="75" />
</WrapPanel>
</Grid>
</Grid>
</Window>

View file

@ -0,0 +1,111 @@
/*
* Copyright (c) 2020 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.Collections.Generic;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using SafeExamBrowser.I18n.Contracts;
using SafeExamBrowser.Server.Contracts.Data;
using SafeExamBrowser.UserInterface.Contracts.Windows;
using SafeExamBrowser.UserInterface.Contracts.Windows.Data;
namespace SafeExamBrowser.UserInterface.Mobile.Windows
{
public partial class ExamSelectionDialog : Window, IExamSelectionDialog
{
private readonly IText text;
public ExamSelectionDialog(IEnumerable<Exam> exams, IText text)
{
this.text = text;
InitializeComponent();
InitializeExamSelectionDialog(exams);
}
public ExamSelectionDialogResult Show(IWindow parent = null)
{
return Dispatcher.Invoke(() =>
{
var result = new ExamSelectionDialogResult { Success = false };
if (parent is Window)
{
Owner = parent as Window;
WindowStartupLocation = WindowStartupLocation.CenterOwner;
}
InitializeBounds();
if (ShowDialog() is true)
{
result.SelectedExam = ExamList.SelectedItem as Exam;
result.Success = true;
}
return result;
});
}
private void InitializeBounds()
{
Left = 0;
Top = 0;
Height = SystemParameters.PrimaryScreenHeight;
Width = SystemParameters.PrimaryScreenWidth;
}
private void InitializeExamSelectionDialog(IEnumerable<Exam> exams)
{
InitializeBounds();
Message.Text = text.Get(TextKey.ExamSelectionDialog_Message);
Title = text.Get(TextKey.ExamSelectionDialog_Title);
WindowStartupLocation = WindowStartupLocation.CenterScreen;
CancelButton.Content = text.Get(TextKey.ExamSelectionDialog_Cancel);
CancelButton.Click += CancelButton_Click;
SelectButton.Content = text.Get(TextKey.ExamSelectionDialog_Select);
SelectButton.Click += ConfirmButton_Click;
ExamList.ItemsSource = exams;
ExamList.SelectionChanged += ExamList_SelectionChanged;
Loaded += (o, args) => Activate();
SystemParameters.StaticPropertyChanged += SystemParameters_StaticPropertyChanged;
}
private void CancelButton_Click(object sender, RoutedEventArgs e)
{
DialogResult = false;
Close();
}
private void ConfirmButton_Click(object sender, RoutedEventArgs e)
{
DialogResult = true;
Close();
}
private void ExamList_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
SelectButton.IsEnabled = ExamList.SelectedItem != null;
}
private void SystemParameters_StaticPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(SystemParameters.WorkArea))
{
Dispatcher.InvokeAsync(InitializeBounds);
}
}
}
}

View file

@ -0,0 +1,45 @@
<Window x:Class="SafeExamBrowser.UserInterface.Mobile.Windows.ServerFailureDialog"
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:fa="http://schemas.fontawesome.io/icons/"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:SafeExamBrowser.UserInterface.Mobile.Windows"
mc:Ignorable="d" Background="Transparent" Height="750" Width="1000" FontSize="16" ResizeMode="NoResize" Topmost="True" AllowsTransparency="True" WindowStyle="None">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="../Templates/Colors.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Grid Background="#66000000">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid Grid.Row="0" />
<Grid Grid.Row="1" Background="White">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<fa:ImageAwesome Grid.Column="0" Foreground="LightGray" Icon="Warning" Margin="50" Width="75" />
<WrapPanel Grid.Column="1" Margin="0,0,50,0" Orientation="Vertical" VerticalAlignment="Center">
<TextBlock x:Name="Message" TextWrapping="WrapWithOverflow" />
<TextBlock x:Name="Info" FontFamily="Courier New" Margin="0,10,0,0" TextWrapping="WrapWithOverflow" />
</WrapPanel>
</Grid>
</Grid>
<Grid Grid.Row="2" Background="{StaticResource BackgroundBrush}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<WrapPanel Orientation="Horizontal" Margin="50,25" HorizontalAlignment="Right" VerticalAlignment="Center">
<Button x:Name="RetryButton" Cursor="Hand" Margin="10,0" Padding="10,5" MinWidth="75" />
<Button x:Name="FallbackButton" Cursor="Hand" Margin="0,0,10,0" Padding="10,5" MinWidth="75" />
<Button x:Name="AbortButton" Cursor="Hand" Padding="10,5" MinWidth="75" />
</WrapPanel>
</Grid>
</Grid>
</Window>

View file

@ -0,0 +1,119 @@
/*
* Copyright (c) 2020 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.ComponentModel;
using System.Windows;
using SafeExamBrowser.I18n.Contracts;
using SafeExamBrowser.UserInterface.Contracts.Windows;
using SafeExamBrowser.UserInterface.Contracts.Windows.Data;
namespace SafeExamBrowser.UserInterface.Mobile.Windows
{
public partial class ServerFailureDialog : Window, IServerFailureDialog
{
private readonly IText text;
public ServerFailureDialog(string info, bool showFallback, IText text)
{
this.text = text;
InitializeComponent();
InitializeDialog(info, showFallback);
}
public ServerFailureDialogResult Show(IWindow parent = null)
{
return Dispatcher.Invoke(() =>
{
var result = new ServerFailureDialogResult { Success = false };
if (parent is Window)
{
Owner = parent as Window;
WindowStartupLocation = WindowStartupLocation.CenterOwner;
}
InitializeBounds();
if (ShowDialog() is true)
{
result.Abort = Tag as string == nameof(AbortButton);
result.Fallback = Tag as string == nameof(FallbackButton);
result.Retry = Tag as string == nameof(RetryButton);
result.Success = true;
}
else
{
result.Abort = true;
}
return result;
});
}
private void InitializeBounds()
{
Left = 0;
Top = 0;
Height = SystemParameters.PrimaryScreenHeight;
Width = SystemParameters.PrimaryScreenWidth;
}
private void InitializeDialog(string info, bool showFallback)
{
InitializeBounds();
Info.Text = info;
Message.Text = text.Get(TextKey.ServerFailureDialog_Message);
Title = text.Get(TextKey.ServerFailureDialog_Title);
AbortButton.Click += AbortButton_Click;
AbortButton.Content = text.Get(TextKey.ServerFailureDialog_Abort);
FallbackButton.Click += FallbackButton_Click;
FallbackButton.Content = text.Get(TextKey.ServerFailureDialog_Fallback);
FallbackButton.Visibility = showFallback ? Visibility.Visible : Visibility.Collapsed;
Loaded += (o, args) => Activate();
RetryButton.Click += RetryButton_Click;
RetryButton.Content = text.Get(TextKey.ServerFailureDialog_Retry);
SystemParameters.StaticPropertyChanged += SystemParameters_StaticPropertyChanged;
}
private void AbortButton_Click(object sender, RoutedEventArgs e)
{
DialogResult = true;
Tag = nameof(AbortButton);
Close();
}
private void FallbackButton_Click(object sender, RoutedEventArgs e)
{
DialogResult = true;
Tag = nameof(FallbackButton);
Close();
}
private void RetryButton_Click(object sender, RoutedEventArgs e)
{
DialogResult = true;
Tag = nameof(RetryButton);
Close();
}
private void SystemParameters_StaticPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(SystemParameters.WorkArea))
{
Dispatcher.InvokeAsync(InitializeBounds);
}
}
}
}