mirror of
https://github.com/QL-Win/QuickLook.git
synced 2025-09-10 17:29:08 +00:00
Support .hap and .hap.1
This commit is contained in:
313
QuickLook.Plugin/QuickLook.Plugin.AppViewer/HapInfoPanel.xaml
Normal file
313
QuickLook.Plugin/QuickLook.Plugin.AppViewer/HapInfoPanel.xaml
Normal file
@@ -0,0 +1,313 @@
|
||||
<UserControl x:Class="QuickLook.Plugin.AppViewer.HapInfoPanel"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:QuickLook.Plugin.AppViewer"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
FontSize="14"
|
||||
UseLayoutRounding="True"
|
||||
mc:Ignorable="d">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="15" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="150" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid Grid.Row="1" Grid.Column="0">
|
||||
<Image x:Name="background"
|
||||
Width="120"
|
||||
Height="120"
|
||||
Margin="8"
|
||||
VerticalAlignment="Top"
|
||||
Opacity="0"
|
||||
RenderOptions.BitmapScalingMode="HighQuality"
|
||||
SnapsToDevicePixels="True"
|
||||
Stretch="Fill"
|
||||
UseLayoutRounding="True">
|
||||
<Image.Style>
|
||||
<Style TargetType="{x:Type Image}">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding Source, ElementName=background}" Value="{x:Null}">
|
||||
<DataTrigger.ExitActions>
|
||||
<BeginStoryboard>
|
||||
<Storyboard>
|
||||
<DoubleAnimation BeginTime="0:0:0"
|
||||
Storyboard.TargetProperty="Opacity"
|
||||
From="0"
|
||||
To="1"
|
||||
Duration="0:0:0.05" />
|
||||
</Storyboard>
|
||||
</BeginStoryboard>
|
||||
</DataTrigger.ExitActions>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Image.Style>
|
||||
</Image>
|
||||
<Image x:Name="foreground"
|
||||
Width="120"
|
||||
Height="120"
|
||||
Margin="8"
|
||||
VerticalAlignment="Top"
|
||||
Opacity="0"
|
||||
RenderOptions.BitmapScalingMode="HighQuality"
|
||||
SnapsToDevicePixels="True"
|
||||
Stretch="Fill"
|
||||
UseLayoutRounding="True">
|
||||
<Image.Style>
|
||||
<Style TargetType="{x:Type Image}">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding Source, ElementName=foreground}" Value="{x:Null}">
|
||||
<DataTrigger.ExitActions>
|
||||
<BeginStoryboard>
|
||||
<Storyboard>
|
||||
<DoubleAnimation BeginTime="0:0:0"
|
||||
Storyboard.TargetProperty="Opacity"
|
||||
From="0"
|
||||
To="1"
|
||||
Duration="0:0:0.05" />
|
||||
</Storyboard>
|
||||
</BeginStoryboard>
|
||||
</DataTrigger.ExitActions>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Image.Style>
|
||||
</Image>
|
||||
</Grid>
|
||||
<Grid Grid.Row="1" Grid.Column="1">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="5" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="10" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="10" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="10" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid Grid.Row="1"
|
||||
Grid.Column="1"
|
||||
Grid.ColumnSpan="2">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Grid.Column="0"
|
||||
MaxHeight="60"
|
||||
Padding="3"
|
||||
FontSize="19"
|
||||
FontWeight="SemiBold"
|
||||
LineHeight="25"
|
||||
TextTrimming="CharacterEllipsis"
|
||||
TextWrapping="Wrap">
|
||||
<TextBlock.Inlines>
|
||||
<Run x:Name="filename" Text="FilenameFilenameFilenameFilenameFilenameFilenameFilenameFilenameFilenameFilename.ext" />
|
||||
</TextBlock.Inlines>
|
||||
</TextBlock>
|
||||
</Grid>
|
||||
<!-- Application Name -->
|
||||
<TextBlock x:Name="applicationNameTitle"
|
||||
Grid.Row="3"
|
||||
Grid.Column="1"
|
||||
Padding="3"
|
||||
Foreground="{DynamicResource WindowTextForegroundAlternative}"
|
||||
Text="Application Name"
|
||||
Visibility="Collapsed" />
|
||||
<TextBlock x:Name="applicationName"
|
||||
Grid.Row="3"
|
||||
Grid.Column="2"
|
||||
Margin="8,0,0,0"
|
||||
Padding="3"
|
||||
Foreground="{DynamicResource WindowTextForegroundAlternative}"
|
||||
Text="Searching..."
|
||||
TextTrimming="CharacterEllipsis"
|
||||
TextWrapping="Wrap"
|
||||
Visibility="Collapsed" />
|
||||
<!-- Bundle Name -->
|
||||
<TextBlock x:Name="bundleNameTitle"
|
||||
Grid.Row="4"
|
||||
Grid.Column="1"
|
||||
Padding="3"
|
||||
Foreground="{DynamicResource WindowTextForegroundAlternative}"
|
||||
Text="Bundle Name" />
|
||||
<TextBlock x:Name="bundleName"
|
||||
Grid.Row="4"
|
||||
Grid.Column="2"
|
||||
Margin="8,0,0,0"
|
||||
Padding="3"
|
||||
Foreground="{DynamicResource WindowTextForegroundAlternative}"
|
||||
Text="Searching..."
|
||||
TextTrimming="CharacterEllipsis"
|
||||
TextWrapping="Wrap" />
|
||||
<!-- Version Name -->
|
||||
<TextBlock x:Name="versionNameTitle"
|
||||
Grid.Row="5"
|
||||
Grid.Column="1"
|
||||
Padding="3"
|
||||
Foreground="{DynamicResource WindowTextForegroundAlternative}"
|
||||
Text="Version" />
|
||||
<TextBlock x:Name="versionName"
|
||||
Grid.Row="5"
|
||||
Grid.Column="2"
|
||||
Margin="8,0,0,0"
|
||||
Padding="3"
|
||||
Foreground="{DynamicResource WindowTextForegroundAlternative}"
|
||||
Text="Searching..."
|
||||
TextTrimming="CharacterEllipsis"
|
||||
TextWrapping="Wrap" />
|
||||
<!-- Version Code -->
|
||||
<TextBlock x:Name="versionCodeTitle"
|
||||
Grid.Row="6"
|
||||
Grid.Column="1"
|
||||
Padding="3"
|
||||
Foreground="{DynamicResource WindowTextForegroundAlternative}"
|
||||
Text="Version Code" />
|
||||
<TextBlock x:Name="versionCode"
|
||||
Grid.Row="6"
|
||||
Grid.Column="2"
|
||||
Margin="8,0,0,0"
|
||||
Padding="3"
|
||||
Foreground="{DynamicResource WindowTextForegroundAlternative}"
|
||||
Text="Searching..."
|
||||
TextTrimming="CharacterEllipsis"
|
||||
TextWrapping="Wrap" />
|
||||
<!-- Device Types -->
|
||||
<TextBlock x:Name="deviceTypesTitle"
|
||||
Grid.Row="7"
|
||||
Grid.Column="1"
|
||||
Padding="3"
|
||||
Foreground="{DynamicResource WindowTextForegroundAlternative}"
|
||||
Text="Device Types" />
|
||||
<TextBlock x:Name="deviceTypes"
|
||||
Grid.Row="7"
|
||||
Grid.Column="2"
|
||||
Margin="8,0,0,0"
|
||||
Padding="3"
|
||||
Foreground="{DynamicResource WindowTextForegroundAlternative}"
|
||||
Text="Searching..."
|
||||
TextTrimming="CharacterEllipsis"
|
||||
TextWrapping="Wrap" />
|
||||
<!-- CompileSdkVersion -->
|
||||
<TextBlock x:Name="compileSdkVersionTitle"
|
||||
Grid.Row="8"
|
||||
Grid.Column="1"
|
||||
Padding="3"
|
||||
Foreground="{DynamicResource WindowTextForegroundAlternative}"
|
||||
Text="CompileSdkVersion" />
|
||||
<TextBlock x:Name="compileSdkVersion"
|
||||
Grid.Row="8"
|
||||
Grid.Column="2"
|
||||
Margin="8,0,0,0"
|
||||
Padding="3"
|
||||
Foreground="{DynamicResource WindowTextForegroundAlternative}"
|
||||
Text="Searching..."
|
||||
TextTrimming="CharacterEllipsis"
|
||||
TextWrapping="Wrap" />
|
||||
<!-- MinAPIVersion -->
|
||||
<TextBlock x:Name="minimumAPIVersionTitle"
|
||||
Grid.Row="9"
|
||||
Grid.Column="1"
|
||||
Padding="3"
|
||||
Foreground="{DynamicResource WindowTextForegroundAlternative}"
|
||||
Text="MinimumAPIVersion" />
|
||||
<TextBlock x:Name="minimumAPIVersion"
|
||||
Grid.Row="9"
|
||||
Grid.Column="2"
|
||||
Margin="8,0,0,0"
|
||||
Padding="3"
|
||||
Foreground="{DynamicResource WindowTextForegroundAlternative}"
|
||||
Text="Searching..."
|
||||
TextTrimming="CharacterEllipsis"
|
||||
TextWrapping="Wrap" />
|
||||
<!-- TargetAPIVersion -->
|
||||
<TextBlock x:Name="targetAPIVersionTitle"
|
||||
Grid.Row="10"
|
||||
Grid.Column="1"
|
||||
Padding="3"
|
||||
Foreground="{DynamicResource WindowTextForegroundAlternative}"
|
||||
Text="TargetAPIVersion" />
|
||||
<TextBlock x:Name="targetAPIVersion"
|
||||
Grid.Row="10"
|
||||
Grid.Column="2"
|
||||
Margin="8,0,0,0"
|
||||
Padding="3"
|
||||
Foreground="{DynamicResource WindowTextForegroundAlternative}"
|
||||
Text="Searching..."
|
||||
TextTrimming="CharacterEllipsis"
|
||||
TextWrapping="Wrap" />
|
||||
<!-- Total Size -->
|
||||
<TextBlock x:Name="totalSizeTitle"
|
||||
Grid.Row="11"
|
||||
Grid.Column="1"
|
||||
Padding="3"
|
||||
Foreground="{DynamicResource WindowTextForegroundAlternative}"
|
||||
Text="Total Size" />
|
||||
<TextBlock x:Name="totalSize"
|
||||
Grid.Row="11"
|
||||
Grid.Column="2"
|
||||
Margin="8,0,0,0"
|
||||
Padding="3"
|
||||
Foreground="{DynamicResource WindowTextForegroundAlternative}"
|
||||
Text="Calculating size..." />
|
||||
<!-- Last Modified -->
|
||||
<TextBlock x:Name="modDateTitle"
|
||||
Grid.Row="12"
|
||||
Grid.Column="1"
|
||||
Padding="3"
|
||||
Foreground="{DynamicResource WindowTextForegroundAlternative}"
|
||||
Text="Last Modified" />
|
||||
<TextBlock x:Name="modDate"
|
||||
Grid.Row="12"
|
||||
Grid.Column="2"
|
||||
Margin="8,0,0,0"
|
||||
Padding="3"
|
||||
Foreground="{DynamicResource WindowTextForegroundAlternative}"
|
||||
Text="Searching..."
|
||||
TextTrimming="CharacterEllipsis" />
|
||||
<!-- Permissions -->
|
||||
<GroupBox x:Name="permissionsGroupBox"
|
||||
Grid.Row="13"
|
||||
Grid.Column="1"
|
||||
Grid.ColumnSpan="2"
|
||||
Margin="0,0,16,16"
|
||||
BorderThickness="0.4"
|
||||
Header="Capabilities">
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
||||
<ScrollViewer.Resources>
|
||||
<Style TargetType="{x:Type TextBox}">
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource TextFillColorPrimaryBrush}" />
|
||||
<Setter Property="BorderThickness" Value="0" />
|
||||
<Setter Property="BorderBrush" Value="Transparent" />
|
||||
</Style>
|
||||
</ScrollViewer.Resources>
|
||||
<ItemsControl x:Name="permissions">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<TextBox Margin="8,3,16,3"
|
||||
IsReadOnly="True"
|
||||
Text="{Binding ., Mode=OneTime}" />
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</ScrollViewer>
|
||||
</GroupBox>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</UserControl>
|
132
QuickLook.Plugin/QuickLook.Plugin.AppViewer/HapInfoPanel.xaml.cs
Normal file
132
QuickLook.Plugin/QuickLook.Plugin.AppViewer/HapInfoPanel.xaml.cs
Normal file
@@ -0,0 +1,132 @@
|
||||
// Copyright © 2017-2025 QL-Win Contributors
|
||||
//
|
||||
// This file is part of QuickLook program.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
using QuickLook.Common.ExtensionMethods;
|
||||
using QuickLook.Common.Helpers;
|
||||
using QuickLook.Common.Plugin;
|
||||
using QuickLook.Plugin.AppViewer.HapPackageParser;
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media.Imaging;
|
||||
|
||||
namespace QuickLook.Plugin.AppViewer;
|
||||
|
||||
public partial class HapInfoPanel : UserControl, IAppInfoPanel
|
||||
{
|
||||
private ContextObject _context;
|
||||
|
||||
public HapInfoPanel(ContextObject context)
|
||||
{
|
||||
_context = context;
|
||||
|
||||
DataContext = this;
|
||||
InitializeComponent();
|
||||
|
||||
string translationFile = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Translations.config");
|
||||
applicationNameTitle.Text = TranslationHelper.Get("APP_NAME", translationFile);
|
||||
versionNameTitle.Text = TranslationHelper.Get("APP_VERSION_NAME", translationFile);
|
||||
versionCodeTitle.Text = TranslationHelper.Get("APP_VERSION_CODE", translationFile);
|
||||
bundleNameTitle.Text = TranslationHelper.Get("BUNDLE_NAME", translationFile);
|
||||
minimumAPIVersionTitle.Text = TranslationHelper.Get("APP_MIN_API_VERSION", translationFile);
|
||||
targetAPIVersionTitle.Text = TranslationHelper.Get("APP_TARGET_API_VERSION", translationFile);
|
||||
compileSdkVersionTitle.Text = TranslationHelper.Get("COMPILE_SDK_VERSION", translationFile);
|
||||
totalSizeTitle.Text = TranslationHelper.Get("TOTAL_SIZE", translationFile);
|
||||
modDateTitle.Text = TranslationHelper.Get("LAST_MODIFIED", translationFile);
|
||||
permissionsGroupBox.Header = TranslationHelper.Get("PERMISSIONS", translationFile);
|
||||
}
|
||||
|
||||
public void DisplayInfo(string path)
|
||||
{
|
||||
var name = Path.GetFileName(path);
|
||||
filename.Text = string.IsNullOrEmpty(name) ? path : name;
|
||||
|
||||
_ = Task.Run(() =>
|
||||
{
|
||||
if (File.Exists(path))
|
||||
{
|
||||
var size = new FileInfo(path).Length;
|
||||
HapInfo hapInfo = HapParser.Parse(path);
|
||||
var last = File.GetLastWriteTime(path);
|
||||
|
||||
Dispatcher.Invoke(() =>
|
||||
{
|
||||
applicationName.Text = hapInfo.Label;
|
||||
versionName.Text = hapInfo.VersionName;
|
||||
versionCode.Text = hapInfo.VersionCode;
|
||||
bundleName.Text = hapInfo.BundleName;
|
||||
deviceTypes.Text = string.Join(", ", hapInfo.DeviceTypes);
|
||||
minimumAPIVersion.Text = hapInfo.MinAPIVersion;
|
||||
targetAPIVersion.Text = hapInfo.TargetAPIVersion;
|
||||
compileSdkVersion.Text = $"{hapInfo.CompileSdkType} {hapInfo.CompileSdkVersion}";
|
||||
totalSize.Text = size.ToPrettySize(2);
|
||||
modDate.Text = last.ToString(CultureInfo.CurrentCulture);
|
||||
permissions.ItemsSource = hapInfo.RequestPermissions;
|
||||
|
||||
if (hapInfo.HasIcon)
|
||||
{
|
||||
if (hapInfo.Logo?.Length > 0)
|
||||
{
|
||||
using var stream = new MemoryStream(hapInfo.Logo);
|
||||
var icon = new BitmapImage();
|
||||
icon.BeginInit();
|
||||
icon.CacheOption = BitmapCacheOption.OnLoad;
|
||||
icon.StreamSource = stream;
|
||||
icon.EndInit();
|
||||
icon.Freeze();
|
||||
background.Source = null;
|
||||
foreground.Source = icon;
|
||||
}
|
||||
else if (hapInfo.HasLayeredIcon)
|
||||
{
|
||||
{
|
||||
using var stream = new MemoryStream(hapInfo.AppIconBackground);
|
||||
var icon = new BitmapImage();
|
||||
icon.BeginInit();
|
||||
icon.CacheOption = BitmapCacheOption.OnLoad;
|
||||
icon.StreamSource = stream;
|
||||
icon.EndInit();
|
||||
icon.Freeze();
|
||||
background.Source = icon;
|
||||
}
|
||||
{
|
||||
using var stream = new MemoryStream(hapInfo.AppIconForeground);
|
||||
var icon = new BitmapImage();
|
||||
icon.BeginInit();
|
||||
icon.CacheOption = BitmapCacheOption.OnLoad;
|
||||
icon.StreamSource = stream;
|
||||
icon.EndInit();
|
||||
icon.Freeze();
|
||||
foreground.Source = icon;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
background.Source = null;
|
||||
foreground.Source = new BitmapImage(new Uri("pack://application:,,,/QuickLook.Plugin.AppViewer;component/Resources/harmonyos.png"));
|
||||
}
|
||||
|
||||
_context.IsBusy = false;
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@@ -0,0 +1,55 @@
|
||||
// Copyright © 2017-2025 QL-Win Contributors
|
||||
//
|
||||
// This file is part of QuickLook program.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
namespace QuickLook.Plugin.AppViewer.HapPackageParser;
|
||||
|
||||
public sealed class HapInfo
|
||||
{
|
||||
public string Label { get; set; }
|
||||
|
||||
public string Icon { get; set; }
|
||||
|
||||
public byte[] Logo { get; set; }
|
||||
|
||||
public byte[] AppIconForeground { get; set; }
|
||||
|
||||
public byte[] AppIconBackground { get; set; }
|
||||
|
||||
public bool HasIcon { get; set; } = false;
|
||||
|
||||
public bool HasLayeredIcon { get; set; } = false;
|
||||
|
||||
public string VersionName { get; set; }
|
||||
|
||||
public string VersionCode { get; set; }
|
||||
|
||||
public string CompileSdkType { get; set; }
|
||||
|
||||
public string CompileSdkVersion { get; set; }
|
||||
|
||||
public string MinAPIVersion { get; set; }
|
||||
|
||||
public string TargetAPIVersion { get; set; }
|
||||
|
||||
public string BundleName { get; set; }
|
||||
|
||||
public bool Debug { get; set; }
|
||||
|
||||
public string[] RequestPermissions { get; set; } = [];
|
||||
|
||||
public string[] DeviceTypes { get; set; } = [];
|
||||
}
|
@@ -0,0 +1,152 @@
|
||||
// Copyright © 2017-2025 QL-Win Contributors
|
||||
//
|
||||
// This file is part of QuickLook program.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
using ICSharpCode.SharpZipLib.Zip;
|
||||
using Newtonsoft.Json;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace QuickLook.Plugin.AppViewer.HapPackageParser;
|
||||
|
||||
internal static class HapParser
|
||||
{
|
||||
public static HapInfo Parse(string path)
|
||||
{
|
||||
using var zip = new ZipFile(path);
|
||||
ZipEntry entry = zip.GetEntry("module.json");
|
||||
|
||||
if (entry != null)
|
||||
{
|
||||
using var stream = zip.GetInputStream(entry);
|
||||
using var reader = new StreamReader(stream, Encoding.UTF8);
|
||||
string content = reader.ReadToEnd();
|
||||
var dict = JsonConvert.DeserializeObject<Dictionary<string, object>>(content);
|
||||
|
||||
if (dict == null) return null;
|
||||
|
||||
var info = new HapInfo();
|
||||
|
||||
if (dict.ContainsKey("app"))
|
||||
{
|
||||
dynamic app = dict["app"];
|
||||
|
||||
if (app.ContainsKey("label")) info.Label = app["label"].ToString();
|
||||
if (app.ContainsKey("icon")) info.Icon = app["icon"].ToString();
|
||||
if (app.ContainsKey("versionName")) info.VersionName = app["versionName"].ToString();
|
||||
if (app.ContainsKey("versionCode")) info.VersionCode = app["versionCode"].ToString();
|
||||
if (app.ContainsKey("compileSdkType")) info.CompileSdkType = app["compileSdkType"].ToString();
|
||||
if (app.ContainsKey("compileSdkVersion")) info.CompileSdkVersion = app["compileSdkVersion"].ToString();
|
||||
if (app.ContainsKey("minAPIVersion")) info.MinAPIVersion = app["minAPIVersion"].ToString();
|
||||
if (app.ContainsKey("targetAPIVersion")) info.TargetAPIVersion = app["targetAPIVersion"].ToString();
|
||||
if (app.ContainsKey("bundleName")) info.BundleName = app["bundleName"].ToString();
|
||||
if (app.ContainsKey("debug")) info.Debug = (bool)app["debug"];
|
||||
}
|
||||
|
||||
{
|
||||
if (info.Icon == "$media:layered_image")
|
||||
{
|
||||
ZipEntry foreground = zip.GetEntry("resources/base/media/foreground.png");
|
||||
ZipEntry background = zip.GetEntry("resources/base/media/background.png");
|
||||
|
||||
if (foreground != null && background != null)
|
||||
{
|
||||
{
|
||||
using var s = new BinaryReader(zip.GetInputStream(foreground));
|
||||
info.AppIconForeground = s.ReadBytes((int)foreground.Size);
|
||||
}
|
||||
{
|
||||
using var s = new BinaryReader(zip.GetInputStream(background));
|
||||
info.AppIconBackground = s.ReadBytes((int)background.Size);
|
||||
}
|
||||
|
||||
info.HasLayeredIcon = true;
|
||||
info.HasIcon = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
info.HasLayeredIcon = false;
|
||||
info.HasIcon = false;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
ZipEntry appIcon = zip.GetEntry("resources/base/media/app_icon.png");
|
||||
|
||||
if (appIcon != null)
|
||||
{
|
||||
using var s = new BinaryReader(zip.GetInputStream(appIcon));
|
||||
info.Logo = s.ReadBytes((int)appIcon.Size);
|
||||
|
||||
info.HasLayeredIcon = false;
|
||||
info.HasIcon = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!info.HasIcon)
|
||||
{
|
||||
ZipEntry icon = zip.GetEntry("resources/base/media/icon.png");
|
||||
|
||||
if (icon != null)
|
||||
{
|
||||
using var s = new BinaryReader(zip.GetInputStream(icon));
|
||||
info.Logo = s.ReadBytes((int)icon.Size);
|
||||
|
||||
info.HasLayeredIcon = false;
|
||||
info.HasIcon = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dict.ContainsKey("module"))
|
||||
{
|
||||
dynamic module = dict["module"];
|
||||
|
||||
{
|
||||
List<string> requestPermissions = [];
|
||||
|
||||
if (module.ContainsKey("requestPermissions"))
|
||||
{
|
||||
foreach (dynamic requestPermission in module["requestPermissions"])
|
||||
{
|
||||
if (requestPermission.ContainsKey("name"))
|
||||
{
|
||||
requestPermissions.Add(requestPermission["name"].ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
info.RequestPermissions = [.. requestPermissions];
|
||||
}
|
||||
{
|
||||
List<string> deviceTypes = [];
|
||||
|
||||
if (module.ContainsKey("deviceTypes"))
|
||||
{
|
||||
foreach (dynamic deviceType in module["deviceTypes"])
|
||||
{
|
||||
deviceTypes.Add(deviceType.ToString());
|
||||
}
|
||||
}
|
||||
info.DeviceTypes = [.. deviceTypes];
|
||||
}
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
@@ -44,7 +44,7 @@ public class Plugin : IViewer
|
||||
".ipa", // iOS IPA
|
||||
|
||||
// HarmonyOS
|
||||
//".hap", // HarmonyOS Package
|
||||
".hap", ".hap.1", // HarmonyOS Package
|
||||
//".har", // HarmonyOS Archive
|
||||
|
||||
// Others
|
||||
@@ -71,6 +71,7 @@ public class Plugin : IViewer
|
||||
{
|
||||
".apk" => new Size { Width = 560, Height = 500 },
|
||||
".ipa" => new Size { Width = 560, Height = 500 },
|
||||
".hap" => new Size { Width = 560, Height = 500 },
|
||||
".msi" => new Size { Width = 520, Height = 230 },
|
||||
".msix" or ".msixbundle" or ".appx" or ".appxbundle" => new Size { Width = 560, Height = 328 },
|
||||
".wgt" or ".wgtu" => new Size { Width = 600, Height = 328 },
|
||||
@@ -85,6 +86,7 @@ public class Plugin : IViewer
|
||||
{
|
||||
".apk" => new ApkInfoPanel(context),
|
||||
".ipa" => new IpaInfoPanel(context),
|
||||
".hap" => new HapInfoPanel(context),
|
||||
".msi" => new MsiInfoPanel(context),
|
||||
".msix" or ".msixbundle" or ".appx" or ".appxbundle" => new AppxInfoPanel(context),
|
||||
".wgt" or ".wgtu" => new WgtInfoPanel(context),
|
||||
|
@@ -64,12 +64,6 @@
|
||||
<Resource Include="Resources\*.png" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Remove="ApkPackageParser\ApkManifest.cs" />
|
||||
<Compile Remove="ApkPackageParser\ApkReader.cs" />
|
||||
<Compile Remove="ApkPackageParser\ApkResourceFinder.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="..\..\GitVersion.cs">
|
||||
<Link>Properties\GitVersion.cs</Link>
|
||||
|
Binary file not shown.
After Width: | Height: | Size: 20 KiB |
@@ -19,6 +19,11 @@
|
||||
<APP_MIN_OS_VERSION>Minimum OS Version</APP_MIN_OS_VERSION>
|
||||
<APP_TARGET_OS_VERSION>Target OS Version</APP_TARGET_OS_VERSION>
|
||||
<DEVICE_FAMILY>Device Family</DEVICE_FAMILY>
|
||||
<BUNDLE_NAME>Bundle Name</BUNDLE_NAME>
|
||||
<DEVICE_TYPES>Device Types</DEVICE_TYPES>
|
||||
<APP_MIN_API_VERSION>Minimum API Version</APP_MIN_API_VERSION>
|
||||
<APP_TARGET_API_VERSION>Target API Version</APP_TARGET_API_VERSION>
|
||||
<COMPILE_SDK_VERSION>Compile SDK Version</COMPILE_SDK_VERSION>
|
||||
</en>
|
||||
<pt-BR>
|
||||
<PRODUCT_VERSION>Versão do produto</PRODUCT_VERSION>
|
||||
@@ -38,6 +43,11 @@
|
||||
<APP_MIN_OS_VERSION>Versão mínima do sistema operacional</APP_MIN_OS_VERSION>
|
||||
<APP_TARGET_OS_VERSION>Versão alvo do sistema operacional</APP_TARGET_OS_VERSION>
|
||||
<DEVICE_FAMILY>Família de dispositivos</DEVICE_FAMILY>
|
||||
<BUNDLE_NAME>Nome do pacote</BUNDLE_NAME>
|
||||
<DEVICE_TYPES>Tipos de dispositivo</DEVICE_TYPES>
|
||||
<APP_MIN_API_VERSION>Versão mínima do API</APP_MIN_API_VERSION>
|
||||
<APP_TARGET_API_VERSION>Versão mínima do API</APP_TARGET_API_VERSION>
|
||||
<COMPILE_SDK_VERSION>Versão do SDK de compilação</COMPILE_SDK_VERSION>
|
||||
</pt-BR>
|
||||
<zh-CN>
|
||||
<PRODUCT_VERSION>产品版本</PRODUCT_VERSION>
|
||||
@@ -57,6 +67,11 @@
|
||||
<APP_MIN_OS_VERSION>最低系统版本</APP_MIN_OS_VERSION>
|
||||
<APP_TARGET_OS_VERSION>目标系统版本</APP_TARGET_OS_VERSION>
|
||||
<DEVICE_FAMILY>设备支持</DEVICE_FAMILY>
|
||||
<BUNDLE_NAME>包名</BUNDLE_NAME>
|
||||
<DEVICE_TYPES>设备类型</DEVICE_TYPES>
|
||||
<APP_MIN_API_VERSION>最低支持 API 版本</APP_MIN_API_VERSION>
|
||||
<APP_TARGET_API_VERSION>目标 API 版本</APP_TARGET_API_VERSION>
|
||||
<COMPILE_SDK_VERSION>编译 SDK 版本</COMPILE_SDK_VERSION>
|
||||
</zh-CN>
|
||||
<zh-TW>
|
||||
<PRODUCT_VERSION>產品版本</PRODUCT_VERSION>
|
||||
@@ -76,6 +91,11 @@
|
||||
<APP_MIN_OS_VERSION>最低作業系統版本</APP_MIN_OS_VERSION>
|
||||
<APP_TARGET_OS_VERSION>目標作業系統版本</APP_TARGET_OS_VERSION>
|
||||
<DEVICE_FAMILY>裝置支援</DEVICE_FAMILY>
|
||||
<BUNDLE_NAME>套件名稱</BUNDLE_NAME>
|
||||
<DEVICE_TYPES>裝置類型</DEVICE_TYPES>
|
||||
<APP_MIN_API_VERSION>最低支援 API 版本</APP_MIN_API_VERSION>
|
||||
<APP_TARGET_API_VERSION>目標 API 版本</APP_TARGET_API_VERSION>
|
||||
<COMPILE_SDK_VERSION>編譯 SDK 版本</COMPILE_SDK_VERSION>
|
||||
</zh-TW>
|
||||
<ja>
|
||||
<PRODUCT_VERSION>製品バージョン</PRODUCT_VERSION>
|
||||
@@ -95,5 +115,10 @@
|
||||
<APP_MIN_OS_VERSION>最小OSバージョン</APP_MIN_OS_VERSION>
|
||||
<APP_TARGET_OS_VERSION>ターゲットOSバージョン</APP_TARGET_OS_VERSION>
|
||||
<DEVICE_FAMILY>対応デバイス</DEVICE_FAMILY>
|
||||
<BUNDLE_NAME>バンドル名</BUNDLE_NAME>
|
||||
<DEVICE_TYPES>デバイスタイプ</DEVICE_TYPES>
|
||||
<APP_MIN_API_VERSION>最小APIバージョン</APP_MIN_API_VERSION>
|
||||
<APP_TARGET_API_VERSION>ターゲットAPIバージョン</APP_TARGET_API_VERSION>
|
||||
<COMPILE_SDK_VERSION>コンパイルSDKバージョン</COMPILE_SDK_VERSION>
|
||||
</ja>
|
||||
</Translations>
|
||||
|
@@ -42,25 +42,25 @@ internal static class WgtParser
|
||||
|
||||
if (dict == null) return null;
|
||||
|
||||
var wgtInfo = new WgtInfo();
|
||||
var info = new WgtInfo();
|
||||
|
||||
if (dict.ContainsKey("@platforms"))
|
||||
{
|
||||
wgtInfo.Platforms = ((JArray)dict["@platforms"]).Values().Select(v => v.ToString()).ToArray();
|
||||
info.Platforms = ((JArray)dict["@platforms"]).Values().Select(v => v.ToString()).ToArray();
|
||||
}
|
||||
if (dict.ContainsKey("id")) wgtInfo.AppId = dict["id"].ToString();
|
||||
if (dict.ContainsKey("name")) wgtInfo.AppName = dict["name"].ToString();
|
||||
if (dict.ContainsKey("id")) info.AppId = dict["id"].ToString();
|
||||
if (dict.ContainsKey("name")) info.AppName = dict["name"].ToString();
|
||||
if (dict.ContainsKey("version"))
|
||||
{
|
||||
var version = (JObject)dict["version"];
|
||||
|
||||
if (version != null)
|
||||
{
|
||||
if (version.ContainsKey("name")) wgtInfo.AppVersionName = version["name"].ToString();
|
||||
if (version.ContainsKey("code")) wgtInfo.AppVersionCode = version["code"].ToString();
|
||||
if (version.ContainsKey("name")) info.AppVersionName = version["name"].ToString();
|
||||
if (version.ContainsKey("code")) info.AppVersionCode = version["code"].ToString();
|
||||
}
|
||||
}
|
||||
if (dict.ContainsKey("description")) wgtInfo.AppDescription = dict["description"].ToString();
|
||||
if (dict.ContainsKey("description")) info.AppDescription = dict["description"].ToString();
|
||||
if (dict.ContainsKey("permissions"))
|
||||
{
|
||||
var permissions = (JObject)dict["permissions"];
|
||||
@@ -72,7 +72,7 @@ internal static class WgtParser
|
||||
{
|
||||
permissionNames.Add(permission.Key);
|
||||
}
|
||||
wgtInfo.Permissions = [.. permissionNames];
|
||||
info.Permissions = [.. permissionNames];
|
||||
}
|
||||
}
|
||||
if (dict.ContainsKey("plus"))
|
||||
@@ -92,7 +92,7 @@ internal static class WgtParser
|
||||
{
|
||||
if (kv.Key == "name")
|
||||
{
|
||||
wgtInfo.AppNameLocales.Add(locale.Key, kv.Value.ToString());
|
||||
info.AppNameLocales.Add(locale.Key, kv.Value.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -103,8 +103,8 @@ internal static class WgtParser
|
||||
var uni_app = plus["uni-app"];
|
||||
var dictionary = uni_app.ToObject<Dictionary<string, object>>();
|
||||
|
||||
if (dictionary.ContainsKey("vueVersion")) wgtInfo.VueVersion = dictionary["vueVersion"].ToString();
|
||||
if (dictionary.ContainsKey("compilerVersion")) wgtInfo.CompilerVersion = dictionary["compilerVersion"].ToString();
|
||||
if (dictionary.ContainsKey("vueVersion")) info.VueVersion = dictionary["vueVersion"].ToString();
|
||||
if (dictionary.ContainsKey("compilerVersion")) info.CompilerVersion = dictionary["compilerVersion"].ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -116,13 +116,13 @@ internal static class WgtParser
|
||||
{
|
||||
foreach (var descriptionLocale in descriptionLocales)
|
||||
{
|
||||
wgtInfo.AppDescriptionLocales.Add(descriptionLocale.Key, descriptionLocale.Value.ToString());
|
||||
info.AppDescriptionLocales.Add(descriptionLocale.Key, descriptionLocale.Value.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (dict.ContainsKey("fallbackLocale")) wgtInfo.FallbackLocale = dict["fallbackLocale"].ToString();
|
||||
if (dict.ContainsKey("fallbackLocale")) info.FallbackLocale = dict["fallbackLocale"].ToString();
|
||||
|
||||
return wgtInfo;
|
||||
return info;
|
||||
}
|
||||
|
||||
return null;
|
||||
|
Reference in New Issue
Block a user