mirror of
https://github.com/rmcrackan/Libation.git
synced 2026-01-02 10:58:43 -05:00
Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
359d082ffd | ||
|
|
017bdba404 | ||
|
|
d4bf13b3fd | ||
|
|
87b695b2de | ||
|
|
222b16113e | ||
|
|
75c07c3209 | ||
|
|
e640edee7f | ||
|
|
6c48fc1f5e | ||
|
|
e5708a382b | ||
|
|
da9cb3371f | ||
|
|
91d0f8020e | ||
|
|
156726ca95 | ||
|
|
3dad4c194b | ||
|
|
6025a7538a | ||
|
|
824f65baae |
@@ -63,6 +63,9 @@ Anything between the opening tag (`<tagname->`) and closing tag (`<-tagname>`) w
|
||||
|\<if series-\>...\<-if series\>|Only include if part of a book series or podcast|Conditional|
|
||||
|\<if podcast-\>...\<-if podcast\>|Only include if part of a podcast|Conditional|
|
||||
|\<if bookseries-\>...\<-if bookseries\>|Only include if part of a book series|Conditional|
|
||||
|\<if podcastparent-\>...\<-if podcastparent\>**†**|Only include if item is a podcast series parent|Conditional|
|
||||
|
||||
**†** Only affects the podcast series folder naming if "Save all podcast episodes to the series parent folder" option is checked.
|
||||
|
||||
For example, <if podcast-\>\<series\>\<-if podcast\> will evaluate to the podcast's series name if the file is a podcast. For audiobooks that are not podcasts, that tag will be blank.
|
||||
|
||||
|
||||
@@ -49,12 +49,12 @@
|
||||
* Customizable saved filters for common searches
|
||||
* Open source
|
||||
* Supports most regions: US, UK, Canada, Germany, France, Australia, Japan, India, and Spain
|
||||
* Fully supported in Windows, Mac, and Linux
|
||||
|
||||
<a name="theBad"/>
|
||||
|
||||
### The bad
|
||||
|
||||
* Only fully supported in Windows. (Mac and Linux are in beta)
|
||||
* Large file size
|
||||
* Made by a programmer, not a designer so the goals are function rather than beauty. And it shows
|
||||
|
||||
|
||||
@@ -81,8 +81,6 @@ if test -f 'libcoreclrtraceptprovider.so'; then
|
||||
rm 'libcoreclrtraceptprovider.so'
|
||||
fi
|
||||
|
||||
touch appsettings.json
|
||||
chmod 666 appsettings.json
|
||||
|
||||
install -m 666 libation_glass.svg %{buildroot}%{_datadir}/icons/hicolor/scalable/apps/libation.svg
|
||||
install -m 666 Libation.desktop %{buildroot}%{_datadir}/applications/Libation.desktop
|
||||
@@ -94,26 +92,33 @@ install * %{buildroot}%{_libdir}/%{name}/
|
||||
|
||||
%post
|
||||
|
||||
ln -s %{_libdir}/%{name}/Libation %{_bindir}/libation
|
||||
ln -s %{_libdir}/%{name}/Hangover %{_bindir}/hangover
|
||||
ln -s %{_libdir}/%{name}/LibationCli %{_bindir}/libationcli
|
||||
if [ \$1 -eq 1 ] ; then
|
||||
# Initial installation
|
||||
touch %{_libdir}/%{name}/appsettings.json
|
||||
chmod 666 %{_libdir}/%{name}/appsettings.json
|
||||
|
||||
ln -s %{_libdir}/%{name}/Libation %{_bindir}/libation
|
||||
ln -s %{_libdir}/%{name}/Hangover %{_bindir}/hangover
|
||||
ln -s %{_libdir}/%{name}/LibationCli %{_bindir}/libationcli
|
||||
|
||||
gtk-update-icon-cache -f %{_datadir}/icons/hicolor/
|
||||
gtk-update-icon-cache -f %{_datadir}/icons/hicolor/
|
||||
|
||||
if ! grep -q 'fs.inotify.max_user_instances=524288' /etc/sysctl.conf; then
|
||||
echo fs.inotify.max_user_instances=524288 | tee -a /etc/sysctl.conf && sysctl -p
|
||||
fi
|
||||
fi
|
||||
|
||||
%postun
|
||||
|
||||
rm %{_bindir}/libation
|
||||
rm %{_bindir}/hangover
|
||||
rm %{_bindir}/libationcli
|
||||
|
||||
if ! grep -q 'fs.inotify.max_user_instances=524288' /etc/sysctl.conf; then
|
||||
echo fs.inotify.max_user_instances=524288 | tee -a /etc/sysctl.conf && sysctl -p
|
||||
if [ \$1 -eq 0 ] ; then
|
||||
# Uninstall
|
||||
rm %{_bindir}/libation
|
||||
rm %{_bindir}/hangover
|
||||
rm %{_bindir}/libationcli
|
||||
fi
|
||||
|
||||
%files
|
||||
%{_datadir}/icons/hicolor/scalable/apps/libation.svg
|
||||
%{_datadir}/applications/Libation.desktop
|
||||
%{_libdir}/%{name}/appsettings.json" >> ~/rpmbuild/SPECS/libation.spec
|
||||
%{_datadir}/applications/Libation.desktop" >> ~/rpmbuild/SPECS/libation.spec
|
||||
|
||||
|
||||
cd "$BIN_DIR"
|
||||
|
||||
@@ -190,7 +190,11 @@ namespace AaxDecrypter
|
||||
//Write aax decryption key
|
||||
string keyPath = Path.ChangeExtension(aaxPath, ".key");
|
||||
FileUtility.SaferDelete(keyPath);
|
||||
await File.WriteAllTextAsync(keyPath, $"Key={DownloadOptions.AudibleKey}{Environment.NewLine}IV={DownloadOptions.AudibleIV}");
|
||||
|
||||
if (string.IsNullOrEmpty(DownloadOptions.AudibleIV))
|
||||
await File.WriteAllTextAsync(keyPath, $"ActivationBytes={DownloadOptions.AudibleKey}");
|
||||
else
|
||||
await File.WriteAllTextAsync(keyPath, $"Key={DownloadOptions.AudibleKey}{Environment.NewLine}IV={DownloadOptions.AudibleIV}");
|
||||
|
||||
OnFileCreated(aaxPath);
|
||||
OnFileCreated(keyPath);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<Version>10.3.1.1</Version>
|
||||
<Version>10.3.3.1</Version>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Octokit" Version="6.0.0" />
|
||||
|
||||
@@ -43,6 +43,9 @@ namespace AudibleUtilities
|
||||
[JsonProperty("locale_code")]
|
||||
public string LocaleCode { get; private set; }
|
||||
|
||||
[JsonProperty("with_username")]
|
||||
public bool WithUsername { get; private set; }
|
||||
|
||||
[JsonProperty("activation_bytes")]
|
||||
public string ActivationBytes { get; private set; }
|
||||
|
||||
@@ -68,7 +71,8 @@ namespace AudibleUtilities
|
||||
}
|
||||
|
||||
[JsonIgnore] public ISystemDateTime SystemDateTime { get; } = new SystemDateTime();
|
||||
[JsonIgnore] public Locale Locale => Localization.Get(LocaleCode);
|
||||
[JsonIgnore]
|
||||
public Locale Locale => Localization.Locales.Where(l => l.WithUsername == WithUsername).Single(l => l.CountryCode == LocaleCode);
|
||||
[JsonIgnore] public string DeviceSerialNumber => DeviceInfo.DeviceSerialNumber;
|
||||
[JsonIgnore] public string DeviceType => DeviceInfo.DeviceType;
|
||||
[JsonIgnore] public string AmazonAccountId => CustomerInfo.UserId;
|
||||
@@ -177,6 +181,7 @@ namespace AudibleUtilities
|
||||
DevicePrivateKey = account.IdentityTokens.PrivateKey,
|
||||
AccessTokenExpires = account.IdentityTokens.ExistingAccessToken.Expires,
|
||||
LocaleCode = account.Locale.CountryCode,
|
||||
WithUsername = account.Locale.WithUsername,
|
||||
RefreshToken = account.IdentityTokens.RefreshToken.Value,
|
||||
StoreAuthenticationCookie = account.IdentityTokens.StoreAuthenticationCookie,
|
||||
WebsiteCookies = new(account.IdentityTokens.Cookies),
|
||||
|
||||
@@ -25,8 +25,7 @@ namespace FileLiberator
|
||||
|
||||
if (seriesParent is not null)
|
||||
{
|
||||
var baseDir = Templates.Folder.GetFilename(seriesParent.ToDto(), AudibleFileStorage.BooksDirectory, "");
|
||||
return Templates.Folder.GetFilename(libraryBook.ToDto(), baseDir, "");
|
||||
return Templates.Folder.GetFilename(seriesParent.ToDto(), AudibleFileStorage.BooksDirectory, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,8 @@ namespace FileLiberator
|
||||
|
||||
SeriesName = libraryBook.Book.SeriesLink.FirstOrDefault()?.Series.Name,
|
||||
SeriesNumber = (int?)libraryBook.Book.SeriesLink.FirstOrDefault()?.Index,
|
||||
IsPodcast = libraryBook.Book.IsEpisodeChild(),
|
||||
IsPodcastParent = libraryBook.Book.IsEpisodeParent(),
|
||||
IsPodcast = libraryBook.Book.IsEpisodeChild() || libraryBook.Book.IsEpisodeParent(),
|
||||
|
||||
BitRate = libraryBook.Book.AudioFormat.Bitrate,
|
||||
SampleRate = libraryBook.Book.AudioFormat.SampleRate,
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
<PropertyGroup>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
<!--Avalonia doesen't support TrimMode=link currently,but we are working on that https://github.com/AvaloniaUI/Avalonia/issues/6892 -->
|
||||
<TrimMode>copyused</TrimMode>
|
||||
<BuiltInComInteropSupport>true</BuiltInComInteropSupport>
|
||||
@@ -66,13 +67,13 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
||||
<PackageReference Include="Avalonia" Version="11.0.0-preview8" />
|
||||
<PackageReference Include="Avalonia.Desktop" Version="11.0.0-preview8" />
|
||||
<PackageReference Include="Avalonia" Version="11.0.0-rc1.1" />
|
||||
<PackageReference Include="Avalonia.Desktop" Version="11.0.0-rc1.1" />
|
||||
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
|
||||
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.0.0-preview8" />
|
||||
<PackageReference Include="Avalonia.ReactiveUI" Version="11.0.0-preview8" />
|
||||
<PackageReference Include="Avalonia.Controls.ItemsRepeater" Version="11.0.0-preview8" />
|
||||
<PackageReference Include="Avalonia.Themes.Fluent" Version="11.0.0-preview8" />
|
||||
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.0.0-rc1.1" />
|
||||
<PackageReference Include="Avalonia.ReactiveUI" Version="11.0.0-rc1.1" />
|
||||
<PackageReference Include="Avalonia.Controls.ItemsRepeater" Version="11.0.0-rc1.1" />
|
||||
<PackageReference Include="Avalonia.Themes.Fluent" Version="11.0.0-rc1.1" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\HangoverBase\HangoverBase.csproj" />
|
||||
|
||||
@@ -28,8 +28,6 @@ namespace LibationAvalonia
|
||||
public static IBrush ProcessQueueBookDefaultBrush { get; private set; }
|
||||
public static IBrush SeriesEntryGridBackgroundBrush { get; private set; }
|
||||
|
||||
public static IAssetLoader AssetLoader { get; private set; }
|
||||
|
||||
public static readonly Uri AssetUriBase = new("avares://Libation/Assets/");
|
||||
public static Stream OpenAsset(string assetRelativePath)
|
||||
=> AssetLoader.Open(new Uri(AssetUriBase, assetRelativePath));
|
||||
@@ -37,7 +35,6 @@ namespace LibationAvalonia
|
||||
public override void Initialize()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
AssetLoader = AvaloniaLocator.Current.GetService<IAssetLoader>();
|
||||
}
|
||||
|
||||
public static Task<List<DataLayer.LibraryBook>> LibraryTask;
|
||||
|
||||
@@ -10,9 +10,9 @@ using System.Windows.Input;
|
||||
|
||||
namespace LibationAvalonia.Controls
|
||||
{
|
||||
public partial class LinkLabel : TextBlock, IStyleable, ICommandSource
|
||||
public partial class LinkLabel : TextBlock, ICommandSource
|
||||
{
|
||||
Type IStyleable.StyleKey => typeof(LinkLabel);
|
||||
protected override Type StyleKeyOverride => typeof(LinkLabel);
|
||||
|
||||
public static readonly StyledProperty<ICommand> CommandProperty =
|
||||
AvaloniaProperty.Register<LinkLabel, ICommand>(nameof(Command), enableDataValidation: true);
|
||||
|
||||
@@ -7,7 +7,8 @@ namespace LibationAvalonia.Controls
|
||||
{
|
||||
public partial class WheelComboBox : ComboBox, IStyleable
|
||||
{
|
||||
Type IStyleable.StyleKey => typeof(ComboBox);
|
||||
protected override Type StyleKeyOverride => typeof(ComboBox);
|
||||
|
||||
public WheelComboBox()
|
||||
{
|
||||
InitializeComponent();
|
||||
@@ -16,9 +17,15 @@ namespace LibationAvalonia.Controls
|
||||
{
|
||||
var dir = Math.Sign(e.Delta.Y);
|
||||
if (dir == 1 && SelectedIndex > 0)
|
||||
{
|
||||
SelectedIndex--;
|
||||
e.Handled = true;
|
||||
}
|
||||
else if (dir == -1 && SelectedIndex < ItemCount - 1)
|
||||
{
|
||||
SelectedIndex++;
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
base.OnPointerWheelChanged(e);
|
||||
}
|
||||
|
||||
@@ -70,13 +70,13 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Avalonia.Diagnostics" Version="11.0.0-preview8" Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'" />
|
||||
<PackageReference Include="Avalonia" Version="11.0.0-preview8" />
|
||||
<PackageReference Include="Avalonia.Controls.DataGrid" Version="11.0.0-preview8" />
|
||||
<PackageReference Include="Avalonia.Controls.ItemsRepeater" Version="11.0.0-preview8" />
|
||||
<PackageReference Include="Avalonia.Desktop" Version="11.0.0-preview8" />
|
||||
<PackageReference Include="Avalonia.ReactiveUI" Version="11.0.0-preview8" />
|
||||
<PackageReference Include="Avalonia.Themes.Fluent" Version="11.0.0-preview8" />
|
||||
<PackageReference Include="Avalonia.Diagnostics" Version="11.0.0-rc1.1" Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'" />
|
||||
<PackageReference Include="Avalonia" Version="11.0.0-rc1.1" />
|
||||
<PackageReference Include="Avalonia.Controls.DataGrid" Version="11.0.0-rc1.1" />
|
||||
<PackageReference Include="Avalonia.Controls.ItemsRepeater" Version="11.0.0-rc1.1" />
|
||||
<PackageReference Include="Avalonia.Desktop" Version="11.0.0-rc1.1" />
|
||||
<PackageReference Include="Avalonia.ReactiveUI" Version="11.0.0-rc1.1" />
|
||||
<PackageReference Include="Avalonia.Themes.Fluent" Version="11.0.0-rc1.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Input;
|
||||
|
||||
namespace LibationAvalonia
|
||||
{
|
||||
internal class MacAccessKeyHandler : AccessKeyHandler
|
||||
{
|
||||
protected override void OnPreviewKeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
if (e.Key is Key.LWin or Key.RWin)
|
||||
{
|
||||
var newArgs = new KeyEventArgs { Key = Key.LeftAlt, Handled = e.Handled };
|
||||
base.OnPreviewKeyDown(sender, newArgs);
|
||||
e.Handled = newArgs.Handled;
|
||||
}
|
||||
else if (e.Key is not Key.LeftAlt and not Key.RightAlt)
|
||||
base.OnPreviewKeyDown(sender, e);
|
||||
}
|
||||
|
||||
protected override void OnPreviewKeyUp(object sender, KeyEventArgs e)
|
||||
{
|
||||
if (e.Key is Key.LWin or Key.RWin)
|
||||
{
|
||||
var newArgs = new KeyEventArgs { Key = Key.LeftAlt, Handled = e.Handled };
|
||||
base.OnPreviewKeyUp(sender, newArgs);
|
||||
e.Handled = newArgs.Handled;
|
||||
}
|
||||
else if (e.Key is not Key.LeftAlt and not Key.RightAlt)
|
||||
base.OnPreviewKeyDown(sender, e);
|
||||
}
|
||||
|
||||
protected override void OnKeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
if (e.KeyModifiers.HasAllFlags(KeyModifiers.Meta))
|
||||
{
|
||||
var newArgs = new KeyEventArgs { Key = e.Key, Handled = e.Handled, KeyModifiers = KeyModifiers.Alt };
|
||||
base.OnKeyDown(sender, newArgs);
|
||||
e.Handled = newArgs.Handled;
|
||||
}
|
||||
else if (!e.KeyModifiers.HasFlag(KeyModifiers.Alt))
|
||||
base.OnPreviewKeyDown(sender, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -61,12 +61,12 @@ namespace LibationAvalonia.ViewModels
|
||||
#region Properties exposed to the view
|
||||
public ProcessBookResult Result { get => _result; set { this.RaiseAndSetIfChanged(ref _result, value); this.RaisePropertyChanged(nameof(StatusText)); } }
|
||||
public ProcessBookStatus Status { get => _status; set { this.RaiseAndSetIfChanged(ref _status, value); this.RaisePropertyChanged(nameof(BackgroundColor)); this.RaisePropertyChanged(nameof(IsFinished)); this.RaisePropertyChanged(nameof(IsDownloading)); this.RaisePropertyChanged(nameof(Queued)); } }
|
||||
public string Narrator { get => _narrator; set => Dispatcher.UIThread.Post(() => this.RaiseAndSetIfChanged(ref _narrator, value)); }
|
||||
public string Author { get => _author; set => Dispatcher.UIThread.Post(() => this.RaiseAndSetIfChanged(ref _author, value)); }
|
||||
public string Title { get => _title; set => Dispatcher.UIThread.Post(() => this.RaiseAndSetIfChanged(ref _title, value)); }
|
||||
public int Progress { get => _progress; private set => Dispatcher.UIThread.Post(() => this.RaiseAndSetIfChanged(ref _progress, value)); }
|
||||
public string ETA { get => _eta; private set => Dispatcher.UIThread.Post(() => this.RaiseAndSetIfChanged(ref _eta, value)); }
|
||||
public Bitmap Cover { get => _cover; private set => Dispatcher.UIThread.Post(() => this.RaiseAndSetIfChanged(ref _cover, value)); }
|
||||
public string Narrator { get => _narrator; set => Dispatcher.UIThread.Invoke(() => this.RaiseAndSetIfChanged(ref _narrator, value)); }
|
||||
public string Author { get => _author; set => Dispatcher.UIThread.Invoke(() => this.RaiseAndSetIfChanged(ref _author, value)); }
|
||||
public string Title { get => _title; set => Dispatcher.UIThread.Invoke(() => this.RaiseAndSetIfChanged(ref _title, value)); }
|
||||
public int Progress { get => _progress; private set => Dispatcher.UIThread.Invoke(() => this.RaiseAndSetIfChanged(ref _progress, value)); }
|
||||
public string ETA { get => _eta; private set => Dispatcher.UIThread.Invoke(() => this.RaiseAndSetIfChanged(ref _eta, value)); }
|
||||
public Bitmap Cover { get => _cover; private set => Dispatcher.UIThread.Invoke(() => this.RaiseAndSetIfChanged(ref _cover, value)); }
|
||||
public bool IsFinished => Status is not ProcessBookStatus.Queued and not ProcessBookStatus.Working;
|
||||
public bool IsDownloading => Status is ProcessBookStatus.Working;
|
||||
public bool Queued => Status is ProcessBookStatus.Queued;
|
||||
|
||||
@@ -45,11 +45,11 @@ namespace LibationAvalonia.ViewModels
|
||||
private bool _progressBarVisible;
|
||||
private decimal _speedLimit;
|
||||
|
||||
public int CompletedCount { get => _completedCount; private set => Dispatcher.UIThread.Post(() => { this.RaiseAndSetIfChanged(ref _completedCount, value); this.RaisePropertyChanged(nameof(AnyCompleted)); }); }
|
||||
public int QueuedCount { get => _queuedCount; private set => Dispatcher.UIThread.Post(() => { this.RaiseAndSetIfChanged(ref _queuedCount, value); this.RaisePropertyChanged(nameof(AnyQueued)); }); }
|
||||
public int ErrorCount { get => _errorCount; private set => Dispatcher.UIThread.Post(() => { this.RaiseAndSetIfChanged(ref _errorCount, value); this.RaisePropertyChanged(nameof(AnyErrors)); }); }
|
||||
public string RunningTime { get => _runningTime; set => Dispatcher.UIThread.Post(() => { this.RaiseAndSetIfChanged(ref _runningTime, value); }); }
|
||||
public bool ProgressBarVisible { get => _progressBarVisible; set => Dispatcher.UIThread.Post(() => { this.RaiseAndSetIfChanged(ref _progressBarVisible, value); }); }
|
||||
public int CompletedCount { get => _completedCount; private set => Dispatcher.UIThread.Invoke(() => { this.RaiseAndSetIfChanged(ref _completedCount, value); this.RaisePropertyChanged(nameof(AnyCompleted)); }); }
|
||||
public int QueuedCount { get => _queuedCount; private set => Dispatcher.UIThread.Invoke(() => { this.RaiseAndSetIfChanged(ref _queuedCount, value); this.RaisePropertyChanged(nameof(AnyQueued)); }); }
|
||||
public int ErrorCount { get => _errorCount; private set => Dispatcher.UIThread.Invoke(() => { this.RaiseAndSetIfChanged(ref _errorCount, value); this.RaisePropertyChanged(nameof(AnyErrors)); }); }
|
||||
public string RunningTime { get => _runningTime; set => Dispatcher.UIThread.Invoke(() => { this.RaiseAndSetIfChanged(ref _runningTime, value); }); }
|
||||
public bool ProgressBarVisible { get => _progressBarVisible; set => Dispatcher.UIThread.Invoke(() => { this.RaiseAndSetIfChanged(ref _progressBarVisible, value); }); }
|
||||
public bool AnyCompleted => CompletedCount > 0;
|
||||
public bool AnyQueued => QueuedCount > 0;
|
||||
public bool AnyErrors => ErrorCount > 0;
|
||||
@@ -79,7 +79,7 @@ namespace LibationAvalonia.ViewModels
|
||||
: _speedLimit > 1 ? 0.1m
|
||||
: 0.01m;
|
||||
|
||||
Dispatcher.UIThread.Post(() =>
|
||||
Dispatcher.UIThread.Invoke(() =>
|
||||
{
|
||||
this.RaisePropertyChanged(nameof(SpeedLimitIncrement));
|
||||
this.RaisePropertyChanged();
|
||||
@@ -106,7 +106,7 @@ namespace LibationAvalonia.ViewModels
|
||||
|
||||
public void WriteLine(string text)
|
||||
{
|
||||
Dispatcher.UIThread.Post(() =>
|
||||
Dispatcher.UIThread.Invoke(() =>
|
||||
LogEntries.Add(new()
|
||||
{
|
||||
LogDate = DateTime.Now,
|
||||
@@ -183,7 +183,7 @@ namespace LibationAvalonia.ViewModels
|
||||
|
||||
public void AddToQueue(IEnumerable<ProcessBookViewModel> pbook)
|
||||
{
|
||||
Dispatcher.UIThread.Post(() =>
|
||||
Dispatcher.UIThread.Invoke(() =>
|
||||
{
|
||||
Queue.Enqueue(pbook);
|
||||
if (!Running)
|
||||
|
||||
@@ -252,8 +252,8 @@ namespace LibationAvalonia.Views
|
||||
var displayIndices = config.GridColumnsDisplayIndices;
|
||||
|
||||
var contextMenu = new ContextMenu();
|
||||
contextMenu.MenuClosed += ContextMenu_MenuClosed;
|
||||
contextMenu.ContextMenuOpening += ContextMenu_ContextMenuOpening;
|
||||
contextMenu.Closed += ContextMenu_MenuClosed;
|
||||
contextMenu.Opening += ContextMenu_ContextMenuOpening;
|
||||
List<Control> menuItems = new();
|
||||
contextMenu.ItemsSource = menuItems;
|
||||
|
||||
|
||||
@@ -248,7 +248,7 @@ namespace LibationAvalonia
|
||||
private async Task displayControlAsync(TemplatedControl control)
|
||||
{
|
||||
await UIThread.InvokeAsync(() => control.IsEnabled = false);
|
||||
await UIThread.InvokeAsync(MainForm.productsDisplay.Focus);
|
||||
await UIThread.InvokeAsync(() => MainForm.productsDisplay.Focus());
|
||||
await UIThread.InvokeAsync(() => flashControlAsync(control));
|
||||
if (control is MenuItem menuItem) await UIThread.InvokeAsync(menuItem.Open);
|
||||
await Task.Delay(500);
|
||||
|
||||
@@ -22,6 +22,7 @@ namespace LibationFileManager
|
||||
public string SeriesName { get; set; }
|
||||
public int? SeriesNumber { get; set; }
|
||||
public bool IsSeries => !string.IsNullOrEmpty(SeriesName);
|
||||
public bool IsPodcastParent { get; set; }
|
||||
public bool IsPodcast { get; set; }
|
||||
|
||||
public int BitRate { get; set; }
|
||||
|
||||
@@ -47,6 +47,7 @@ namespace LibationFileManager
|
||||
public static TemplateTags DateAdded { get; } = new TemplateTags("date added", "Date added to your Audible account. e.g. yyyy-MM-dd", $"<date added [{DEFAULT_DATE_FORMAT}]>", "<date added [...]>");
|
||||
public static TemplateTags IfSeries { get; } = new TemplateTags("if series", "Only include if part of a book series or podcast", "<if series-><-if series>", "<if series->...<-if series>");
|
||||
public static TemplateTags IfPodcast { get; } = new TemplateTags("if podcast", "Only include if part of a podcast", "<if podcast-><-if podcast>", "<if podcast->...<-if podcast>");
|
||||
public static TemplateTags IfPodcastParent { get; } = new TemplateTags("if podcastparent", "Only include if item is a podcast series parent", "<if podcastparent-><-if podcastparent>", "<if podcastparent->...<-if podcastparent>");
|
||||
public static TemplateTags IfBookseries { get; } = new TemplateTags("if bookseries", "Only include if part of a book series", "<if bookseries-><-if bookseries>", "<if bookseries->...<-if bookseries>");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -207,13 +207,13 @@ namespace LibationFileManager
|
||||
{ TemplateTags.Narrator, lb => lb.Narrators, NameListFormat.Formatter },
|
||||
{ TemplateTags.FirstNarrator, lb => lb.FirstNarrator },
|
||||
{ TemplateTags.Series, lb => lb.SeriesName },
|
||||
{ TemplateTags.SeriesNumber, lb => lb.SeriesNumber },
|
||||
{ TemplateTags.SeriesNumber, lb => lb.IsPodcastParent ? null : lb.SeriesNumber },
|
||||
{ TemplateTags.Language, lb => lb.Language },
|
||||
//Don't allow formatting of LanguageShort
|
||||
{ TemplateTags.LanguageShort, lb =>lb.Language, getLanguageShort },
|
||||
{ TemplateTags.Bitrate, lb => lb.BitRate },
|
||||
{ TemplateTags.SampleRate, lb => lb.SampleRate },
|
||||
{ TemplateTags.Channels, lb => lb.Channels },
|
||||
{ TemplateTags.Bitrate, lb => (int?)(lb.IsPodcastParent ? null : lb.BitRate) },
|
||||
{ TemplateTags.SampleRate, lb => (int?)(lb.IsPodcastParent ? null : lb.SampleRate) },
|
||||
{ TemplateTags.Channels, lb => (int?)(lb.IsPodcastParent ? null : lb.Channels) },
|
||||
{ TemplateTags.Account, lb => lb.Account },
|
||||
{ TemplateTags.Locale, lb => lb.Locale },
|
||||
{ TemplateTags.YearPublished, lb => lb.YearPublished },
|
||||
@@ -242,9 +242,14 @@ namespace LibationFileManager
|
||||
|
||||
private static readonly ConditionalTagCollection<LibraryBookDto> conditionalTags = new()
|
||||
{
|
||||
{ TemplateTags.IfSeries, lb => lb.IsSeries },
|
||||
{ TemplateTags.IfPodcast, lb => lb.IsPodcast },
|
||||
{ TemplateTags.IfBookseries, lb => lb.IsSeries && !lb.IsPodcast },
|
||||
{ TemplateTags.IfSeries, lb => lb.IsSeries || lb.IsPodcastParent },
|
||||
{ TemplateTags.IfPodcast, lb => lb.IsPodcast || lb.IsPodcastParent },
|
||||
{ TemplateTags.IfBookseries, lb => lb.IsSeries && !lb.IsPodcast && !lb.IsPodcastParent },
|
||||
};
|
||||
|
||||
private static readonly ConditionalTagCollection<LibraryBookDto> folderConditionalTags = new()
|
||||
{
|
||||
{ TemplateTags.IfPodcastParent, lb => lb.IsPodcastParent }
|
||||
};
|
||||
|
||||
#endregion
|
||||
@@ -293,7 +298,8 @@ namespace LibationFileManager
|
||||
public static string Name { get; }= "Folder Template";
|
||||
public static string Description { get; } = Configuration.GetDescription(nameof(Configuration.FolderTemplate));
|
||||
public static string DefaultTemplate { get; } = "<title short> [<id>]";
|
||||
public static IEnumerable<TagCollection> TagCollections => new TagCollection[] { filePropertyTags, conditionalTags };
|
||||
public static IEnumerable<TagCollection> TagCollections
|
||||
=> new TagCollection[] { filePropertyTags, conditionalTags, folderConditionalTags };
|
||||
|
||||
public override IEnumerable<string> Errors
|
||||
=> TemplateText?.Length >= 2 && Path.IsPathFullyQualified(TemplateText) ? base.Errors.Append(ERROR_FULL_PATH_IS_INVALID) : base.Errors;
|
||||
|
||||
@@ -29,11 +29,11 @@ namespace LinuxConfigApp
|
||||
|
||||
//only run the auto upgrader if the current app was installed from the
|
||||
//.deb or .rpm package. Try to detect this by checking if the symlink exists.
|
||||
public bool CanUpgrade => Directory.Exists("/usr/lib/libation");
|
||||
public bool CanUpgrade => File.Exists("/bin/libation");
|
||||
public void InstallUpgrade(string upgradeBundle)
|
||||
{
|
||||
if (File.Exists("/bin/yum"))
|
||||
RunAsRoot("yum", $"install '{upgradeBundle}'");
|
||||
RunAsRoot("yum", $"install -y '{upgradeBundle}'");
|
||||
else
|
||||
RunAsRoot("apt", $"install '{upgradeBundle}'");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user