Fix tags font color in dark mode

This commit is contained in:
Michael Bucari-Tovo 2025-03-04 15:07:37 -07:00
parent c4827fc761
commit 7658f21d7c
2 changed files with 146 additions and 146 deletions

View File

@ -51,7 +51,7 @@
<DataGridTemplateColumn Width="Auto" Header="Tag"> <DataGridTemplateColumn Width="Auto" Header="Tag">
<DataGridTemplateColumn.CellTemplate> <DataGridTemplateColumn.CellTemplate>
<DataTemplate> <DataTemplate>
<TextPresenter Height="18" Margin="10,0,10,0" VerticalAlignment="Center" Text="{Binding Item1}" /> <TextBlock Height="18" Margin="10,0,10,0" VerticalAlignment="Center" Text="{Binding Item1}" />
</DataTemplate> </DataTemplate>
</DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn> </DataGridTemplateColumn>
@ -59,7 +59,7 @@
<DataGridTemplateColumn Width="Auto" Header="Description"> <DataGridTemplateColumn Width="Auto" Header="Description">
<DataGridTemplateColumn.CellTemplate> <DataGridTemplateColumn.CellTemplate>
<DataTemplate> <DataTemplate>
<TextPresenter <TextBlock
Height="18" Height="18"
Margin="10,0,10,0" Margin="10,0,10,0"
VerticalAlignment="Center" Text="{Binding Item2}" /> VerticalAlignment="Center" Text="{Binding Item2}" />

View File

