瀏覽代碼

added download links to posts attachments

Veloe 1 年之前
父節點
當前提交
57e95f5784

+ 13 - 0
VeloeAvaloniaKemonoPartyApp/VeloeAvaloniaKemonoPartyApp.Android/AndroidOpenUrlService.cs

@@ -0,0 +1,13 @@
+using VeloeAvaloniaKemonoPartyApp.Services;
+using Xamarin.Essentials;
+
+namespace VeloeAvaloniaKemonoPartyApp.Android
+{
+    public class AndroidOpenUrlService : IOpenUrlService
+    {
+        public async void OpenUrl(string url)
+        {
+            await Browser.OpenAsync(new System.Uri(url), BrowserLaunchMode.SystemPreferred);
+        }
+    }
+}

+ 2 - 0
VeloeAvaloniaKemonoPartyApp/VeloeAvaloniaKemonoPartyApp.Android/MainActivity.cs

@@ -17,6 +17,8 @@ namespace VeloeAvaloniaKemonoPartyApp.Android
     {
         protected override AppBuilder CustomizeAppBuilder(AppBuilder builder)
         {
+            Services.RegisteredServices.OpenUrlService = new AndroidOpenUrlService();
+            
             return base.CustomizeAppBuilder(builder)
                 .WithInterFont()
                 .UseReactiveUI();

+ 3 - 2
VeloeAvaloniaKemonoPartyApp/VeloeAvaloniaKemonoPartyApp.Android/VeloeAvaloniaKemonoPartyApp.Android.csproj

@@ -9,8 +9,8 @@
     <ApplicationDisplayVersion>1.0</ApplicationDisplayVersion>
     <AndroidPackageFormat>apk</AndroidPackageFormat>
     <AndroidEnableProfiledAot>False</AndroidEnableProfiledAot>
-    <AssemblyVersion>1.0.0.74</AssemblyVersion>
-    <FileVersion>1.0.0.74</FileVersion>
+    <AssemblyVersion>1.0.0.83</AssemblyVersion>
+    <FileVersion>1.0.0.83</FileVersion>
   </PropertyGroup>
 
   <ItemGroup>
@@ -22,6 +22,7 @@
   <ItemGroup>
     <PackageReference Include="Avalonia.Android" Version="11.0.6" />
     <PackageReference Include="Xamarin.AndroidX.Core.SplashScreen" Version="1.0.1.5" />
+    <PackageReference Include="Xamarin.Essentials" Version="1.8.1" />
   </ItemGroup>
 
   <ItemGroup>

+ 0 - 1
VeloeAvaloniaKemonoPartyApp/VeloeAvaloniaKemonoPartyApp/App.axaml

@@ -12,7 +12,6 @@
     <Application.Styles>
         <FluentTheme />
 		<StyleInclude Source="avares://Avalonia.Controls.TreeDataGrid/Themes/Fluent.axaml"/>
-		<StyleInclude Source="avares://UVtools.AvaloniaControls/Controls.axaml"/>
     </Application.Styles>
 
 </Application>

+ 2 - 2
VeloeAvaloniaKemonoPartyApp/VeloeAvaloniaKemonoPartyApp/Models/Post.cs

@@ -80,12 +80,12 @@ namespace VeloeAvaloniaKemonoPartyApp.Models
 
         public string Link => $"https://kemono.su/data{Path}";
 
+        public bool IsImage => Path.EndsWith(".jpg") || Path.EndsWith(".png") || Path.EndsWith(".jpeg");
+
         private static KemonoHttpClient s_httpClient = new();
 
         private static StorageService s_storage = new();
 
-        private string CachePath => $"./Cache/{FileName}";
-
         private string FileName => Path.Split('/').Last();
 
         public async Task<Stream> LoadCoverBitmapAsync()

+ 13 - 0
VeloeAvaloniaKemonoPartyApp/VeloeAvaloniaKemonoPartyApp/Services/OpenUrlService.cs

@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace VeloeAvaloniaKemonoPartyApp.Services
+{
+    public interface IOpenUrlService
+    {
+        void OpenUrl(string url);
+    }
+}

+ 13 - 0
VeloeAvaloniaKemonoPartyApp/VeloeAvaloniaKemonoPartyApp/Services/RegisteredServices.cs

@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace VeloeAvaloniaKemonoPartyApp.Services
+{
+    public static class RegisteredServices
+    {
+        public static IOpenUrlService? OpenUrlService { get; set; }
+    }
+}

+ 3 - 3
VeloeAvaloniaKemonoPartyApp/VeloeAvaloniaKemonoPartyApp/VeloeAvaloniaKemonoPartyApp.csproj

@@ -4,8 +4,8 @@
     <Nullable>enable</Nullable>
     <LangVersion>latest</LangVersion>
     <AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
-    <AssemblyVersion>1.0.0.169</AssemblyVersion>
-    <FileVersion>1.0.0.169</FileVersion>
+    <AssemblyVersion>1.0.0.180</AssemblyVersion>
+    <FileVersion>1.0.0.180</FileVersion>
   </PropertyGroup>
 
   
@@ -15,6 +15,7 @@
 
   <ItemGroup>
     <PackageReference Include="Avalonia" Version="11.0.6" />
+    <PackageReference Include="Avalonia.Browser" Version="11.0.6" />
     <PackageReference Include="Avalonia.Controls.PanAndZoom" Version="11.0.0.2" />
     <PackageReference Include="Avalonia.Controls.TreeDataGrid" Version="11.0.2" />
     <PackageReference Include="Avalonia.HtmlRenderer" Version="11.0.0" />
@@ -29,7 +30,6 @@
       <PrivateAssets>all</PrivateAssets>
       <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
     </PackageReference>
-    <PackageReference Include="UVtools.AvaloniaControls" Version="3.0.1" />
   </ItemGroup>
 
   <ItemGroup>

+ 46 - 0
VeloeAvaloniaKemonoPartyApp/VeloeAvaloniaKemonoPartyApp/ViewModels/AttachmentViewModel.cs

@@ -0,0 +1,46 @@
+using Avalonia.Interactivity;
+using Avalonia.Browser;
+using VeloeAvaloniaKemonoPartyApp.Models;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using System;
+
+namespace VeloeAvaloniaKemonoPartyApp.ViewModels
+{
+    public class AttachmentViewModel : ViewModelBase
+    {
+        private Attachment _attachment;
+        
+        public AttachmentViewModel(Attachment attachment)
+        {
+            _attachment = attachment;
+        }
+        public string Name => _attachment.Name;
+
+        public async void DownloadAttachment()
+        {
+            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+            {
+                //https://stackoverflow.com/a/2796367/241446
+                using var proc = new Process { StartInfo = { UseShellExecute = true, FileName = _attachment.Link } };
+                proc.Start();
+
+                return;
+            }
+
+            if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
+            {
+                Process.Start("x-www-browser", _attachment.Link);
+                return;
+            }
+
+            if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
+            {
+                Process.Start("open", _attachment.Link);
+                return;
+            }
+
+            Services.RegisteredServices.OpenUrlService?.OpenUrl(_attachment.Link);
+        }
+    }
+}

+ 0 - 2
VeloeAvaloniaKemonoPartyApp/VeloeAvaloniaKemonoPartyApp/ViewModels/ImageZoomViewModel.cs

@@ -36,8 +36,6 @@ namespace VeloeAvaloniaKemonoPartyApp.ViewModels
             private set => this.RaiseAndSetIfChanged(ref _cover, value);
         }
 
-        public UVtools.AvaloniaControls.AdvancedImageBox.SizeModes SizeModeValue => UVtools.AvaloniaControls.AdvancedImageBox.SizeModes.Fit;
-
         public async Task LoadAvatar()
         {
             await using (var imageStream = await _attachment.LoadCoverBitmapAsync())

+ 1 - 1
VeloeAvaloniaKemonoPartyApp/VeloeAvaloniaKemonoPartyApp/ViewModels/PostImageViewModel.cs

@@ -53,7 +53,7 @@ namespace VeloeAvaloniaKemonoPartyApp.ViewModels
         public async Task OnImageClick(object sender, RoutedEventArgs e)
         {
             var vm = new ImageZoomViewModel(_attachment);
-            _dialogService.Show(null, vm);
+            _dialogService.Show((_dialogService.DialogManager as HanumanInstitute.MvvmDialogs.Avalonia.DialogManager).NavigationManager.CurrentViewModel, vm);
         }
 
     }

+ 20 - 2
VeloeAvaloniaKemonoPartyApp/VeloeAvaloniaKemonoPartyApp/ViewModels/PostViewModel.cs

@@ -1,5 +1,6 @@
 using HanumanInstitute.MvvmDialogs;
 using System.Collections.ObjectModel;
+using System.Text.RegularExpressions;
 using VeloeAvaloniaKemonoPartyApp.Models;
 
 namespace VeloeAvaloniaKemonoPartyApp.ViewModels
@@ -20,18 +21,35 @@ namespace VeloeAvaloniaKemonoPartyApp.ViewModels
             {
                 if (attachment is null) continue;
 
-                if (attachment.Path.EndsWith(".jpg") || attachment.Path.EndsWith(".png") || attachment.Path.EndsWith(".jpeg"))
+                if (attachment.IsImage)
                 {
                     Images.Add(new PostImageViewModel(_dialogService,attachment));
                 }
+
+                Attachments.Add(new AttachmentViewModel(attachment));
             }
         }
 
         public ObservableCollection<PostImageViewModel> Images { get; } = new();
