├── .editorconfig ├── .gitattributes ├── .github ├── FUNDING.yml └── workflows │ ├── build-nightly.yml │ └── build-release.yml ├── .gitignore ├── LICENSE.md ├── LRReader.Avalonia.Desktop ├── LRReader.Avalonia.Desktop.csproj ├── Program.cs ├── Properties │ └── PublishProfiles │ │ ├── linux-x64.pubxml │ │ ├── macos-x64.pubxml │ │ └── win-x64.pubxml └── logo.ico ├── LRReader.Avalonia ├── App.axaml ├── App.axaml.cs ├── Assets │ ├── SplashScreen.scale-200.png │ └── Square44x44Logo.altform-unplated_targetsize-256.png ├── Init.cs ├── LRReader.Avalonia.csproj ├── ResourceLoader.cs ├── Resources │ ├── AvaloniaTemplates.axaml │ └── ThemeDictionary.axaml ├── Services │ ├── Dispatcher.cs │ ├── Files.cs │ ├── ImageProcessing.cs │ ├── Platform.cs │ └── SettingsStorage.cs ├── Views │ ├── Controls │ │ └── CustomTab.cs │ ├── Dialogs │ │ ├── GenericDialog.axaml │ │ ├── GenericDialog.axaml.cs │ │ ├── ServerProfileDialog.axaml │ │ └── ServerProfileDialog.axaml.cs │ ├── Items │ │ ├── ArchiveItem.axaml │ │ └── ArchiveItem.axaml.cs │ ├── Main │ │ ├── FirstRunPage.axaml │ │ ├── FirstRunPage.axaml.cs │ │ ├── HostTabPage.axaml │ │ ├── HostTabPage.axaml.cs │ │ ├── LoadingPage.axaml │ │ └── LoadingPage.axaml.cs │ ├── MainView.axaml │ ├── MainView.axaml.cs │ ├── MainWindow.axaml │ ├── MainWindow.axaml.cs │ └── Tabs │ │ ├── ArchivesTab.axaml │ │ ├── ArchivesTab.axaml.cs │ │ ├── Content │ │ ├── Archives.axaml │ │ └── Archives.axaml.cs │ │ ├── SettingsTab.axaml │ │ └── SettingsTab.axaml.cs └── nuget.config ├── LRReader.Shared ├── ApiConnection.cs ├── Converters │ └── Converters.cs ├── Directory.Build.targets ├── Extensions │ └── Extensions.cs ├── Formats │ └── JpegXL │ │ ├── JpegXLConfigurationModule.cs │ │ ├── JpegXLConstants.cs │ │ ├── JpegXLDecoder.cs │ │ ├── JpegXLFormat.cs │ │ ├── JpegXLImageFormatDetector.cs │ │ └── JpegXLMetadata.cs ├── Generic.cs ├── Internal │ └── Util.cs ├── LRReader.Shared.csproj ├── Messages │ └── Events.cs ├── Models │ ├── App.cs │ ├── Dialogs.cs │ ├── Karen.cs │ ├── Main │ │ ├── Archive.cs │ │ ├── Category.cs │ │ ├── Database.cs │ │ ├── Generic.cs │ │ ├── Minion.cs │ │ ├── Plugins.cs │ │ ├── Profile.cs │ │ ├── Server.cs │ │ ├── Shinobu.cs │ │ ├── Tags.cs │ │ └── Tankoubon.cs │ └── Payloads.cs ├── Providers │ ├── ArchivesProvider.cs │ ├── CategoriesProvider.cs │ ├── DatabaseProvider.cs │ ├── SearchProvider.cs │ ├── ServerProvider.cs │ ├── ShinobuProvider.cs │ └── TankoubonsProvider.cs ├── Services │ ├── Api.cs │ ├── Archives.cs │ ├── Dispatcher.cs │ ├── Events.cs │ ├── Files.cs │ ├── ImageProcessing.cs │ ├── Images.cs │ ├── Karen.cs │ ├── Persistance.cs │ ├── Platform.cs │ ├── Services.cs │ ├── Settings.cs │ ├── SettingsStorage.cs │ ├── Tabs.cs │ └── Updates.cs ├── Tools │ ├── Deduplicator.cs │ └── Tool.cs ├── ViewModels │ ├── ArchiveEditViewModel.cs │ ├── ArchivePageViewModel.cs │ ├── ArchivesPageViewModel.cs │ ├── Base │ │ ├── ArchiveBaseViewModel.cs │ │ ├── CategoryBaseViewModel.cs │ │ └── TankoubonBaseViewModel.cs │ ├── BookmarksTabViewModel.cs │ ├── CategoriesViewModel.cs │ ├── CategoryArchiveViewModel.cs │ ├── CategoryEditViewModel.cs │ ├── Items │ │ ├── ArchiveHitViewModel.cs │ │ ├── ArchiveImageViewModel.cs │ │ └── ArchiveItemViewModel.cs │ ├── LoadingPageViewModel.cs │ ├── SearchResultsViewModel.cs │ ├── SettingsPageViewModel.cs │ ├── TankoubonEditViewModel.cs │ ├── TankoubonViewModel.cs │ ├── TankoubonsViewModel.cs │ └── Tools │ │ ├── BulkEditorViewModel.cs │ │ ├── DeduplicatorToolViewModel.cs │ │ └── ToolViewModel.cs └── packages.lock.json ├── LRReader.UWP.Installer ├── App.xaml ├── App.xaml.cs ├── EntryPoint.cs ├── FodyWeavers.xml ├── FodyWeavers.xsd ├── LRReader.UWP.Installer.csproj ├── MainWindow.xaml ├── MainWindow.xaml.cs ├── Variables.cs ├── Win32Interop.cs ├── app.manifest ├── logo.ico └── packages.lock.json ├── LRReader.UWP.Servicing.CertInstaller ├── FodyWeavers.xml ├── FodyWeavers.xsd ├── LRReader.UWP.Servicing.CertInstaller.csproj ├── Program.cs └── app.manifest ├── LRReader.UWP.Servicing ├── CertInfo.cs ├── CertUtil.cs ├── LRReader.UWP.Servicing.csproj ├── Process.cs └── packages.lock.json ├── LRReader.UWP ├── App.xaml ├── App.xaml.cs ├── Assets │ ├── LargeTile.scale-100.png │ ├── LargeTile.scale-125.png │ ├── LargeTile.scale-150.png │ ├── LargeTile.scale-200.png │ ├── LargeTile.scale-400.png │ ├── LockScreenLogo.scale-200.png │ ├── Other │ │ ├── GitHub-dark.png │ │ ├── GitHub-light.png │ │ ├── LANraragi-dark.png │ │ └── LANraragi-light.png │ ├── SmallTile.scale-100.png │ ├── SmallTile.scale-125.png │ ├── SmallTile.scale-150.png │ ├── SmallTile.scale-200.png │ ├── SmallTile.scale-400.png │ ├── SplashScreen.scale-100.png │ ├── SplashScreen.scale-125.png │ ├── SplashScreen.scale-150.png │ ├── SplashScreen.scale-200.png │ ├── SplashScreen.scale-400.png │ ├── Square150x150Logo.scale-100.png │ ├── Square150x150Logo.scale-125.png │ ├── Square150x150Logo.scale-150.png │ ├── Square150x150Logo.scale-200.png │ ├── Square150x150Logo.scale-400.png │ ├── Square44x44Logo.altform-lightunplated_targetsize-16.png │ ├── Square44x44Logo.altform-lightunplated_targetsize-24.png │ ├── Square44x44Logo.altform-lightunplated_targetsize-256.png │ ├── Square44x44Logo.altform-lightunplated_targetsize-32.png │ ├── Square44x44Logo.altform-lightunplated_targetsize-48.png │ ├── Square44x44Logo.altform-unplated_targetsize-16.png │ ├── Square44x44Logo.altform-unplated_targetsize-256.png │ ├── Square44x44Logo.altform-unplated_targetsize-32.png │ ├── Square44x44Logo.altform-unplated_targetsize-48.png │ ├── Square44x44Logo.scale-100.png │ ├── Square44x44Logo.scale-125.png │ ├── Square44x44Logo.scale-150.png │ ├── Square44x44Logo.scale-200.png │ ├── Square44x44Logo.scale-400.png │ ├── Square44x44Logo.targetsize-16.png │ ├── Square44x44Logo.targetsize-24.png │ ├── Square44x44Logo.targetsize-24_altform-unplated.png │ ├── Square44x44Logo.targetsize-256.png │ ├── Square44x44Logo.targetsize-32.png │ ├── Square44x44Logo.targetsize-48.png │ ├── StoreLogo.backup.png │ ├── StoreLogo.scale-100.png │ ├── StoreLogo.scale-125.png │ ├── StoreLogo.scale-150.png │ ├── StoreLogo.scale-200.png │ ├── StoreLogo.scale-400.png │ ├── Wide310x150Logo.scale-100.png │ ├── Wide310x150Logo.scale-125.png │ ├── Wide310x150Logo.scale-150.png │ ├── Wide310x150Logo.scale-200.png │ └── Wide310x150Logo.scale-400.png ├── Converters │ └── Converters.cs ├── Directory.Build.targets ├── Extensions │ ├── Extensions.cs │ └── ScrollViewerExtensions.cs ├── Helpers │ └── EnumValueExtension.cs ├── Init.cs ├── Internal │ └── Utils.cs ├── LRReader.UWP.csproj ├── Package.appxmanifest ├── Properties │ ├── PublishProfiles │ │ ├── win-arm64.pubxml │ │ └── win-x64.pubxml │ └── launchSettings.json ├── Resources │ ├── Converters.xaml │ ├── MiddleClickScrolling-CursorType.res │ ├── Templates.xaml │ ├── Templates.xaml.cs │ ├── ThemeDictionary.xaml │ ├── WinUITemplates.xaml │ └── WinUITemplates.xaml.cs ├── Secrets.cs ├── Services │ ├── Dispatcher.cs │ ├── Files.cs │ ├── ImageProcessing.cs │ ├── Karen.cs │ ├── Platform.cs │ ├── SettingsStorage.cs │ └── Updates.cs ├── Strings │ ├── en │ │ ├── Dialogs.resw │ │ ├── Generic.resw │ │ ├── Items.resw │ │ ├── Pages.resw │ │ ├── Settings.resw │ │ ├── Shared.resw │ │ ├── Tabs.resw │ │ └── Tools.resw │ ├── es │ │ ├── Dialogs.resw │ │ ├── Generic.resw │ │ ├── Items.resw │ │ ├── Pages.resw │ │ ├── Settings.resw │ │ ├── Shared.resw │ │ ├── Tabs.resw │ │ └── Tools.resw │ ├── ru │ │ ├── Dialogs.resw │ │ ├── Generic.resw │ │ ├── Items.resw │ │ ├── Pages.resw │ │ ├── Settings.resw │ │ ├── Shared.resw │ │ ├── Tabs.resw │ │ └── Tools.resw │ └── zh-cn │ │ ├── Dialogs.resw │ │ ├── Generic.resw │ │ ├── Items.resw │ │ ├── Pages.resw │ │ ├── Settings.resw │ │ ├── Shared.resw │ │ ├── Tabs.resw │ │ └── Tools.resw ├── Util │ └── IgnoreFocusKeyboardAccelerator.cs ├── Views │ ├── Content │ │ ├── Empty.xaml │ │ ├── Empty.xaml.cs │ │ ├── Settings │ │ │ ├── About.xaml │ │ │ ├── About.xaml.cs │ │ │ ├── Feedback.xaml │ │ │ ├── Feedback.xaml.cs │ │ │ ├── General.xaml │ │ │ ├── General.xaml.cs │ │ │ ├── Main.xaml │ │ │ ├── Main.xaml.cs │ │ │ ├── Profiles.xaml │ │ │ ├── Profiles.xaml.cs │ │ │ ├── Reader.xaml │ │ │ ├── Reader.xaml.cs │ │ │ ├── Server.xaml │ │ │ ├── Server.xaml.cs │ │ │ ├── Updates.xaml │ │ │ └── Updates.xaml.cs │ │ ├── Tools │ │ │ ├── BulkEditor.xaml │ │ │ ├── BulkEditor.xaml.cs │ │ │ ├── Deduplicator.xaml │ │ │ ├── Deduplicator.xaml.cs │ │ │ ├── DeduplicatorHidden.xaml │ │ │ ├── DeduplicatorHidden.xaml.cs │ │ │ ├── Main.xaml │ │ │ └── Main.xaml.cs │ │ ├── WebContent.xaml │ │ └── WebContent.xaml.cs │ ├── Controls │ │ ├── ArchiveList.xaml │ │ ├── ArchiveList.xaml.cs │ │ ├── ArchiveTags.xaml │ │ ├── ArchiveTags.xaml.cs │ │ ├── ArchiveTemplateSelector.cs │ │ ├── ModernBasePage.cs │ │ ├── ModernExpander.xaml │ │ ├── ModernExpander.xaml.cs │ │ ├── ModernGroup.cs │ │ ├── ModernInput.cs │ │ ├── ModernPageTab.xaml │ │ ├── ModernPageTab.xaml.cs │ │ ├── ModernTab.cs │ │ ├── ModernTabView.cs │ │ ├── ModernWebView.cs │ │ └── NoBorderListViewItemPresenter.cs │ ├── Dialogs │ │ ├── CategoryArchive.xaml │ │ ├── CategoryArchive.xaml.cs │ │ ├── CreateCategory.xaml │ │ ├── CreateCategory.xaml.cs │ │ ├── CreateTankoubon.xaml │ │ ├── CreateTankoubon.xaml.cs │ │ ├── GenericDialog.xaml │ │ ├── GenericDialog.xaml.cs │ │ ├── MarkdownDialog.xaml │ │ ├── MarkdownDialog.xaml.cs │ │ ├── ProgressConflict.xaml │ │ ├── ProgressConflict.xaml.cs │ │ ├── ServerProfileDialog.xaml │ │ ├── ServerProfileDialog.xaml.cs │ │ ├── ThumbnailPicker.xaml │ │ ├── ThumbnailPicker.xaml.cs │ │ ├── ValidateApiDialog.xaml │ │ └── ValidateApiDialog.xaml.cs │ ├── Items │ │ ├── ArchiveHitItem.xaml │ │ ├── ArchiveHitItem.xaml.cs │ │ ├── ArchiveImage.cs │ │ ├── CategoryItem.xaml │ │ ├── CategoryItem.xaml.cs │ │ ├── GenericArchiveItem.cs │ │ ├── ReaderImage.xaml │ │ ├── ReaderImage.xaml.cs │ │ ├── TankoubonItem.xaml │ │ └── TankoubonItem.xaml.cs │ ├── Main │ │ ├── FirstRunPage.xaml │ │ ├── FirstRunPage.xaml.cs │ │ ├── HostTabPage.xaml │ │ ├── HostTabPage.xaml.cs │ │ ├── LoadingPage.xaml │ │ └── LoadingPage.xaml.cs │ ├── Root.xaml │ ├── Root.xaml.cs │ └── Tabs │ │ ├── ArchiveEditTab.xaml │ │ ├── ArchiveEditTab.xaml.cs │ │ ├── ArchiveTab.xaml │ │ ├── ArchiveTab.xaml.cs │ │ ├── ArchivesTab.xaml │ │ ├── ArchivesTab.xaml.cs │ │ ├── BookmarksTab.xaml │ │ ├── BookmarksTab.xaml.cs │ │ ├── CategoriesTab.xaml │ │ ├── CategoriesTab.xaml.cs │ │ ├── CategoryEditTab.xaml │ │ ├── CategoryEditTab.xaml.cs │ │ ├── Content │ │ ├── ArchiveEdit.xaml │ │ ├── ArchiveEdit.xaml.cs │ │ ├── ArchiveTabContent.xaml │ │ ├── ArchiveTabContent.xaml.cs │ │ ├── ArchivesTabContent.xaml │ │ ├── ArchivesTabContent.xaml.cs │ │ ├── Bookmarks.xaml │ │ ├── Bookmarks.xaml.cs │ │ ├── Categories.xaml │ │ ├── Categories.xaml.cs │ │ ├── CategoryEdit.xaml │ │ ├── CategoryEdit.xaml.cs │ │ ├── SearchResults.xaml │ │ ├── SearchResults.xaml.cs │ │ ├── Tankoubon.xaml │ │ ├── Tankoubon.xaml.cs │ │ ├── TankoubonEdit.xaml │ │ ├── TankoubonEdit.xaml.cs │ │ ├── Tankoubons.xaml │ │ └── Tankoubons.xaml.cs │ │ ├── SearchResultsTab.xaml │ │ ├── SearchResultsTab.xaml.cs │ │ ├── SettingsTab.xaml │ │ ├── SettingsTab.xaml.cs │ │ ├── TankoubonEditTab.xaml │ │ ├── TankoubonEditTab.xaml.cs │ │ ├── TankoubonTab.xaml │ │ ├── TankoubonTab.xaml.cs │ │ ├── TankoubonsTab.xaml │ │ ├── TankoubonsTab.xaml.cs │ │ ├── ToolsTab.xaml │ │ ├── ToolsTab.xaml.cs │ │ ├── WebTab.xaml │ │ └── WebTab.xaml.cs ├── packages.lock.json └── zServicing │ └── .gitkeep ├── LRReader.sln ├── LRReader.slnx ├── Privacy.md ├── README.md ├── Util ├── CleanInstaller.ps1 ├── ConfigureAppCenter.ps1 ├── ConfigureInstaller.ps1 ├── Package.appxmanifest ├── PrepareForUpload.ps1 └── Version.ps1 └── nuget.config /.editorconfig: -------------------------------------------------------------------------------- 1 | [*.cs] 2 | indent_style = tab 3 | 4 | [*.csproj] 5 | indent_style = space 6 | tab_width = 2 7 | indent_size = 2 -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: Guerra24 2 | -------------------------------------------------------------------------------- /LRReader.Avalonia.Desktop/LRReader.Avalonia.Desktop.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | WinExe 4 | net6.0 5 | enable 6 | logo.ico 7 | true 8 | copyused 9 | AnyCPU 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /LRReader.Avalonia.Desktop/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Avalonia; 3 | 4 | namespace LRReader.Avalonia.Desktop 5 | { 6 | static class Program 7 | { 8 | // Initialization code. Don't use any Avalonia, third-party APIs or any 9 | // SynchronizationContext-reliant code before AppMain is called: things aren't initialized 10 | // yet and stuff might break. 11 | [STAThread] 12 | public static void Main(string[] args) 13 | { 14 | Init.EarlyInit(); 15 | BuildAvaloniaApp().StartWithClassicDesktopLifetime(args); 16 | } 17 | 18 | // Avalonia configuration, don't remove; also used by visual designer. 19 | public static AppBuilder BuildAvaloniaApp() 20 | => AppBuilder.Configure() 21 | .UsePlatformDetect() 22 | .LogToTrace(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /LRReader.Avalonia.Desktop/Properties/PublishProfiles/linux-x64.pubxml: -------------------------------------------------------------------------------- 1 |  2 | 5 | 6 | 7 | Release 8 | Any CPU 9 | publish\linux-x64\ 10 | FileSystem 11 | net6.0 12 | linux-x64 13 | true 14 | true 15 | true 16 | 17 | -------------------------------------------------------------------------------- /LRReader.Avalonia.Desktop/Properties/PublishProfiles/macos-x64.pubxml: -------------------------------------------------------------------------------- 1 |  2 | 5 | 6 | 7 | Release 8 | Any CPU 9 | publish\macos-x64\ 10 | FileSystem 11 | net6.0 12 | osx-x64 13 | true 14 | true 15 | true 16 | 17 | -------------------------------------------------------------------------------- /LRReader.Avalonia.Desktop/Properties/PublishProfiles/win-x64.pubxml: -------------------------------------------------------------------------------- 1 |  2 | 5 | 6 | 7 | Release 8 | Any CPU 9 | publish\win-x64\ 10 | FileSystem 11 | net6.0 12 | win-x64 13 | true 14 | true 15 | false 16 | true 17 | 18 | -------------------------------------------------------------------------------- /LRReader.Avalonia.Desktop/logo.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Guerra24/LRReader/c4f30a8a85062517f6f51f039885a57d1cb84ebb/LRReader.Avalonia.Desktop/logo.ico -------------------------------------------------------------------------------- /LRReader.Avalonia/App.axaml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /LRReader.Avalonia/App.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia; 2 | using Avalonia.Controls.ApplicationLifetimes; 3 | using Avalonia.Markup.Xaml; 4 | using LRReader.Avalonia.Views; 5 | 6 | namespace LRReader.Avalonia 7 | { 8 | public class App : Application 9 | { 10 | public override void Initialize() 11 | { 12 | AvaloniaXamlLoader.Load(this); 13 | } 14 | 15 | public override void OnFrameworkInitializationCompleted() 16 | { 17 | if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) 18 | { 19 | desktop.MainWindow = new MainWindow(); 20 | } 21 | else if (ApplicationLifetime is ISingleViewApplicationLifetime singleView) 22 | { 23 | singleView.MainView = new MainView(); 24 | } 25 | 26 | base.OnFrameworkInitializationCompleted(); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /LRReader.Avalonia/Assets/SplashScreen.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Guerra24/LRReader/c4f30a8a85062517f6f51f039885a57d1cb84ebb/LRReader.Avalonia/Assets/SplashScreen.scale-200.png -------------------------------------------------------------------------------- /LRReader.Avalonia/Assets/Square44x44Logo.altform-unplated_targetsize-256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Guerra24/LRReader/c4f30a8a85062517f6f51f039885a57d1cb84ebb/LRReader.Avalonia/Assets/Square44x44Logo.altform-unplated_targetsize-256.png -------------------------------------------------------------------------------- /LRReader.Avalonia/Init.cs: -------------------------------------------------------------------------------- 1 | using LRReader.Avalonia.Services; 2 | using LRReader.Shared.Services; 3 | using Microsoft.Extensions.DependencyInjection; 4 | using Microsoft.Extensions.DependencyInjection.Extensions; 5 | 6 | namespace LRReader.Avalonia 7 | { 8 | public static class Init 9 | { 10 | public static void EarlyInit() 11 | { 12 | Service.BuildServices((ServiceCollection collection) => 13 | { 14 | collection.Replace(ServiceDescriptor.Singleton()); 15 | collection.Replace(ServiceDescriptor.Singleton()); 16 | collection.Replace(ServiceDescriptor.Singleton()); 17 | collection.Replace(ServiceDescriptor.Singleton()); 18 | 19 | collection.AddSingleton(); 20 | }); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /LRReader.Avalonia/LRReader.Avalonia.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | net6.0 4 | enable 5 | AnyCPU 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /LRReader.Avalonia/ResourceLoader.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Reflection; 4 | using System.Text.RegularExpressions; 5 | using System.Xml; 6 | using Avalonia.Markup.Xaml; 7 | 8 | namespace LRReader.Avalonia 9 | { 10 | class ResourceLoader 11 | { 12 | 13 | private Dictionary Lang = new Dictionary(); 14 | 15 | public ResourceLoader(string file) 16 | { 17 | var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream($"LRReader.Avalonia.Strings.en.{file}.resw"); 18 | if (stream == null) 19 | return; 20 | using (stream) 21 | { 22 | var xml = new XmlTextReader(stream); 23 | while (xml.Read()) 24 | { 25 | switch (xml.NodeType) 26 | { 27 | case XmlNodeType.Element: 28 | if (xml.Name.Equals("data")) 29 | { 30 | var key = xml.GetAttribute("name"); 31 | xml.Read(); 32 | xml.Read(); 33 | Lang.Add(key!.Replace('.', '/'), xml.ReadString()); 34 | } 35 | break; 36 | } 37 | } 38 | } 39 | } 40 | 41 | public string GetString(string key) 42 | { 43 | if (!Lang.TryGetValue(key, out var value)) 44 | return key; 45 | return value; 46 | } 47 | 48 | private static Dictionary Resources = new Dictionary(); 49 | 50 | public static ResourceLoader GetForCurrentView(string file) 51 | { 52 | if (!Resources.TryGetValue(file, out var loader)) 53 | { 54 | loader = new ResourceLoader(file); 55 | Resources.Add(file, loader); 56 | } 57 | return loader; 58 | } 59 | 60 | } 61 | 62 | public sealed class LocalizedString : MarkupExtension 63 | { 64 | public string Key { get; set; } = null!; 65 | 66 | public override object ProvideValue(IServiceProvider serviceProvider) 67 | { 68 | var split = Regex.Split(Key, @"\/(.*?)\/(.*)"); 69 | return ResourceLoader.GetForCurrentView(split[1]).GetString(split[2]); 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /LRReader.Avalonia/Resources/ThemeDictionary.axaml: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /LRReader.Avalonia/Services/Dispatcher.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Threading; 2 | using LRReader.Shared.Services; 3 | using System; 4 | using System.Threading.Tasks; 5 | 6 | namespace LRReader.Avalonia.Services 7 | { 8 | 9 | public class DispatcherService : IDispatcherService 10 | { 11 | private Dispatcher Dispatcher = null!; 12 | 13 | public void Init() => Dispatcher = Dispatcher.UIThread; 14 | 15 | public bool Run(Action action, int priority = 0) 16 | { 17 | action.Invoke(); 18 | return true; 19 | } 20 | 21 | public Task RunAsync(Action action) => Dispatcher.InvokeAsync(action); 22 | 23 | public Task RunAsync(Action action, int priority = 0) => Dispatcher.InvokeAsync(action); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /LRReader.Avalonia/Services/Files.cs: -------------------------------------------------------------------------------- 1 | using LRReader.Shared.Services; 2 | using System; 3 | using System.IO; 4 | using System.Threading.Tasks; 5 | 6 | namespace LRReader.Avalonia.Services 7 | { 8 | public class FilesService : IFilesService 9 | { 10 | private readonly string LocalCachePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "LRReader"); 11 | private readonly string LocalPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "LRReader"); 12 | 13 | public string LocalCache => LocalCachePath; 14 | 15 | public string Local => LocalPath; 16 | 17 | public FilesService() 18 | { 19 | Directory.CreateDirectory(LocalCachePath); 20 | Directory.CreateDirectory(LocalPath); 21 | } 22 | 23 | public Task GetFile(string path) => File.ReadAllTextAsync(path); 24 | 25 | public Task GetFileBytes(string path) => File.ReadAllBytesAsync(path); 26 | 27 | public Task StoreFile(string path, string content) => File.WriteAllTextAsync(path, content); 28 | 29 | public Task StoreFile(string path, byte[] content) => File.WriteAllBytesAsync(path, content); 30 | 31 | public Task StoreFileSafe(string path, string content) => File.WriteAllTextAsync(path, content); // TODO Implement this 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /LRReader.Avalonia/Services/ImageProcessing.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Media.Imaging; 2 | using LRReader.Shared.Services; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.IO; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace LRReader.Avalonia.Services 11 | { 12 | public class AvaloniaImageProcessingService : ImageProcessingService 13 | { 14 | public override Task ByteToBitmap(byte[]? bytes, int decodeWidth = 0, int decodeHeight = 0, bool transcode = false, object? image = default) 15 | { 16 | return Task.Run(() => 17 | { 18 | if (bytes == null) 19 | return null; 20 | using (var stream = new MemoryStream(bytes)) 21 | { 22 | return (object)new Bitmap(stream); 23 | } 24 | }); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /LRReader.Avalonia/Views/Controls/CustomTab.cs: -------------------------------------------------------------------------------- 1 | using Aura.UI.Controls; 2 | using Avalonia; 3 | using Avalonia.Styling; 4 | using FluentAvalonia.UI.Controls; 5 | using LRReader.Shared.Models; 6 | using System; 7 | 8 | namespace LRReader.Avalonia 9 | { 10 | public class CustomTab : AuraTabItem, ICustomTab, IStyleable 11 | { 12 | Type IStyleable.StyleKey => typeof(CustomTab); 13 | 14 | public Symbol CustomTabIcon 15 | { 16 | get => (Symbol)GetValue(CustomTabIconProperty)!; 17 | set => SetValue(CustomTabIconProperty, value); 18 | } 19 | 20 | public object CustomTabControl 21 | { 22 | get => GetValue(CustomTabControlProperty); 23 | set => SetValue(CustomTabControlProperty, value); 24 | } 25 | 26 | public string CustomTabId 27 | { 28 | get => GetValue(CustomTabIdProperty) as string; 29 | set => SetValue(CustomTabIdProperty, value); 30 | } 31 | 32 | public bool CustomTabIsClosable 33 | { 34 | get => (bool)GetValue(CustomTabIsClosableProperty); 35 | set => SetValue(CustomTabIsClosableProperty, value); 36 | } 37 | 38 | public virtual void Unload() 39 | { 40 | } 41 | 42 | public virtual bool BackRequested() 43 | { 44 | return false; 45 | } 46 | 47 | public static readonly AvaloniaProperty CustomTabControlProperty = AvaloniaProperty.Register("CustomTabControl"); 48 | public static readonly AvaloniaProperty CustomTabIdProperty = AvaloniaProperty.Register("CustomTabId"); 49 | public static readonly AvaloniaProperty CustomTabIconProperty = AvaloniaProperty.Register("CustomTabIcon"); 50 | public static readonly AvaloniaProperty CustomTabIsClosableProperty = AvaloniaProperty.Register("CustomTabIsClosable", true); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /LRReader.Avalonia/Views/Dialogs/GenericDialog.axaml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 |