@ -1,8 +1,8 @@
using Avalonia.Collections; using Avalonia.Collections;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Controls.Documents; using Avalonia.Controls.Documents;
using Avalonia.Markup.Xaml;
using Avalonia.Media; using Avalonia.Media;
using Avalonia.Styling;
using Dinah.Core; using Dinah.Core;
using LibationFileManager; using LibationFileManager;
using ReactiveUI; using ReactiveUI;
@ -11,175 +11,175 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace LibationAvalonia.Dialogs namespace LibationAvalonia.Dialogs;
public partial class EditTemplateDialog : DialogWindow
{ {
public partial class EditTemplateDialog : DialogWindow private EditTemplateViewModel _viewModel;
public EditTemplateDialog()
{ {
private EditTemplateViewModel _viewModel; InitializeComponent();
public EditTemplateDialog() if (Design.IsDesignMode)
{ {
InitializeComponent(); _ = Configuration.Instance.LibationFiles;
RequestedThemeVariant = ThemeVariant.Dark;
if (Design.IsDesignMode) var editor = TemplateEditor<Templates.FileTemplate>.CreateFilenameEditor(Configuration.Instance.Books, Configuration.Instance.FileTemplate);
{ _viewModel = new(Configuration.Instance, editor);
_ = Configuration.Instance.LibationFiles; _viewModel.ResetTextBox(editor.EditingTemplate.TemplateText);
var editor = TemplateEditor<Templates.FileTemplate>.CreateFilenameEditor(Configuration.Instance.Books, Configuration.Instance.FileTemplate); Title = $"Edit {editor.TemplateName}";
_viewModel = new(Configuration.Instance, editor);
_viewModel.ResetTextBox(editor.EditingTemplate.TemplateText);
Title = $"Edit {editor.TemplateName}";
DataContext = _viewModel;
}
}
public EditTemplateDialog(ITemplateEditor templateEditor) : this()
{
ArgumentValidator.EnsureNotNull(templateEditor, nameof(templateEditor));
_viewModel = new EditTemplateViewModel(Configuration.Instance, templateEditor);
_viewModel.ResetTextBox(templateEditor.EditingTemplate.TemplateText);
Title = $"Edit {templateEditor.TemplateName}";
DataContext = _viewModel; DataContext = _viewModel;
} }
}
public EditTemplateDialog(ITemplateEditor templateEditor) : this()
{
ArgumentValidator.EnsureNotNull(templateEditor, nameof(templateEditor));
_viewModel = new EditTemplateViewModel(Configuration.Instance, templateEditor);
_viewModel.ResetTextBox(templateEditor.EditingTemplate.TemplateText);
Title = $"Edit {templateEditor.TemplateName}";
DataContext = _viewModel;
}
public void EditTemplateViewModel_DoubleTapped(object sender, Avalonia.Input.TappedEventArgs e) public void EditTemplateViewModel_DoubleTapped(object sender, Avalonia.Input.TappedEventArgs e)
{
var dataGrid = sender as DataGrid;
var item = (dataGrid.SelectedItem as Tuple<string, string, string>).Item3;
if (string.IsNullOrWhiteSpace(item)) return;
var text = userEditTbox.Text;
userEditTbox.Text = text.Insert(Math.Min(Math.Max(0, userEditTbox.CaretIndex), text.Length), item);
userEditTbox.CaretIndex += item.Length;
}
protected override async Task SaveAndCloseAsync()
{
if (!await _viewModel.Validate())
return;
await base.SaveAndCloseAsync();
}
public async void SaveButton_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e)
=> await SaveAndCloseAsync();
private class EditTemplateViewModel : ViewModels.ViewModelBase
{
private readonly Configuration config;
public InlineCollection Inlines { get; } = new();
public ITemplateEditor TemplateEditor { get; }
public EditTemplateViewModel(Configuration configuration, ITemplateEditor templates)
{ {
var dataGrid = sender as DataGrid; config = configuration;
TemplateEditor = templates;
Description = templates.TemplateDescription;
ListItems
= new AvaloniaList<Tuple<string, string, string>>(
TemplateEditor
.EditingTemplate
.TagsRegistered
.Cast<TemplateTags>()
.Select(
t => new Tuple<string, string, string>(
$"<{t.TagName}>",
t.Description,
t.DefaultValue)
)
);
var item = (dataGrid.SelectedItem as Tuple<string, string, string>).Item3;
if (string.IsNullOrWhiteSpace(item)) return;
var text = userEditTbox.Text;
userEditTbox.Text = text.Insert(Math.Min(Math.Max(0, userEditTbox.CaretIndex), text.Length), item);
userEditTbox.CaretIndex += item.Length;
} }
protected override async Task SaveAndCloseAsync() // hold the work-in-progress value. not guaranteed to be valid
private string _userTemplateText;
public string UserTemplateText
{ {
if (!await _viewModel.Validate()) get => _userTemplateText;
return; set
await base.SaveAndCloseAsync();
}
public async void SaveButton_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e)
=> await SaveAndCloseAsync();
private class EditTemplateViewModel : ViewModels.ViewModelBase
{
private readonly Configuration config;
public InlineCollection Inlines { get; } = new();
public ITemplateEditor TemplateEditor { get; }
public EditTemplateViewModel(Configuration configuration, ITemplateEditor templates)
{ {
config = configuration; this.RaiseAndSetIfChanged(ref _userTemplateText, value);
TemplateEditor = templates; templateTb_TextChanged();
Description = templates.TemplateDescription; }
ListItems }
= new AvaloniaList<Tuple<string, string, string>>(
private string _warningText;
public string WarningText { get => _warningText; set => this.RaiseAndSetIfChanged(ref _warningText, value); }
public string Description { get; }
public AvaloniaList<Tuple<string, string, string>> ListItems { get; set; }
public void ResetTextBox(string value) => UserTemplateText = value;
public void ResetToDefault() => ResetTextBox(TemplateEditor.DefaultTemplate);
public async Task<bool> Validate()
{
if (TemplateEditor.EditingTemplate.IsValid)
return true;
var errors
= TemplateEditor
.EditingTemplate
.Errors
.Select(err => $"- {err}")
.Aggregate((a, b) => $"{a}\r\n{b}");
await MessageBox.Show($"This template text is not valid. Errors:\r\n{errors}", "Invalid", MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}
private void templateTb_TextChanged()
{
TemplateEditor.SetTemplateText(UserTemplateText);
const char ZERO_WIDTH_SPACE = '\u200B';
var sing = $"{Path.DirectorySeparatorChar}";
// result: can wrap long paths. eg:
// |-- LINE WRAP BOUNDARIES --|
// \books\author with a very <= normal line break on space between words
// long name\narrator narrator
// \title <= line break on the zero-with space we added before slashes
string slashWrap(string val) => val.Replace(sing, $"{ZERO_WIDTH_SPACE}{sing}");
WarningText
= !TemplateEditor.EditingTemplate.HasWarnings
? ""
: "Warning:\r\n" +
TemplateEditor TemplateEditor
.EditingTemplate .EditingTemplate
.TagsRegistered .Warnings
.Cast<TemplateTags>() .Select(err => $"- {err}")
.Select( .Aggregate((a, b) => $"{a}\r\n{b}");
t => new Tuple<string, string, string>(
$"<{t.TagName}>",
t.Description,
t.DefaultValue)
)
);
} var bold = FontWeight.Bold;
var reg = FontWeight.Normal;
// hold the work-in-progress value. not guaranteed to be valid Inlines.Clear();
private string _userTemplateText;
public string UserTemplateText if (!TemplateEditor.IsFilePath)
{ {
get => _userTemplateText; Inlines.Add(new Run(TemplateEditor.GetName()) { FontWeight = bold });
set return;
{
this.RaiseAndSetIfChanged(ref _userTemplateText, value);
templateTb_TextChanged();
}
} }
private string _warningText; var folder = TemplateEditor.GetFolderName();
public string WarningText { get => _warningText; set => this.RaiseAndSetIfChanged(ref _warningText, value); } var file = TemplateEditor.GetFileName();
var ext = config.DecryptToLossy ? "mp3" : "m4b";
public string Description { get; } Inlines.Add(new Run(slashWrap(TemplateEditor.BaseDirectory.PathWithoutPrefix)) { FontWeight = reg });
Inlines.Add(new Run(sing) { FontWeight = reg });
public AvaloniaList<Tuple<string, string, string>> ListItems { get; set; } Inlines.Add(new Run(slashWrap(folder)) { FontWeight = TemplateEditor.IsFolder ? bold : reg });
public void ResetTextBox(string value) => UserTemplateText = value; Inlines.Add(new Run(sing));
public void ResetToDefault() => ResetTextBox(TemplateEditor.DefaultTemplate);
public async Task<bool> Validate() Inlines.Add(new Run(slashWrap(file)) { FontWeight = TemplateEditor.IsFolder ? reg : bold });
{
if (TemplateEditor.EditingTemplate.IsValid)
return true;
var errors Inlines.Add(new Run($".{ext}"));
= TemplateEditor
.EditingTemplate
.Errors
.Select(err => $"- {err}")
.Aggregate((a, b) => $"{a}\r\n{b}");
await MessageBox.Show($"This template text is not valid. Errors:\r\n{errors}", "Invalid", MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}
private void templateTb_TextChanged()
{
TemplateEditor.SetTemplateText(UserTemplateText);
const char ZERO_WIDTH_SPACE = '\u200B';
var sing = $"{Path.DirectorySeparatorChar}";
// result: can wrap long paths. eg:
// |-- LINE WRAP BOUNDARIES --|
// \books\author with a very <= normal line break on space between words
// long name\narrator narrator
// \title <= line break on the zero-with space we added before slashes
string slashWrap(string val) => val.Replace(sing, $"{ZERO_WIDTH_SPACE}{sing}");
WarningText
= !TemplateEditor.EditingTemplate.HasWarnings
? ""
: "Warning:\r\n" +
TemplateEditor
.EditingTemplate
.Warnings
.Select(err => $"- {err}")
.Aggregate((a, b) => $"{a}\r\n{b}");
var bold = FontWeight.Bold;
var reg = FontWeight.Normal;
Inlines.Clear();
if (!TemplateEditor.IsFilePath)
{
Inlines.Add(new Run(TemplateEditor.GetName()) { FontWeight = bold });
return;
}
var folder = TemplateEditor.GetFolderName();
var file = TemplateEditor.GetFileName();
var ext = config.DecryptToLossy ? "mp3" : "m4b";
Inlines.Add(new Run(slashWrap(TemplateEditor.BaseDirectory.PathWithoutPrefix)) { FontWeight = reg });
Inlines.Add(new Run(sing) { FontWeight = reg });
Inlines.Add(new Run(slashWrap(folder)) { FontWeight = TemplateEditor.IsFolder ? bold : reg });
Inlines.Add(new Run(sing));
Inlines.Add(new Run(slashWrap(file)) { FontWeight = TemplateEditor.IsFolder ? reg : bold });
Inlines.Add(new Run($".{ext}"));
}
} }
} }
} }