+
+        public ObservableCollection<AttachmentViewModel> Attachments { get; } = new();
+
+        public AttachmentViewModel SelectedAttachment { get; set; }
         
         public bool IsImagesEmpty => Images.Count == 0;
 
-        public string Content => _post.Content;
+        public string Content => Regex.Replace(_post.Content, "<[^>]*>|&lt|&gt|&apos|&amp|&quot", (Match m) =>
+            m.Value switch
+            {
+                "&lt" => "<",
+                "&gt" => ">",
+                "&apos" => "'",
+                "&amp" => "&",
+                "&quot" => "\"",
+                "</p>" => "\n",
+                _ => ""
+            }
+        );
 
         public string Title => _post.Title;
 

+ 28 - 0
VeloeAvaloniaKemonoPartyApp/VeloeAvaloniaKemonoPartyApp/Views/AttachmentView.axaml

@@ -0,0 +1,28 @@
+<UserControl xmlns="https://github.com/avaloniaui"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+			 xmlns:m="using:VeloeAvaloniaKemonoPartyApp.Models"
+			 xmlns:vm="clr-namespace:VeloeAvaloniaKemonoPartyApp.ViewModels"
+             mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
+             x:Class="VeloeAvaloniaKemonoPartyApp.Views.AttachmentView"
+			 x:DataType="vm:AttachmentViewModel">
+	<UserControl.Styles>
+		<Style Selector="Button.hyperlink">
+			<Setter Property="Template">
+				<ControlTemplate>
+					<TextBlock Text="{TemplateBinding Content}" Foreground="{StaticResource SystemAccentColor}" TextDecorations="Underline">
+						<TextBlock.Styles>
+							<Style Selector="TextBlock:pointerover">
+								<Setter Property="Foreground" Value="{StaticResource SystemAccentColorLight1}"/>
+							</Style>
+						</TextBlock.Styles>
+					</TextBlock>
+				</ControlTemplate>
+			</Setter>
+			<Setter Property="Background" Value="Transparent"/>
+			<Setter Property="BorderThickness" Value="0"/>
+		</Style>
+	</UserControl.Styles>
+	<Button Content="{Binding Name}" HorizontalContentAlignment="Left" Command="{Binding DownloadAttachment}" Classes="hyperlink"/>
+</UserControl>

