Files
FluentTerminal/FluentTerminal.App.ViewModels/Settings/ThemesPageViewModel.cs
T
Leonardo Di Stasio 37b4fd283a Add theme background image feature (#545)
* Add a background image property in theme

* Add the browse command to theme settings page

The goal was to create a command that permit to browse user pictures.
The user can now select is picture by browsing file or to simply copy the
link of the image in the textbox.

* Try to show the image that we download

* Change the save image method in file service

We call the method `ImportImageFile` so that we can show a picker dialog
and directly import the image in the roaming folder.
We make some check to avoid the application crash, still need to test

* Reorganize the UI for image import

* Add background brush converter

Now that we have a background image we need to set the background according
to the theme color or the selected image.
To do this we need to use the `ThemeViewModel` and the new converter to
select the right brush to use (`ImageBrush` or ` AcrylicBrush`)

* Use the File object insted of a image path

* Add background style to content and toolbar

* Create the ImageFile object

* Use the ImageFile object so that we can serialize the theme

* Remove commented code

* Remove the base64 string of the image file

* Disable if it's a preinstalled theme

* Add new event when background image changed

* Make the RemoveImportedImage method async

* Subscribe to background image event and change background in code behind

* Add the delete background image command

* Remove unused converters that we created

* Save background image in temporary folder

* Remove the temporary images and save the last one

* Implement the cancel and delete background

* Show the background image in terminal

* Split the image file methods in another interface

* Change the name of image saving method

* Prepare the object and methods to export encoded image

* Add import method to deserialize correctly the theme

* Remove the private from the set accessor

* Implememnt the import method

* Implement the conversion base64 image to real image

* Create the background image and import it

* Fix some actions bug

* Get the new image file name after import

* Fix some bugs when the image is deleted

* Move the background image in terminal view

* Translate the background image text

* Add the delete background command

* Fix the background image deletion if we click on cancel

* Add background opacity property to terminal view model

* Need to create a theme changed event

If we don't notify the view that the selected theme has changed with
another theme that has the same background but a different background image
we'll never see this image appear.
In fact the background change is triggered by the background color change.

* Remove the background from the theme settings page

* Fix error of last edited image

* Fix image background aspect ratio
2019-10-20 10:30:52 +02:00

223 lines
8.3 KiB
C#

using FluentTerminal.App.Services;
using FluentTerminal.App.Services.Utilities;
using FluentTerminal.App.ViewModels.Infrastructure;
using FluentTerminal.Models;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading.Tasks;
using FluentTerminal.Models.Messages;
namespace FluentTerminal.App.ViewModels.Settings
{
public class ThemesPageViewModel : ViewModelBase
{
private readonly IDefaultValueProvider _defaultValueProvider;
private readonly IDialogService _dialogService;
private readonly ISettingsService _settingsService;
private ThemeViewModel _selectedTheme;
private double _backgroundOpacity;
private readonly IThemeParserFactory _themeParserFactory;
private readonly IFileSystemService _fileSystemService;
private readonly IImageFileSystemService _imageFileSystemService;
public event EventHandler<string> SelectedThemeBackgroundColorChanged;
public event EventHandler<ImageFile> SelectedThemeBackgroundImageChanged;
public event EventHandler<ThemeViewModel> SelectedThemeChanged;
public ThemesPageViewModel(ISettingsService settingsService,
IDialogService dialogService,
IDefaultValueProvider defaultValueProvider,
IThemeParserFactory themeParserFactory,
IFileSystemService fileSystemService,
IImageFileSystemService imageFileSystemService)
{
_settingsService = settingsService;
_dialogService = dialogService;
_defaultValueProvider = defaultValueProvider;
_themeParserFactory = themeParserFactory;
_fileSystemService = fileSystemService;
_imageFileSystemService = imageFileSystemService;
CreateThemeCommand = new RelayCommand(CreateTheme);
ImportThemeCommand = new AsyncCommand(ImportTheme);
CloneCommand = new RelayCommand<ThemeViewModel>(CloneTheme);
MessengerInstance.Register<TerminalOptionsChangedMessage>(this, OnTerminalOptionsChanged);
BackgroundOpacity = _settingsService.GetTerminalOptions().BackgroundOpacity;
var activeThemeId = _settingsService.GetCurrentThemeId();
foreach (var theme in _settingsService.GetThemes())
{
var viewModel = new ThemeViewModel(theme, _settingsService, _dialogService, _fileSystemService, _imageFileSystemService, false);
viewModel.Activated += OnThemeActivated;
viewModel.Deleted += OnThemeDeleted;
if (theme.Id == activeThemeId)
{
viewModel.IsActive = true;
}
Themes.Add(viewModel);
}
SelectedTheme = Themes.First(t => t.IsActive);
}
public RelayCommand CreateThemeCommand { get; }
public IAsyncCommand ImportThemeCommand { get; }
public RelayCommand<ThemeViewModel> CloneCommand { get; set; }
public double BackgroundOpacity
{
get => _backgroundOpacity;
set => Set(ref _backgroundOpacity, value);
}
public ThemeViewModel SelectedTheme
{
get => _selectedTheme;
set
{
if (_selectedTheme != null)
{
_selectedTheme.BackgroundChanged -= OnSelectedThemeBackgroundChanged;
_selectedTheme.BackgroundImageChanged -= OnSelectedThemeBackgroundImageChanged;
}
Set(ref _selectedTheme, value);
SelectedThemeChanged?.Invoke(this, _selectedTheme);
if (value != null)
{
_selectedTheme.BackgroundOpacity = BackgroundOpacity;
value.BackgroundChanged += OnSelectedThemeBackgroundChanged;
value.BackgroundImageChanged += OnSelectedThemeBackgroundImageChanged;
}
}
}
public ObservableCollection<ThemeViewModel> Themes { get; } = new ObservableCollection<ThemeViewModel>();
private void CloneTheme(ThemeViewModel theme)
{
var cloned = new TerminalTheme(theme.Model)
{
Id = Guid.NewGuid(),
PreInstalled = false,
Name = $"Copy of {theme.Name}"
};
AddTheme(cloned);
}
private void CreateTheme()
{
var defaultTheme = _settingsService.GetTheme(_defaultValueProvider.GetDefaultThemeId());
var theme = new TerminalTheme
{
Id = Guid.NewGuid(),
PreInstalled = false,
Name = "New Theme",
Colors = new TerminalColors(defaultTheme.Colors)
};
AddTheme(theme);
}
private async Task ImportTheme()
{
var file = await _fileSystemService.OpenFile(_themeParserFactory.SupportedFileTypes).ConfigureAwait(true);
if (file != null)
{
var parser = _themeParserFactory.GetParser(file.FileType);
if (parser == null)
{
await _dialogService.ShowMessageDialogAsnyc(I18N.Translate("ImportThemeFailed"), I18N.Translate("NoSuitableParserFound"), DialogButton.OK).ConfigureAwait(false);
return;
}
try
{
var exportedTheme = await parser.Import(file.Name, file.Content).ConfigureAwait(true);
if (!string.IsNullOrWhiteSpace(exportedTheme.EncodedImage))
{
var importedImage = await _imageFileSystemService.ImportThemeImage(exportedTheme.BackgroundImage, exportedTheme.EncodedImage);
exportedTheme.BackgroundImage = importedImage;
}
var terminalTheme = new TerminalTheme(exportedTheme);
AddTheme(terminalTheme);
}
catch (Exception exception)
{
await _dialogService.ShowMessageDialogAsnyc(I18N.Translate("ImportThemeFailed"), exception.Message, DialogButton.OK).ConfigureAwait(false);
}
}
}
private void AddTheme(TerminalTheme theme)
{
_settingsService.SaveTheme(theme, true);
var viewModel = new ThemeViewModel(theme, _settingsService, _dialogService, _fileSystemService, _imageFileSystemService, true);
viewModel.EditCommand.Execute(null);
viewModel.Activated += OnThemeActivated;
viewModel.Deleted += OnThemeDeleted;
Themes.Add(viewModel);
SelectedTheme = viewModel;
}
private void OnThemeActivated(object sender, EventArgs e)
{
if (sender is ThemeViewModel activatedTheme)
{
_settingsService.SaveCurrentThemeId(activatedTheme.Id);
foreach (var theme in Themes)
{
theme.IsActive = theme.Id == activatedTheme.Id;
}
}
}
private void OnThemeDeleted(object sender, EventArgs e)
{
if (sender is ThemeViewModel theme)
{
if (SelectedTheme == theme)
{
SelectedTheme = Themes.First();
}
Themes.Remove(theme);
if (theme.IsActive)
{
Themes.First().IsActive = true;
_settingsService.SaveCurrentThemeId(Themes.First().Id);
}
_settingsService.DeleteTheme(theme.Id);
}
}
private void OnTerminalOptionsChanged(TerminalOptionsChangedMessage message)
{
BackgroundOpacity = message.TerminalOptions.BackgroundOpacity;
}
private void OnSelectedThemeBackgroundChanged(object sender, string e)
{
SelectedThemeBackgroundColorChanged?.Invoke(this, e);
}
private void OnSelectedThemeBackgroundImageChanged(object sender, ImageFile e)
{
SelectedThemeBackgroundImageChanged?.Invoke(this, e);
}
}
}