+ 13 - 0
VeloeAvaloniaKemonoPartyApp/VeloeAvaloniaKemonoPartyApp/Views/AttachmentView.axaml.cs

@@ -0,0 +1,13 @@
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Markup.Xaml;
+
+namespace VeloeAvaloniaKemonoPartyApp.Views;
+
+public partial class AttachmentView : UserControl
+{
+    public AttachmentView()
+    {
+        InitializeComponent();
+    }
+}

+ 10 - 1
VeloeAvaloniaKemonoPartyApp/VeloeAvaloniaKemonoPartyApp/Views/PostView.axaml

@@ -18,7 +18,16 @@
 				</ItemsPanelTemplate>
 			</ItemsControl.ItemsPanel>
 		</ItemsControl>
-		<av:HtmlPanel HorizontalAlignment="Center" Text="{Binding Content}" Background="MintCream"/>
+		<TextBlock Text="{Binding Content}" TextWrapping="Wrap"/>
+		<ListBox ItemsSource="{Binding Attachments}" 
+				 SelectionMode="Single"
+				 Background="Transparent">
+			<ListBox.ItemsPanel>
+				<ItemsPanelTemplate>
+					<StackPanel/>
+				</ItemsPanelTemplate>
+			</ListBox.ItemsPanel>
+		</ListBox>
 		<TextBlock HorizontalAlignment="Right" FontSize="10" FontStyle="Italic" Text="{Binding Date}"/>
 	</StackPanel>
 </UserControl>