Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
596ad18412 | ||
|
|
fe282b445b | ||
|
|
0ee94bcb0d | ||
|
|
96001e4d40 | ||
|
|
6898eeb42c | ||
|
|
5250f48d38 | ||
|
|
802daebe56 | ||
|
|
f49e184dbb | ||
|
|
d634763eef | ||
|
|
5902bf9aa3 | ||
|
|
6d91972e97 | ||
|
|
879a12f912 | ||
|
|
e4d421d4e0 | ||
|
|
e2f65b540a | ||
|
|
5788b098e9 |
@@ -4,5 +4,29 @@
|
||||
<dict>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>AppIcon</string>
|
||||
<key>UTImportedTypeDeclarations</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>UTTypeConformsTo</key>
|
||||
<array>
|
||||
<string>public.data</string>
|
||||
</array>
|
||||
<key>UTTypeIdentifier</key>
|
||||
<string>com.opa334.trollstore.tipa</string>
|
||||
<key>UTTypeDescription</key>
|
||||
<string>AirDrop friendly iOS app</string>
|
||||
<key>UTTypeTagSpecification</key>
|
||||
<dict>
|
||||
<key>public.mime-type</key>
|
||||
<array>
|
||||
<string>application/trollstore-ipa</string>
|
||||
</array>
|
||||
<key>public.filename-extension</key>
|
||||
<array>
|
||||
<string>tipa</string>
|
||||
</array>
|
||||
</dict>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
@@ -1,33 +1,27 @@
|
||||
import Foundation
|
||||
import AppKit // NSImage
|
||||
import CoreUI // CUICatalog
|
||||
import os // OSLog
|
||||
private import CoreUI // CUICatalog
|
||||
private import os // OSLog
|
||||
|
||||
private let log = OSLog(subsystem: Bundle.main.bundleIdentifier!, category: "AppIcon+Car")
|
||||
private let log = OSLog(subsystem: Bundle.main.bundleIdentifier!, category: "AssetCarReader")
|
||||
|
||||
// this has been written from scratch but general usage on
|
||||
// including the private framework has been taken from:
|
||||
// https://github.com/showxu/cartools
|
||||
// also see:
|
||||
// https://blog.timac.org/2018/1018-reverse-engineering-the-car-file-format/
|
||||
|
||||
extension AppIcon {
|
||||
/// Use `CUICatalog` to extract an image from `Assets.car`
|
||||
func imageFromAssetsCar(_ imageName: String) -> NSImage? {
|
||||
guard let data = meta.readPayloadFile("Assets.car") else {
|
||||
return nil
|
||||
}
|
||||
let catalog: CUICatalog
|
||||
public class CarReader {
|
||||
private let catalog: CUICatalog
|
||||
|
||||
public init?(_ data: Data) {
|
||||
do {
|
||||
catalog = try data.withUnsafeBytes { try CUICatalog(bytes: $0.baseAddress!, length: UInt64(data.count)) }
|
||||
} catch {
|
||||
os_log(.error, log: log, "[icon-car] ERROR: could not open catalog: %{public}@", error.localizedDescription)
|
||||
os_log(.error, log: log, "[asset-car] ERROR: could not open catalog: %{public}@", error.localizedDescription)
|
||||
return nil
|
||||
}
|
||||
|
||||
if let validName = carVerifyNameExists(imageName, in: catalog) {
|
||||
if let bestImage = carFindHighestResolutionIcon(catalog.images(withName: validName)) {
|
||||
os_log(.debug, log: log, "[icon-car] using Assets.car with key %{public}@", validName)
|
||||
}
|
||||
|
||||
/// Use `CUICatalog` to extract an image from `Assets.car`
|
||||
public func imageFromAssetsCar(_ imageName: String) -> NSImage? {
|
||||
if let validName = verifyNameExists(imageName, in: catalog) {
|
||||
if let bestImage = findHighestResolutionIcon(catalog.images(withName: validName)) {
|
||||
os_log(.debug, log: log, "[asset-car] using Assets.car with key %{public}@", validName)
|
||||
return NSImage(cgImage: bestImage.image, size: bestImage.size)
|
||||
}
|
||||
}
|
||||
@@ -35,19 +29,19 @@ extension AppIcon {
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Helper: Assets.car
|
||||
// MARK: - Private methods
|
||||
|
||||
/// Helper method to check available icon names. Will return a valid name or `nil` if no image with that key is found.
|
||||
func carVerifyNameExists(_ imageName: String, in catalog: CUICatalog) -> String? {
|
||||
private func verifyNameExists(_ imageName: String, in catalog: CUICatalog) -> String? {
|
||||
if let availableNames = catalog.allImageNames(), !availableNames.contains(imageName) {
|
||||
// Theoretically this should never happen. Assuming the image name is found in an image file.
|
||||
os_log(.info, log: log, "[icon-car] WARN: key '%{public}@' does not match any available key", imageName)
|
||||
os_log(.info, log: log, "[asset-car] WARN: key '%{public}@' does not match any available key", imageName)
|
||||
|
||||
if let alternativeName = carSearchAlternativeName(imageName, inAvailable: availableNames) {
|
||||
os_log(.info, log: log, "[icon-car] falling back to '%{public}@'", alternativeName)
|
||||
if let alternativeName = searchAlternativeName(imageName, inAvailable: availableNames) {
|
||||
os_log(.info, log: log, "[asset-car] falling back to '%{public}@'", alternativeName)
|
||||
return alternativeName
|
||||
}
|
||||
os_log(.debug, log: log, "[icon-car] available keys: %{public}@", catalog.allImageNames() ?? [])
|
||||
os_log(.debug, log: log, "[asset-car] available keys: %{public}@", catalog.allImageNames() ?? [])
|
||||
return nil
|
||||
}
|
||||
return imageName;
|
||||
@@ -55,7 +49,7 @@ extension AppIcon {
|
||||
|
||||
/// If exact name does not exist in catalog, search for a name that shares the same prefix.
|
||||
/// E.g., "AppIcon60x60" may match "AppIcon" or "AppIcon60x60_small"
|
||||
func carSearchAlternativeName(_ originalName: String, inAvailable availableNames: [String]) -> String? {
|
||||
private func searchAlternativeName(_ originalName: String, inAvailable availableNames: [String]) -> String? {
|
||||
var bestOption: String? = nil
|
||||
var bestDiff: Int = 999
|
||||
|
||||
@@ -72,7 +66,7 @@ extension AppIcon {
|
||||
}
|
||||
|
||||
/// Given a list of `CUINamedImage`, return the one with the highest resolution. Vector graphics are ignored.
|
||||
func carFindHighestResolutionIcon(_ availableImages: [CUINamedImage]) -> CUINamedImage? {
|
||||
private func findHighestResolutionIcon(_ availableImages: [CUINamedImage]) -> CUINamedImage? {
|
||||
var largestWidth: CGFloat = 0
|
||||
var largestImage: CUINamedImage? = nil
|
||||
// cast to NSArray is necessary as otherwise this will crash
|
||||
9
AssetCarReader/AssetCarReader.xcconfig
Normal file
9
AssetCarReader/AssetCarReader.xcconfig
Normal file
@@ -0,0 +1,9 @@
|
||||
// Configuration settings file format documentation can be found at:
|
||||
// https://help.apple.com/xcode/#/dev745c5c974
|
||||
|
||||
FRAMEWORK_SEARCH_PATHS = $(PROJECT_DIR)/AssetCarReader/PrivateFrameworks
|
||||
SYSTEM_FRAMEWORK_SEARCH_PATHS = $(SYSTEM_LIBRARY_DIR)/PrivateFrameworks
|
||||
SWIFT_INCLUDE_PATHS = $(SRCROOT)/AssetCarReader/PrivateFrameworks/CoreUI.framework
|
||||
|
||||
DYLIB_COMPATIBILITY_VERSION = 1
|
||||
DYLIB_CURRENT_VERSION = 42
|
||||
30
CHANGELOG.md
Normal file
30
CHANGELOG.md
Normal file
@@ -0,0 +1,30 @@
|
||||
# Changelog
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project does adhere to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
|
||||
## [1.2.0] – 2025-11-04
|
||||
Added:
|
||||
- Customizable HTML template
|
||||
|
||||
Fixed:
|
||||
- Properly handle `Assets.car` files by abstracting relevant code into `.framework`
|
||||
|
||||
Changed:
|
||||
- Updated HTML template
|
||||
|
||||
|
||||
## [1.1.0] – 2025-10-30
|
||||
Added:
|
||||
- Support for `.tipa` files
|
||||
|
||||
|
||||
## [1.0.0] – 2025-10-30
|
||||
Initial release
|
||||
|
||||
|
||||
[1.2.0]: https://github.com/relikd/QLAppBundle/compare/v1.1.0...v1.2.0
|
||||
[1.1.0]: https://github.com/relikd/QLAppBundle/compare/v1.0.0...v1.1.0
|
||||
[1.0.0]: https://github.com/relikd/QLAppBundle/compare/9b0761318c85090d1ef22f12d3eab67a9a194882...v1.0.0
|
||||
6
Config-debug.xcconfig
Normal file
6
Config-debug.xcconfig
Normal file
@@ -0,0 +1,6 @@
|
||||
// Configuration settings file format documentation can be found at:
|
||||
// https://help.apple.com/xcode/#/dev745c5c974
|
||||
|
||||
#include "Config.xcconfig"
|
||||
|
||||
PRODUCT_BUNDLE_IDENTIFIER = de.relikd.QLAppBundle.debug
|
||||
13
Config.xcconfig
Normal file
13
Config.xcconfig
Normal file
@@ -0,0 +1,13 @@
|
||||
// Configuration settings file format documentation can be found at:
|
||||
// https://help.apple.com/xcode/#/dev745c5c974
|
||||
|
||||
CODE_SIGN_STYLE = Manual
|
||||
CODE_SIGN_IDENTITY = Apple Development
|
||||
ENABLE_HARDENED_RUNTIME = YES
|
||||
|
||||
SWIFT_VERSION = 5.0
|
||||
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.15
|
||||
MARKETING_VERSION = 1.2.0
|
||||
PRODUCT_NAME = QLAppBundle
|
||||
PRODUCT_BUNDLE_IDENTIFIER = de.relikd.QLAppBundle
|
||||
@@ -11,36 +11,39 @@
|
||||
5405CF652EA1376B00613856 /* Zip.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5405CF642EA1376B00613856 /* Zip.swift */; };
|
||||
543FE5742EB3BB5E0059F98B /* AppIcon.icns in Resources */ = {isa = PBXBuildFile; fileRef = 543FE5732EB3BB5E0059F98B /* AppIcon.icns */; };
|
||||
54442C232E378BAF008A870E /* Quartz.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 54442C222E378BAF008A870E /* Quartz.framework */; };
|
||||
54442C302E378BAF008A870E /* QLPreview.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 54442C202E378BAF008A870E /* QLPreview.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||
54442C702E378BDD008A870E /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54442C6A2E378BDD008A870E /* AppDelegate.swift */; };
|
||||
54442C722E378BDD008A870E /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 54442C6D2E378BDD008A870E /* MainMenu.xib */; };
|
||||
54442C792E378BE0008A870E /* PreviewViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54442C742E378BE0008A870E /* PreviewViewController.swift */; };
|
||||
54442C7B2E378BE0008A870E /* PreviewViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 54442C762E378BE0008A870E /* PreviewViewController.xib */; };
|
||||
544AF3692EB6AAC0006837F2 /* AssetCarReader.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 544AF3682EB6AAC0006837F2 /* AssetCarReader.xcconfig */; };
|
||||
545459C42EA469E4002892E5 /* defaultIcon.png in Resources */ = {isa = PBXBuildFile; fileRef = 54D3A6F22EA4603B001EF4F6 /* defaultIcon.png */; };
|
||||
545459C52EA469EA002892E5 /* template.html in Resources */ = {isa = PBXBuildFile; fileRef = 54D3A6F32EA4603B001EF4F6 /* template.html */; };
|
||||
54581FD12EB29A0B0043A0B3 /* QuickLookThumbnailing.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 54581FD02EB29A0B0043A0B3 /* QuickLookThumbnailing.framework */; };
|
||||
54581FD22EB29A0B0043A0B3 /* Quartz.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 54442C222E378BAF008A870E /* Quartz.framework */; };
|
||||
54581FDA2EB29A0B0043A0B3 /* QLThumbnail.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 54581FCF2EB29A0B0043A0B3 /* QLThumbnail.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||
545820222EB29B3D0043A0B3 /* ThumbnailProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5458201F2EB29B3D0043A0B3 /* ThumbnailProvider.swift */; };
|
||||
54581FDA2EB29A0B0043A0B3 /* QLAppBundle Thumbnail Extension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 54581FCF2EB29A0B0043A0B3 /* QLAppBundle Thumbnail Extension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||
545820232EB29B4C0043A0B3 /* defaultIcon.png in Resources */ = {isa = PBXBuildFile; fileRef = 54D3A6F22EA4603B001EF4F6 /* defaultIcon.png */; };
|
||||
5469E11D2EA5930C00D46CE7 /* Entitlements.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5469E11C2EA5930C00D46CE7 /* Entitlements.swift */; };
|
||||
5478996F2EB38EBB00F96B80 /* CoreUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 54D3A6F52EA4610B001EF4F6 /* CoreUI.framework */; };
|
||||
547899702EB38EBB00F96B80 /* CoreUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 54D3A6F52EA4610B001EF4F6 /* CoreUI.framework */; };
|
||||
547899712EB38F3D00F96B80 /* Zip.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5405CF642EA1376B00613856 /* Zip.swift */; };
|
||||
547899722EB38F3D00F96B80 /* MetaInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5405CF5D2EA1199B00613856 /* MetaInfo.swift */; };
|
||||
547899732EB38F3D00F96B80 /* NSBezierPath+RoundedRect.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54D3A6EF2EA3F49F001EF4F6 /* NSBezierPath+RoundedRect.swift */; };
|
||||
547899752EB38F3D00F96B80 /* AppIcon.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54D3A6ED2EA39CC6001EF4F6 /* AppIcon.swift */; };
|
||||
547899762EB38FD400F96B80 /* AppIcon+Car.swift in Sources */ = {isa = PBXBuildFile; fileRef = 545459C62EA4773A002892E5 /* AppIcon+Car.swift */; };
|
||||
547899772EB38FD400F96B80 /* AppIcon+Car.swift in Sources */ = {isa = PBXBuildFile; fileRef = 545459C62EA4773A002892E5 /* AppIcon+Car.swift */; };
|
||||
547F52DE2EB2C15D002B6D5F /* ExpirationStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = 547F52DC2EB2C15D002B6D5F /* ExpirationStatus.swift */; };
|
||||
547F52E42EB2C3D8002B6D5F /* Html+iTunesPurchase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 547F52E32EB2C3D8002B6D5F /* Html+iTunesPurchase.swift */; };
|
||||
547F52E82EB2C41C002B6D5F /* HtmlGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 547F52E62EB2C41C002B6D5F /* HtmlGenerator.swift */; };
|
||||
547F52EB2EB2C672002B6D5F /* Html+FileInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 547F52E92EB2C672002B6D5F /* Html+FileInfo.swift */; };
|
||||
547F52ED2EB2C822002B6D5F /* Html+AppInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 547F52EC2EB2C822002B6D5F /* Html+AppInfo.swift */; };
|
||||
547F52EF2EB2C8E8002B6D5F /* Html+Provisioning.swift in Sources */ = {isa = PBXBuildFile; fileRef = 547F52EE2EB2C8E8002B6D5F /* Html+Provisioning.swift */; };
|
||||
547F52F42EB2CA05002B6D5F /* Html+Entitlements.swift in Sources */ = {isa = PBXBuildFile; fileRef = 547F52F32EB2CA05002B6D5F /* Html+Entitlements.swift */; };
|
||||
547F52F72EB2CAC7002B6D5F /* Html+Footer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 547F52F62EB2CAC7002B6D5F /* Html+Footer.swift */; };
|
||||
547F52E42EB2C3D8002B6D5F /* Preview+iTunesPurchase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 547F52E32EB2C3D8002B6D5F /* Preview+iTunesPurchase.swift */; };
|
||||
547F52E82EB2C41C002B6D5F /* PreviewGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 547F52E62EB2C41C002B6D5F /* PreviewGenerator.swift */; };
|
||||
547F52EB2EB2C672002B6D5F /* Preview+FileInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 547F52E92EB2C672002B6D5F /* Preview+FileInfo.swift */; };
|
||||
547F52ED2EB2C822002B6D5F /* Preview+AppInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 547F52EC2EB2C822002B6D5F /* Preview+AppInfo.swift */; };
|
||||
547F52EF2EB2C8E8002B6D5F /* Preview+Provisioning.swift in Sources */ = {isa = PBXBuildFile; fileRef = 547F52EE2EB2C8E8002B6D5F /* Preview+Provisioning.swift */; };
|
||||
547F52F42EB2CA05002B6D5F /* Preview+Entitlements.swift in Sources */ = {isa = PBXBuildFile; fileRef = 547F52F32EB2CA05002B6D5F /* Preview+Entitlements.swift */; };
|
||||
547F52F72EB2CAC7002B6D5F /* Preview+Footer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 547F52F62EB2CAC7002B6D5F /* Preview+Footer.swift */; };
|
||||
547F52F92EB2CBAB002B6D5F /* Date+Format.swift in Sources */ = {isa = PBXBuildFile; fileRef = 547F52F82EB2CBAB002B6D5F /* Date+Format.swift */; };
|
||||
549E3B9F2EBA9D2500ADFF56 /* QLAppBundle Preview Extension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 54442C202E378BAF008A870E /* QLAppBundle Preview Extension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||
54AE5BFF2EB3DB1000B4CFC7 /* ThumbnailProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54AE5BFD2EB3DB1000B4CFC7 /* ThumbnailProvider.swift */; };
|
||||
54B6FFEE2EB6A847007397C0 /* AssetCarReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54B6FFEC2EB6A847007397C0 /* AssetCarReader.swift */; };
|
||||
54B6FFEF2EB6A8E0007397C0 /* CoreUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 54D3A6F52EA4610B001EF4F6 /* CoreUI.framework */; };
|
||||
54B6FFF02EB6AA0F007397C0 /* AssetCarReader.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 54352E8A2EB6A79A0082F61D /* AssetCarReader.framework */; };
|
||||
54B6FFF12EB6AA0F007397C0 /* AssetCarReader.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 54352E8A2EB6A79A0082F61D /* AssetCarReader.framework */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||
54B6FFF52EB6AA14007397C0 /* AssetCarReader.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 54352E8A2EB6A79A0082F61D /* AssetCarReader.framework */; };
|
||||
54B6FFF62EB6AA14007397C0 /* AssetCarReader.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 54352E8A2EB6A79A0082F61D /* AssetCarReader.framework */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||
54D3A6EC2EA31B52001EF4F6 /* AppCategories.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54D3A6EB2EA31B52001EF4F6 /* AppCategories.swift */; };
|
||||
54D3A6EE2EA39CC6001EF4F6 /* AppIcon.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54D3A6ED2EA39CC6001EF4F6 /* AppIcon.swift */; };
|
||||
54D3A6F02EA3F49F001EF4F6 /* NSBezierPath+RoundedRect.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54D3A6EF2EA3F49F001EF4F6 /* NSBezierPath+RoundedRect.swift */; };
|
||||
@@ -63,6 +66,20 @@
|
||||
remoteGlobalIDString = 54581FCE2EB29A0B0043A0B3;
|
||||
remoteInfo = QLThumbnail;
|
||||
};
|
||||
54B6FFF22EB6AA0F007397C0 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 54442BEC2E378B71008A870E /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 54352E892EB6A79A0082F61D;
|
||||
remoteInfo = AssetCarReader;
|
||||
};
|
||||
54B6FFF72EB6AA14007397C0 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 54442BEC2E378B71008A870E /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 54352E892EB6A79A0082F61D;
|
||||
remoteInfo = AssetCarReader;
|
||||
};
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
@@ -72,21 +89,44 @@
|
||||
dstPath = "";
|
||||
dstSubfolderSpec = 13;
|
||||
files = (
|
||||
54581FDA2EB29A0B0043A0B3 /* QLThumbnail.appex in Embed Foundation Extensions */,
|
||||
54442C302E378BAF008A870E /* QLPreview.appex in Embed Foundation Extensions */,
|
||||
549E3B9F2EBA9D2500ADFF56 /* QLAppBundle Preview Extension.appex in Embed Foundation Extensions */,
|
||||
54581FDA2EB29A0B0043A0B3 /* QLAppBundle Thumbnail Extension.appex in Embed Foundation Extensions */,
|
||||
);
|
||||
name = "Embed Foundation Extensions";
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
54B6FFF42EB6AA0F007397C0 /* Embed Frameworks */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = "";
|
||||
dstSubfolderSpec = 10;
|
||||
files = (
|
||||
54B6FFF12EB6AA0F007397C0 /* AssetCarReader.framework in Embed Frameworks */,
|
||||
);
|
||||
name = "Embed Frameworks";
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
54B6FFF92EB6AA14007397C0 /* Embed Frameworks */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = "";
|
||||
dstSubfolderSpec = 10;
|
||||
files = (
|
||||
54B6FFF62EB6AA14007397C0 /* AssetCarReader.framework in Embed Frameworks */,
|
||||
);
|
||||
name = "Embed Frameworks";
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
5405CF5D2EA1199B00613856 /* MetaInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MetaInfo.swift; sourceTree = "<group>"; };
|
||||
5405CF642EA1376B00613856 /* Zip.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Zip.swift; sourceTree = "<group>"; };
|
||||
54352E8A2EB6A79A0082F61D /* AssetCarReader.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = AssetCarReader.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
543FE5732EB3BB5E0059F98B /* AppIcon.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = AppIcon.icns; sourceTree = "<group>"; };
|
||||
543FE5752EB3BC740059F98B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
54442BF42E378B71008A870E /* QLAppBundle (debug).app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "QLAppBundle (debug).app"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
54442C202E378BAF008A870E /* QLPreview.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = QLPreview.appex; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
54442C202E378BAF008A870E /* QLAppBundle Preview Extension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "QLAppBundle Preview Extension.appex"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
54442C222E378BAF008A870E /* Quartz.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Quartz.framework; path = System/Library/Frameworks/Quartz.framework; sourceTree = SDKROOT; };
|
||||
54442C6A2E378BDD008A870E /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
54442C6C2E378BDD008A870E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = "<group>"; };
|
||||
@@ -95,25 +135,27 @@
|
||||
54442C742E378BE0008A870E /* PreviewViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreviewViewController.swift; sourceTree = "<group>"; };
|
||||
54442C752E378BE0008A870E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/PreviewViewController.xib; sourceTree = "<group>"; };
|
||||
54442C772E378BE0008A870E /* QLPreview.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = QLPreview.entitlements; sourceTree = "<group>"; };
|
||||
545459C62EA4773A002892E5 /* AppIcon+Car.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AppIcon+Car.swift"; sourceTree = "<group>"; };
|
||||
54581FCF2EB29A0B0043A0B3 /* QLThumbnail.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = QLThumbnail.appex; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
544AF3682EB6AAC0006837F2 /* AssetCarReader.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AssetCarReader.xcconfig; sourceTree = "<group>"; };
|
||||
54581FCF2EB29A0B0043A0B3 /* QLAppBundle Thumbnail Extension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "QLAppBundle Thumbnail Extension.appex"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
54581FD02EB29A0B0043A0B3 /* QuickLookThumbnailing.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuickLookThumbnailing.framework; path = System/Library/Frameworks/QuickLookThumbnailing.framework; sourceTree = SDKROOT; };
|
||||
5458201D2EB29B3D0043A0B3 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
5458201E2EB29B3D0043A0B3 /* QLThumbnail.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = QLThumbnail.entitlements; sourceTree = "<group>"; };
|
||||
5458201F2EB29B3D0043A0B3 /* ThumbnailProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThumbnailProvider.swift; sourceTree = "<group>"; };
|
||||
545D9F3D2EB54C6200C38917 /* Config.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Config.xcconfig; sourceTree = "<group>"; };
|
||||
5469E11C2EA5930C00D46CE7 /* Entitlements.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Entitlements.swift; sourceTree = "<group>"; };
|
||||
547F52DC2EB2C15D002B6D5F /* ExpirationStatus.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExpirationStatus.swift; sourceTree = "<group>"; };
|
||||
547F52E32EB2C3D8002B6D5F /* Html+iTunesPurchase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Html+iTunesPurchase.swift"; sourceTree = "<group>"; };
|
||||
547F52E62EB2C41C002B6D5F /* HtmlGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HtmlGenerator.swift; sourceTree = "<group>"; };
|
||||
547F52E92EB2C672002B6D5F /* Html+FileInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Html+FileInfo.swift"; sourceTree = "<group>"; };
|
||||
547F52EC2EB2C822002B6D5F /* Html+AppInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Html+AppInfo.swift"; sourceTree = "<group>"; };
|
||||
547F52EE2EB2C8E8002B6D5F /* Html+Provisioning.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Html+Provisioning.swift"; sourceTree = "<group>"; };
|
||||
547F52F32EB2CA05002B6D5F /* Html+Entitlements.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Html+Entitlements.swift"; sourceTree = "<group>"; };
|
||||
547F52F62EB2CAC7002B6D5F /* Html+Footer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Html+Footer.swift"; sourceTree = "<group>"; };
|
||||
547F52E32EB2C3D8002B6D5F /* Preview+iTunesPurchase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Preview+iTunesPurchase.swift"; sourceTree = "<group>"; };
|
||||
547F52E62EB2C41C002B6D5F /* PreviewGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreviewGenerator.swift; sourceTree = "<group>"; };
|
||||
547F52E92EB2C672002B6D5F /* Preview+FileInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Preview+FileInfo.swift"; sourceTree = "<group>"; };
|
||||
547F52EC2EB2C822002B6D5F /* Preview+AppInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Preview+AppInfo.swift"; sourceTree = "<group>"; };
|
||||
547F52EE2EB2C8E8002B6D5F /* Preview+Provisioning.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Preview+Provisioning.swift"; sourceTree = "<group>"; };
|
||||
547F52F32EB2CA05002B6D5F /* Preview+Entitlements.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Preview+Entitlements.swift"; sourceTree = "<group>"; };
|
||||
547F52F62EB2CAC7002B6D5F /* Preview+Footer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Preview+Footer.swift"; sourceTree = "<group>"; };
|
||||
547F52F82EB2CBAB002B6D5F /* Date+Format.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Date+Format.swift"; sourceTree = "<group>"; };
|
||||
547F52FB2EB37F10002B6D5F /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
|
||||
547F52FC2EB37F3A002B6D5F /* LICENSE */ = {isa = PBXFileReference; lastKnownFileType = text; path = LICENSE; sourceTree = "<group>"; };
|
||||
5485EE362EB1460C009E3905 /* Network.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Network.framework; path = System/Library/Frameworks/Network.framework; sourceTree = SDKROOT; };
|
||||
549E3B9E2EBA8FDA00ADFF56 /* CHANGELOG.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = CHANGELOG.md; sourceTree = "<group>"; };
|
||||
54AE5BFB2EB3DB1000B4CFC7 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
54AE5BFC2EB3DB1000B4CFC7 /* QLThumbnail.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = QLThumbnail.entitlements; sourceTree = "<group>"; };
|
||||
54AE5BFD2EB3DB1000B4CFC7 /* ThumbnailProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThumbnailProvider.swift; sourceTree = "<group>"; };
|
||||
54B6FFEC2EB6A847007397C0 /* AssetCarReader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AssetCarReader.swift; sourceTree = "<group>"; };
|
||||
54D3A6EB2EA31B52001EF4F6 /* AppCategories.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppCategories.swift; sourceTree = "<group>"; };
|
||||
54D3A6ED2EA39CC6001EF4F6 /* AppIcon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppIcon.swift; sourceTree = "<group>"; };
|
||||
54D3A6EF2EA3F49F001EF4F6 /* NSBezierPath+RoundedRect.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSBezierPath+RoundedRect.swift"; sourceTree = "<group>"; };
|
||||
@@ -121,18 +163,19 @@
|
||||
54D3A6F32EA4603B001EF4F6 /* template.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = template.html; sourceTree = "<group>"; };
|
||||
54D3A6F52EA4610B001EF4F6 /* CoreUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = CoreUI.framework; sourceTree = "<group>"; };
|
||||
54D3A6FA2EA46588001EF4F6 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
|
||||
54D3A6FC2EA465A9001EF4F6 /* CoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreServices.framework; path = System/Library/Frameworks/CoreServices.framework; sourceTree = SDKROOT; };
|
||||
54D3A6FF2EA465C4001EF4F6 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
|
||||
54E0874C2EB1488300979D91 /* ApplicationServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ApplicationServices.framework; path = System/Library/Frameworks/ApplicationServices.framework; sourceTree = SDKROOT; };
|
||||
54E0874E2EB1489100979D91 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; };
|
||||
54E087512EB148B700979D91 /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; };
|
||||
54E087532EB148DB00979D91 /* QuickLook.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuickLook.framework; path = System/Library/Frameworks/QuickLook.framework; sourceTree = SDKROOT; };
|
||||
54E087552EB148DF00979D91 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; };
|
||||
54E087572EB148E700979D91 /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = System/Library/Frameworks/WebKit.framework; sourceTree = SDKROOT; };
|
||||
54E087592EB15DD000979D91 /* style.css */ = {isa = PBXFileReference; lastKnownFileType = text.css; path = style.css; sourceTree = "<group>"; };
|
||||
54EA9EB22EB6CCA300AB6027 /* Config-debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Config-debug.xcconfig"; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
54352E872EB6A79A0082F61D /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
54B6FFEF2EB6A8E0007397C0 /* CoreUI.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
54442BF12E378B71008A870E /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -144,9 +187,9 @@
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
54B6FFF02EB6AA0F007397C0 /* AssetCarReader.framework in Frameworks */,
|
||||
54D3A6FE2EA465B4001EF4F6 /* CoreGraphics.framework in Frameworks */,
|
||||
54442C232E378BAF008A870E /* Quartz.framework in Frameworks */,
|
||||
5478996F2EB38EBB00F96B80 /* CoreUI.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -154,9 +197,9 @@
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
54B6FFF52EB6AA14007397C0 /* AssetCarReader.framework in Frameworks */,
|
||||
54581FD12EB29A0B0043A0B3 /* QuickLookThumbnailing.framework in Frameworks */,
|
||||
54581FD22EB29A0B0043A0B3 /* Quartz.framework in Frameworks */,
|
||||
547899702EB38EBB00F96B80 /* CoreUI.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -169,16 +212,15 @@
|
||||
5405CF5D2EA1199B00613856 /* MetaInfo.swift */,
|
||||
54D3A6EB2EA31B52001EF4F6 /* AppCategories.swift */,
|
||||
54D3A6ED2EA39CC6001EF4F6 /* AppIcon.swift */,
|
||||
545459C62EA4773A002892E5 /* AppIcon+Car.swift */,
|
||||
5469E11C2EA5930C00D46CE7 /* Entitlements.swift */,
|
||||
547F52DC2EB2C15D002B6D5F /* ExpirationStatus.swift */,
|
||||
547F52E62EB2C41C002B6D5F /* HtmlGenerator.swift */,
|
||||
547F52EC2EB2C822002B6D5F /* Html+AppInfo.swift */,
|
||||
547F52EE2EB2C8E8002B6D5F /* Html+Provisioning.swift */,
|
||||
547F52F32EB2CA05002B6D5F /* Html+Entitlements.swift */,
|
||||
547F52E32EB2C3D8002B6D5F /* Html+iTunesPurchase.swift */,
|
||||
547F52E92EB2C672002B6D5F /* Html+FileInfo.swift */,
|
||||
547F52F62EB2CAC7002B6D5F /* Html+Footer.swift */,
|
||||
547F52E62EB2C41C002B6D5F /* PreviewGenerator.swift */,
|
||||
547F52EC2EB2C822002B6D5F /* Preview+AppInfo.swift */,
|
||||
547F52EE2EB2C8E8002B6D5F /* Preview+Provisioning.swift */,
|
||||
547F52F32EB2CA05002B6D5F /* Preview+Entitlements.swift */,
|
||||
547F52E32EB2C3D8002B6D5F /* Preview+iTunesPurchase.swift */,
|
||||
547F52E92EB2C672002B6D5F /* Preview+FileInfo.swift */,
|
||||
547F52F62EB2CAC7002B6D5F /* Preview+Footer.swift */,
|
||||
5405CF642EA1376B00613856 /* Zip.swift */,
|
||||
54D3A6EF2EA3F49F001EF4F6 /* NSBezierPath+RoundedRect.swift */,
|
||||
547F52F82EB2CBAB002B6D5F /* Date+Format.swift */,
|
||||
@@ -189,14 +231,17 @@
|
||||
54442BEB2E378B71008A870E = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
545D9F3D2EB54C6200C38917 /* Config.xcconfig */,
|
||||
54EA9EB22EB6CCA300AB6027 /* Config-debug.xcconfig */,
|
||||
547F52FC2EB37F3A002B6D5F /* LICENSE */,
|
||||
547F52FB2EB37F10002B6D5F /* README.md */,
|
||||
54D3A6F62EA4610B001EF4F6 /* PrivateFrameworks */,
|
||||
549E3B9E2EBA8FDA00ADFF56 /* CHANGELOG.md */,
|
||||
541051562E37AFC10083670B /* src */,
|
||||
54D3A6F42EA46069001EF4F6 /* resources */,
|
||||
54442C6F2E378BDD008A870E /* App */,
|
||||
54442C782E378BE0008A870E /* QLPreview */,
|
||||
545820202EB29B3D0043A0B3 /* QLThumbnail */,
|
||||
54AE5BFE2EB3DB1000B4CFC7 /* QLThumbnail */,
|
||||
54B6FFED2EB6A847007397C0 /* AssetCarReader */,
|
||||
54442C212E378BAF008A870E /* Frameworks */,
|
||||
54442BF52E378B71008A870E /* Products */,
|
||||
);
|
||||
@@ -206,8 +251,9 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
54442BF42E378B71008A870E /* QLAppBundle (debug).app */,
|
||||
54442C202E378BAF008A870E /* QLPreview.appex */,
|
||||
54581FCF2EB29A0B0043A0B3 /* QLThumbnail.appex */,
|
||||
54442C202E378BAF008A870E /* QLAppBundle Preview Extension.appex */,
|
||||
54581FCF2EB29A0B0043A0B3 /* QLAppBundle Thumbnail Extension.appex */,
|
||||
54352E8A2EB6A79A0082F61D /* AssetCarReader.framework */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
@@ -215,15 +261,6 @@
|
||||
54442C212E378BAF008A870E /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
54E087572EB148E700979D91 /* WebKit.framework */,
|
||||
54E087552EB148DF00979D91 /* Security.framework */,
|
||||
54E087532EB148DB00979D91 /* QuickLook.framework */,
|
||||
54E087512EB148B700979D91 /* libz.tbd */,
|
||||
54E0874E2EB1489100979D91 /* CoreFoundation.framework */,
|
||||
54E0874C2EB1488300979D91 /* ApplicationServices.framework */,
|
||||
5485EE362EB1460C009E3905 /* Network.framework */,
|
||||
54D3A6FF2EA465C4001EF4F6 /* AppKit.framework */,
|
||||
54D3A6FC2EA465A9001EF4F6 /* CoreServices.framework */,
|
||||
54D3A6FA2EA46588001EF4F6 /* CoreGraphics.framework */,
|
||||
54442C222E378BAF008A870E /* Quartz.framework */,
|
||||
54581FD02EB29A0B0043A0B3 /* QuickLookThumbnailing.framework */,
|
||||
@@ -253,16 +290,26 @@
|
||||
path = QLPreview;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
545820202EB29B3D0043A0B3 /* QLThumbnail */ = {
|
||||
54AE5BFE2EB3DB1000B4CFC7 /* QLThumbnail */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
5458201D2EB29B3D0043A0B3 /* Info.plist */,
|
||||
5458201E2EB29B3D0043A0B3 /* QLThumbnail.entitlements */,
|
||||
5458201F2EB29B3D0043A0B3 /* ThumbnailProvider.swift */,
|
||||
54AE5BFB2EB3DB1000B4CFC7 /* Info.plist */,
|
||||
54AE5BFC2EB3DB1000B4CFC7 /* QLThumbnail.entitlements */,
|
||||
54AE5BFD2EB3DB1000B4CFC7 /* ThumbnailProvider.swift */,
|
||||
);
|
||||
path = QLThumbnail;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
54B6FFED2EB6A847007397C0 /* AssetCarReader */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
544AF3682EB6AAC0006837F2 /* AssetCarReader.xcconfig */,
|
||||
54B6FFEC2EB6A847007397C0 /* AssetCarReader.swift */,
|
||||
54D3A6F62EA4610B001EF4F6 /* PrivateFrameworks */,
|
||||
);
|
||||
path = AssetCarReader;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
54D3A6F42EA46069001EF4F6 /* resources */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -284,10 +331,40 @@
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXHeadersBuildPhase section */
|
||||
54352E852EB6A79A0082F61D /* Headers */ = {
|
||||
isa = PBXHeadersBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXHeadersBuildPhase section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
54442BF32E378B71008A870E /* QLAppBundle */ = {
|
||||
54352E892EB6A79A0082F61D /* AssetCarReader */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 54442C012E378B71008A870E /* Build configuration list for PBXNativeTarget "QLAppBundle" */;
|
||||
buildConfigurationList = 54352E902EB6A79A0082F61D /* Build configuration list for PBXNativeTarget "AssetCarReader" */;
|
||||
buildPhases = (
|
||||
54352E852EB6A79A0082F61D /* Headers */,
|
||||
54352E862EB6A79A0082F61D /* Sources */,
|
||||
54352E872EB6A79A0082F61D /* Frameworks */,
|
||||
54352E882EB6A79A0082F61D /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = AssetCarReader;
|
||||
packageProductDependencies = (
|
||||
);
|
||||
productName = AssetCarReader;
|
||||
productReference = 54352E8A2EB6A79A0082F61D /* AssetCarReader.framework */;
|
||||
productType = "com.apple.product-type.framework";
|
||||
};
|
||||
54442BF32E378B71008A870E /* App */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 54442C012E378B71008A870E /* Build configuration list for PBXNativeTarget "App" */;
|
||||
buildPhases = (
|
||||
54442BF02E378B71008A870E /* Sources */,
|
||||
54442BF12E378B71008A870E /* Frameworks */,
|
||||
@@ -300,49 +377,53 @@
|
||||
54442C2F2E378BAF008A870E /* PBXTargetDependency */,
|
||||
54581FD92EB29A0B0043A0B3 /* PBXTargetDependency */,
|
||||
);
|
||||
name = QLAppBundle;
|
||||
name = App;
|
||||
packageProductDependencies = (
|
||||
);
|
||||
productName = QLApps;
|
||||
productReference = 54442BF42E378B71008A870E /* QLAppBundle (debug).app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
54442C1F2E378BAF008A870E /* QLPreview */ = {
|
||||
54442C1F2E378BAF008A870E /* QL Preview */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 54442C352E378BAF008A870E /* Build configuration list for PBXNativeTarget "QLPreview" */;
|
||||
buildConfigurationList = 54442C352E378BAF008A870E /* Build configuration list for PBXNativeTarget "QL Preview" */;
|
||||
buildPhases = (
|
||||
54442C1C2E378BAF008A870E /* Sources */,
|
||||
54442C1D2E378BAF008A870E /* Frameworks */,
|
||||
54442C1E2E378BAF008A870E /* Resources */,
|
||||
54B6FFF42EB6AA0F007397C0 /* Embed Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
54B6FFF32EB6AA0F007397C0 /* PBXTargetDependency */,
|
||||
);
|
||||
name = QLPreview;
|
||||
name = "QL Preview";
|
||||
packageProductDependencies = (
|
||||
);
|
||||
productName = QLPreview;
|
||||
productReference = 54442C202E378BAF008A870E /* QLPreview.appex */;
|
||||
productReference = 54442C202E378BAF008A870E /* QLAppBundle Preview Extension.appex */;
|
||||
productType = "com.apple.product-type.app-extension";
|
||||
};
|
||||
54581FCE2EB29A0B0043A0B3 /* QLThumbnail */ = {
|
||||
54581FCE2EB29A0B0043A0B3 /* QL Thumbnail */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 54581FDE2EB29A0B0043A0B3 /* Build configuration list for PBXNativeTarget "QLThumbnail" */;
|
||||
buildConfigurationList = 54581FDE2EB29A0B0043A0B3 /* Build configuration list for PBXNativeTarget "QL Thumbnail" */;
|
||||
buildPhases = (
|
||||
54581FCB2EB29A0B0043A0B3 /* Sources */,
|
||||
54581FCC2EB29A0B0043A0B3 /* Frameworks */,
|
||||
54581FCD2EB29A0B0043A0B3 /* Resources */,
|
||||
54B6FFF92EB6AA14007397C0 /* Embed Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
54B6FFF82EB6AA14007397C0 /* PBXTargetDependency */,
|
||||
);
|
||||
name = QLThumbnail;
|
||||
name = "QL Thumbnail";
|
||||
packageProductDependencies = (
|
||||
);
|
||||
productName = QLThumbnail;
|
||||
productReference = 54581FCF2EB29A0B0043A0B3 /* QLThumbnail.appex */;
|
||||
productReference = 54581FCF2EB29A0B0043A0B3 /* QLAppBundle Thumbnail Extension.appex */;
|
||||
productType = "com.apple.product-type.app-extension";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
@@ -380,14 +461,23 @@
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
54442BF32E378B71008A870E /* QLAppBundle */,
|
||||
54442C1F2E378BAF008A870E /* QLPreview */,
|
||||
54581FCE2EB29A0B0043A0B3 /* QLThumbnail */,
|
||||
54442BF32E378B71008A870E /* App */,
|
||||
54442C1F2E378BAF008A870E /* QL Preview */,
|
||||
54581FCE2EB29A0B0043A0B3 /* QL Thumbnail */,
|
||||
54352E892EB6A79A0082F61D /* AssetCarReader */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
54352E882EB6A79A0082F61D /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
544AF3692EB6AAC0006837F2 /* AssetCarReader.xcconfig in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
54442BF22E378B71008A870E /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -419,6 +509,14 @@
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
54352E862EB6A79A0082F61D /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
54B6FFEE2EB6A847007397C0 /* AssetCarReader.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
54442BF02E378B71008A870E /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -432,22 +530,21 @@
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
54D3A6F02EA3F49F001EF4F6 /* NSBezierPath+RoundedRect.swift in Sources */,
|
||||
547F52E42EB2C3D8002B6D5F /* Html+iTunesPurchase.swift in Sources */,
|
||||
547F52F72EB2CAC7002B6D5F /* Html+Footer.swift in Sources */,
|
||||
547F52E42EB2C3D8002B6D5F /* Preview+iTunesPurchase.swift in Sources */,
|
||||
547F52F72EB2CAC7002B6D5F /* Preview+Footer.swift in Sources */,
|
||||
5469E11D2EA5930C00D46CE7 /* Entitlements.swift in Sources */,
|
||||
54442C792E378BE0008A870E /* PreviewViewController.swift in Sources */,
|
||||
547F52EF2EB2C8E8002B6D5F /* Html+Provisioning.swift in Sources */,
|
||||
547F52EF2EB2C8E8002B6D5F /* Preview+Provisioning.swift in Sources */,
|
||||
547F52DE2EB2C15D002B6D5F /* ExpirationStatus.swift in Sources */,
|
||||
54D3A6EE2EA39CC6001EF4F6 /* AppIcon.swift in Sources */,
|
||||
547F52E82EB2C41C002B6D5F /* HtmlGenerator.swift in Sources */,
|
||||
547F52EB2EB2C672002B6D5F /* Html+FileInfo.swift in Sources */,
|
||||
547F52ED2EB2C822002B6D5F /* Html+AppInfo.swift in Sources */,
|
||||
547F52F42EB2CA05002B6D5F /* Html+Entitlements.swift in Sources */,
|
||||
547F52E82EB2C41C002B6D5F /* PreviewGenerator.swift in Sources */,
|
||||
547F52EB2EB2C672002B6D5F /* Preview+FileInfo.swift in Sources */,
|
||||
547F52ED2EB2C822002B6D5F /* Preview+AppInfo.swift in Sources */,
|
||||
547F52F42EB2CA05002B6D5F /* Preview+Entitlements.swift in Sources */,
|
||||
5405CF5E2EA1199B00613856 /* MetaInfo.swift in Sources */,
|
||||
547F52F92EB2CBAB002B6D5F /* Date+Format.swift in Sources */,
|
||||
54D3A6EC2EA31B52001EF4F6 /* AppCategories.swift in Sources */,
|
||||
5405CF652EA1376B00613856 /* Zip.swift in Sources */,
|
||||
547899762EB38FD400F96B80 /* AppIcon+Car.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -458,9 +555,8 @@
|
||||
547899712EB38F3D00F96B80 /* Zip.swift in Sources */,
|
||||
547899722EB38F3D00F96B80 /* MetaInfo.swift in Sources */,
|
||||
547899732EB38F3D00F96B80 /* NSBezierPath+RoundedRect.swift in Sources */,
|
||||
54AE5BFF2EB3DB1000B4CFC7 /* ThumbnailProvider.swift in Sources */,
|
||||
547899752EB38F3D00F96B80 /* AppIcon.swift in Sources */,
|
||||
545820222EB29B3D0043A0B3 /* ThumbnailProvider.swift in Sources */,
|
||||
547899772EB38FD400F96B80 /* AppIcon+Car.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -469,14 +565,24 @@
|
||||
/* Begin PBXTargetDependency section */
|
||||
54442C2F2E378BAF008A870E /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 54442C1F2E378BAF008A870E /* QLPreview */;
|
||||
target = 54442C1F2E378BAF008A870E /* QL Preview */;
|
||||
targetProxy = 54442C2E2E378BAF008A870E /* PBXContainerItemProxy */;
|
||||
};
|
||||
54581FD92EB29A0B0043A0B3 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 54581FCE2EB29A0B0043A0B3 /* QLThumbnail */;
|
||||
target = 54581FCE2EB29A0B0043A0B3 /* QL Thumbnail */;
|
||||
targetProxy = 54581FD82EB29A0B0043A0B3 /* PBXContainerItemProxy */;
|
||||
};
|
||||
54B6FFF32EB6AA0F007397C0 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 54352E892EB6A79A0082F61D /* AssetCarReader */;
|
||||
targetProxy = 54B6FFF22EB6AA0F007397C0 /* PBXContainerItemProxy */;
|
||||
};
|
||||
54B6FFF82EB6AA14007397C0 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 54352E892EB6A79A0082F61D /* AssetCarReader */;
|
||||
targetProxy = 54B6FFF72EB6AA14007397C0 /* PBXContainerItemProxy */;
|
||||
};
|
||||
/* End PBXTargetDependency section */
|
||||
|
||||
/* Begin PBXVariantGroup section */
|
||||
@@ -499,8 +605,77 @@
|
||||
/* End PBXVariantGroup section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
54352E8E2EB6A79A0082F61D /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 544AF3682EB6AAC0006837F2 /* AssetCarReader.xcconfig */;
|
||||
buildSettings = {
|
||||
BUILD_LIBRARY_FOR_DISTRIBUTION = YES;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
ENABLE_MODULE_VERIFIER = YES;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
"@loader_path/Frameworks",
|
||||
);
|
||||
MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++";
|
||||
MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu17 gnu++20";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = de.relikd.AssetCarReader;
|
||||
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
|
||||
SKIP_INSTALL = YES;
|
||||
STRING_CATALOG_GENERATE_SYMBOLS = YES;
|
||||
SWIFT_APPROACHABLE_CONCURRENCY = YES;
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
SWIFT_INSTALL_MODULE = YES;
|
||||
SWIFT_INSTALL_OBJC_HEADER = NO;
|
||||
SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
|
||||
SWIFT_VERSION = 5.0;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
54352E8F2EB6A79A0082F61D /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 544AF3682EB6AAC0006837F2 /* AssetCarReader.xcconfig */;
|
||||
buildSettings = {
|
||||
BUILD_LIBRARY_FOR_DISTRIBUTION = YES;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
ENABLE_MODULE_VERIFIER = YES;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
"@loader_path/Frameworks",
|
||||
);
|
||||
MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++";
|
||||
MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu17 gnu++20";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = de.relikd.AssetCarReader;
|
||||
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
|
||||
SKIP_INSTALL = YES;
|
||||
STRING_CATALOG_GENERATE_SYMBOLS = YES;
|
||||
SWIFT_APPROACHABLE_CONCURRENCY = YES;
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
SWIFT_INSTALL_MODULE = YES;
|
||||
SWIFT_INSTALL_OBJC_HEADER = NO;
|
||||
SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
|
||||
SWIFT_VERSION = 5.0;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
54442BFF2E378B71008A870E /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 54EA9EB22EB6CCA300AB6027 /* Config-debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||
@@ -533,13 +708,13 @@
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 1086;
|
||||
CURRENT_PROJECT_VERSION = 1655;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
DEVELOPMENT_TEAM = UY657LKNHJ;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||
FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/PrivateFrameworks";
|
||||
GCC_C_LANGUAGE_STANDARD = gnu17;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
@@ -555,22 +730,18 @@
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.15;
|
||||
MARKETING_VERSION = 1.0.0;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = de.relikd.QLAppBundle.debug;
|
||||
SDKROOT = macosx;
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)";
|
||||
SWIFT_INCLUDE_PATHS = "$(SRCROOT)/PrivateFrameworks/CoreUI.framework";
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SYSTEM_FRAMEWORK_SEARCH_PATHS = "$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
54442C002E378B71008A870E /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 545D9F3D2EB54C6200C38917 /* Config.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||
@@ -603,13 +774,13 @@
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 1086;
|
||||
CURRENT_PROJECT_VERSION = 1655;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_TEAM = UY657LKNHJ;
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||
FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/PrivateFrameworks";
|
||||
GCC_C_LANGUAGE_STANDARD = gnu17;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = "";
|
||||
@@ -620,15 +791,10 @@
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.15;
|
||||
MARKETING_VERSION = 1.0.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = de.relikd.QLAppBundle;
|
||||
SDKROOT = macosx;
|
||||
SWIFT_COMPILATION_MODE = wholemodule;
|
||||
SWIFT_INCLUDE_PATHS = "$(SRCROOT)/PrivateFrameworks/CoreUI.framework";
|
||||
SYSTEM_FRAMEWORK_SEARCH_PATHS = "$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
@@ -636,12 +802,10 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CODE_SIGN_ENTITLEMENTS = App/App.entitlements;
|
||||
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
"DEVELOPMENT_TEAM[sdk=macosx*]" = UY657LKNHJ;
|
||||
ENABLE_HARDENED_RUNTIME = YES;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_FILE = App/Info.plist;
|
||||
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||
@@ -651,8 +815,7 @@
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "$(inherited)";
|
||||
PRODUCT_NAME = "$(TARGET_NAME) (debug)";
|
||||
PRODUCT_NAME = "$(inherited) (debug)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
REGISTER_APP_GROUPS = YES;
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
@@ -664,12 +827,10 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CODE_SIGN_ENTITLEMENTS = App/App.entitlements;
|
||||
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
"DEVELOPMENT_TEAM[sdk=macosx*]" = UY657LKNHJ;
|
||||
ENABLE_HARDENED_RUNTIME = YES;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_FILE = App/Info.plist;
|
||||
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||
@@ -679,8 +840,6 @@
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "$(inherited)";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
REGISTER_APP_GROUPS = YES;
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
@@ -692,21 +851,20 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CODE_SIGN_ENTITLEMENTS = QLPreview/QLPreview.entitlements;
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
"DEVELOPMENT_TEAM[sdk=macosx*]" = UY657LKNHJ;
|
||||
ENABLE_HARDENED_RUNTIME = YES;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_FILE = QLPreview/Info.plist;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = QLPreview;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = "$(PRODUCT_NAME) (debug)";
|
||||
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
"@executable_path/../../../../Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "$(inherited).QLPreview";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "$(inherited).Preview";
|
||||
PRODUCT_NAME = "$(inherited) Preview Extension";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
@@ -718,21 +876,20 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CODE_SIGN_ENTITLEMENTS = QLPreview/QLPreview.entitlements;
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
"DEVELOPMENT_TEAM[sdk=macosx*]" = UY657LKNHJ;
|
||||
ENABLE_HARDENED_RUNTIME = YES;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_FILE = QLPreview/Info.plist;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = QLPreview;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = "$(PRODUCT_NAME)";
|
||||
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
"@executable_path/../../../../Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "$(inherited).QLPreview";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "$(inherited).Preview";
|
||||
PRODUCT_NAME = "$(inherited) Preview Extension";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
@@ -744,21 +901,20 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CODE_SIGN_ENTITLEMENTS = QLThumbnail/QLThumbnail.entitlements;
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
"DEVELOPMENT_TEAM[sdk=macosx*]" = UY657LKNHJ;
|
||||
ENABLE_HARDENED_RUNTIME = YES;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_FILE = QLThumbnail/Info.plist;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = QLThumbnail;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = "$(PRODUCT_NAME) (debug)";
|
||||
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
"@executable_path/../../../../Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "$(inherited).QLThumbnail";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "$(inherited).Thumbnail";
|
||||
PRODUCT_NAME = "$(inherited) Thumbnail Extension";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
@@ -770,21 +926,20 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CODE_SIGN_ENTITLEMENTS = QLThumbnail/QLThumbnail.entitlements;
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
"DEVELOPMENT_TEAM[sdk=macosx*]" = UY657LKNHJ;
|
||||
ENABLE_HARDENED_RUNTIME = YES;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_FILE = QLThumbnail/Info.plist;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = QLThumbnail;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = "$(PRODUCT_NAME)";
|
||||
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
"@executable_path/../../../../Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "$(inherited).QLThumbnail";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "$(inherited).Thumbnail";
|
||||
PRODUCT_NAME = "$(inherited) Thumbnail Extension";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
@@ -795,6 +950,15 @@
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
54352E902EB6A79A0082F61D /* Build configuration list for PBXNativeTarget "AssetCarReader" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
54352E8E2EB6A79A0082F61D /* Debug */,
|
||||
54352E8F2EB6A79A0082F61D /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
54442BEF2E378B71008A870E /* Build configuration list for PBXProject "QLAppBundle" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
@@ -804,7 +968,7 @@
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
54442C012E378B71008A870E /* Build configuration list for PBXNativeTarget "QLAppBundle" */ = {
|
||||
54442C012E378B71008A870E /* Build configuration list for PBXNativeTarget "App" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
54442C022E378B71008A870E /* Debug */,
|
||||
@@ -813,7 +977,7 @@
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
54442C352E378BAF008A870E /* Build configuration list for PBXNativeTarget "QLPreview" */ = {
|
||||
54442C352E378BAF008A870E /* Build configuration list for PBXNativeTarget "QL Preview" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
54442C322E378BAF008A870E /* Debug */,
|
||||
@@ -822,7 +986,7 @@
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
54581FDE2EB29A0B0043A0B3 /* Build configuration list for PBXNativeTarget "QLThumbnail" */ = {
|
||||
54581FDE2EB29A0B0043A0B3 /* Build configuration list for PBXNativeTarget "QL Thumbnail" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
54581FDB2EB29A0B0043A0B3 /* Debug */,
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "54442C1F2E378BAF008A870E"
|
||||
BuildableName = "QLPreview.appex"
|
||||
BlueprintName = "QLPreview"
|
||||
BuildableName = "QLAppBundle Preview Extension.appex"
|
||||
BlueprintName = "QL Preview"
|
||||
ReferencedContainer = "container:QLAppBundle.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
@@ -32,7 +32,7 @@
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "54442BF32E378B71008A870E"
|
||||
BuildableName = "QLAppBundle.app"
|
||||
BlueprintName = "QLAppBundle"
|
||||
BlueprintName = "App"
|
||||
ReferencedContainer = "container:QLAppBundle.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
@@ -63,7 +63,7 @@
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "54442BF32E378B71008A870E"
|
||||
BuildableName = "QLAppBundle.app"
|
||||
BlueprintName = "QLAppBundle"
|
||||
BlueprintName = "App"
|
||||
ReferencedContainer = "container:QLAppBundle.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
@@ -82,7 +82,7 @@
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "54442BF32E378B71008A870E"
|
||||
BuildableName = "QLAppBundle.app"
|
||||
BlueprintName = "QLAppBundle"
|
||||
BlueprintName = "App"
|
||||
ReferencedContainer = "container:QLAppBundle.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
@@ -0,0 +1,97 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1640"
|
||||
wasCreatedForAppExtension = "YES"
|
||||
version = "2.0">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES"
|
||||
buildArchitectures = "Automatic">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "54581FCE2EB29A0B0043A0B3"
|
||||
BuildableName = "QLAppBundle Thumbnail Extension.appex"
|
||||
BlueprintName = "QL Thumbnail"
|
||||
ReferencedContainer = "container:QLAppBundle.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "54442BF32E378B71008A870E"
|
||||
BuildableName = "QLAppBundle.app"
|
||||
BlueprintName = "App"
|
||||
ReferencedContainer = "container:QLAppBundle.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
shouldAutocreateTestPlan = "YES">
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = ""
|
||||
selectedLauncherIdentifier = "Xcode.IDEFoundation.Launcher.PosixSpawn"
|
||||
launchStyle = "0"
|
||||
askForAppToLaunch = "Yes"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES"
|
||||
launchAutomaticallySubstyle = "2">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "54442BF32E378B71008A870E"
|
||||
BuildableName = "QLAppBundle.app"
|
||||
BlueprintName = "App"
|
||||
ReferencedContainer = "container:QLAppBundle.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
askForAppToLaunch = "Yes"
|
||||
launchAutomaticallySubstyle = "2">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "54442BF32E378B71008A870E"
|
||||
BuildableName = "QLAppBundle.app"
|
||||
BlueprintName = "App"
|
||||
ReferencedContainer = "container:QLAppBundle.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
||||
@@ -17,7 +17,7 @@
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "54442BF32E378B71008A870E"
|
||||
BuildableName = "QLAppBundle.app"
|
||||
BlueprintName = "QLAppBundle"
|
||||
BlueprintName = "App"
|
||||
ReferencedContainer = "container:QLAppBundle.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
@@ -46,7 +46,7 @@
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "54442BF32E378B71008A870E"
|
||||
BuildableName = "QLAppBundle.app"
|
||||
BlueprintName = "QLAppBundle"
|
||||
BlueprintName = "App"
|
||||
ReferencedContainer = "container:QLAppBundle.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
@@ -63,7 +63,7 @@
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "54442BF32E378B71008A870E"
|
||||
BuildableName = "QLAppBundle.app"
|
||||
BlueprintName = "QLAppBundle"
|
||||
BlueprintName = "App"
|
||||
ReferencedContainer = "container:QLAppBundle.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
<string>com.apple.itunes.ipa</string>
|
||||
<string>com.apple.application-and-system-extension</string>
|
||||
<string>com.apple.xcode.archive</string>
|
||||
<string>com.opa334.trollstore.tipa</string>
|
||||
<string>dyn.ah62d4rv4ge81k4puqe</string>
|
||||
</array>
|
||||
<key>QLSupportsSearchableItems</key>
|
||||
<false/>
|
||||
|
||||
@@ -3,7 +3,6 @@ import Quartz // QLPreviewingController
|
||||
import WebKit // WebView
|
||||
import os // OSLog
|
||||
|
||||
// show Console logs with subsystem:de.relikd.QLApps
|
||||
private let log = OSLog(subsystem: Bundle.main.bundleIdentifier!, category: "preview-plugin")
|
||||
|
||||
class PreviewViewController: NSViewController, QLPreviewingController {
|
||||
@@ -12,9 +11,26 @@ class PreviewViewController: NSViewController, QLPreviewingController {
|
||||
return NSNib.Name("PreviewViewController")
|
||||
}
|
||||
|
||||
/// Load resource file either from user documents dir (if exists) or app bundle (default).
|
||||
func bundleFile(filename: String, ext: String) throws -> String {
|
||||
if let appSupport = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first {
|
||||
let override = appSupport.appendingPathComponent(filename + "." + ext)
|
||||
if FileManager.default.fileExists(atPath: override.path) {
|
||||
return try String(contentsOfFile: override.path, encoding: .utf8)
|
||||
}
|
||||
// else: do NOT copy! Breaks on future updates
|
||||
}
|
||||
// else, load bundle file
|
||||
let path = Bundle.main.url(forResource: filename, withExtension: ext)
|
||||
return try String(contentsOf: path!, encoding: .utf8)
|
||||
}
|
||||
|
||||
func preparePreviewOfFile(at url: URL) async throws {
|
||||
let meta = MetaInfo(url)
|
||||
let html = HtmlGenerator(meta).applyHtmlTemplate()
|
||||
let html = PreviewGenerator(meta).generate(
|
||||
template: try bundleFile(filename: "template", ext: "html"),
|
||||
css: try bundleFile(filename: "style", ext: "css"),
|
||||
)
|
||||
// sure, we could use `WKWebView`, but that requires the `com.apple.security.network.client` entitlement
|
||||
//let web = WKWebView(frame: self.view.bounds)
|
||||
let web = WebView(frame: self.view.bounds)
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
<string>com.apple.itunes.ipa</string>
|
||||
<string>com.apple.application-and-system-extension</string>
|
||||
<string>com.apple.xcode.archive</string>
|
||||
<string>com.opa334.trollstore.tipa</string>
|
||||
<string>dyn.ah62d4rv4ge81k4puqe</string>
|
||||
</array>
|
||||
<key>QLThumbnailMinimumDimension</key>
|
||||
<integer>16</integer>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import QuickLookThumbnailing
|
||||
import os // OSLog
|
||||
|
||||
// show Console logs with subsystem:de.relikd.QLApps
|
||||
private let log = OSLog(subsystem: Bundle.main.bundleIdentifier!, category: "thumbnail-plugin")
|
||||
|
||||
extension QLThumbnailReply {
|
||||
@@ -18,12 +17,15 @@ extension QLThumbnailReply {
|
||||
|
||||
class ThumbnailProvider: QLThumbnailProvider {
|
||||
|
||||
// TODO: sadly, this does not seem to work for .xarchive and .appex
|
||||
// TODO: sadly, this does not seem to work for .xcarchive and .appex
|
||||
// Probably overwritten by Apple somehow
|
||||
|
||||
override func provideThumbnail(for request: QLFileThumbnailRequest, _ handler: @escaping (QLThumbnailReply?, Error?) -> Void) {
|
||||
let meta = MetaInfo(request.fileURL)
|
||||
let img = AppIcon(meta).extractImage(from: meta.readPlistApp()).withRoundCorners()
|
||||
guard let appPlist = meta.readPlistApp() else {
|
||||
return
|
||||
}
|
||||
let img = AppIcon(meta).extractImage(from: appPlist).withRoundCorners()
|
||||
|
||||
// First way: Draw the thumbnail into the current context, set up with UIKit's coordinate system.
|
||||
let reply = QLThumbnailReply(contextSize: request.maximumSize, currentContextDrawing: { () -> Bool in
|
||||
@@ -39,3 +41,4 @@ class ThumbnailProvider: QLThumbnailProvider {
|
||||
reply.setFlavor(meta.type == .Archive ? 12 : 0) // .archive looks like "in development"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
37
README.md
37
README.md
@@ -6,7 +6,7 @@
|
||||
QLAppBundle
|
||||
===========
|
||||
|
||||
A QuickLook plugin for app bundles (`.ipa`, `.appex`, `.xcarchive`).
|
||||
A QuickLook plugin for app bundles (`.ipa`, `.tipa`, `.appex`, `.xcarchive`).
|
||||
|
||||

|
||||
|
||||
@@ -24,31 +24,30 @@ I merely want things to be done.
|
||||
Also, I've removed support for provisioning profiles (`.mobileprovision`, `.provisionprofile`) to focus on app bundles.
|
||||
|
||||
|
||||
## ToDO
|
||||
|
||||
## ToDo
|
||||
|
||||
- [ ] support for `.apk` files
|
||||
|
||||
|
||||
|
||||
## Features
|
||||
|
||||
### Customize HTML / CSS
|
||||
|
||||
1. Right click on the app and select "Show Package Contents"
|
||||
2. Copy `Contents/Resources/template.html` (or `style.css`)
|
||||
3. Open `~/Library/Containers/de.relikd.QLAppBundle.Preview/Data/Documents/`
|
||||
4. Paste the previous file and modify it to your liking
|
||||
5. `QLAppBundle` will use the new file from now on
|
||||
|
||||
|
||||
|
||||
## Development notes
|
||||
|
||||
If you encounter compile errors like:
|
||||
### Debug
|
||||
|
||||
```
|
||||
Command SwiftEmitModule failed with a nonzero exit code
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```
|
||||
Could not build Objective-C module 'ExtensionFoundation'
|
||||
```
|
||||
|
||||
remove the `SYSTEM_FRAMEWORK_SEARCH_PATHS` attribute from Project > Build Settings then try to compile again (it will fail).
|
||||
Afterwards, restore the value in the attribute.
|
||||
Now, the build index should be up-to-date and the app should compile fine.
|
||||
|
||||
I havent figured out the exact issue, consider it a workaround.
|
||||
It should only be necessary once (or if you delete your `DerivedData` folder).
|
||||
You can show Console logs with `subsystem:de.relikd.QLAppBundle`
|
||||
|
||||
|
||||
[1]: https://github.com/ealeksandrov/ProvisionQL
|
||||
|
||||
@@ -5,59 +5,23 @@
|
||||
<style>__CSS__</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="app __AppInfoHidden__">
|
||||
<h1>__AppInfoTitle__</h1>
|
||||
<div class="app">
|
||||
<h1>__QuickLookTitle__</h1>
|
||||
<div class="floatLeft icon"><img alt="App icon" src="data:image/png;base64,__AppIcon__"/></div>
|
||||
<div class="floatLeft info">
|
||||
Name: <strong>__CFBundleName__</strong><br />
|
||||
Version: __CFBundleShortVersionString__ (__CFBundleVersion__)<br />
|
||||
BundleId: __CFBundleIdentifier__<br />
|
||||
<div class="__ExtensionTypeHidden__">
|
||||
Extension type: __ExtensionType__<br />
|
||||
Name: <strong>__AppName__</strong><br />
|
||||
Version: __AppVersion__ (__AppBuildVer__)<br />
|
||||
BundleId: __AppId__<br />
|
||||
<div class="__AppExtensionTypeHidden__">
|
||||
Extension type: __AppExtensionType__<br />
|
||||
</div>
|
||||
DeviceFamily: __UIDeviceFamily__<br />
|
||||
SDK: __DTSDKName__<br />
|
||||
Minimum OS Version: __MinimumOSVersion__<br />
|
||||
DeviceFamily: __AppDeviceFamily__<br />
|
||||
SDK: __AppSDK__<br />
|
||||
Minimum OS Version: __AppMinOS__<br />
|
||||
</div>
|
||||
<br class="clear" />
|
||||
<h2>App Transport Security</h2>
|
||||
__AppTransportSecurityFormatted__
|
||||
</div>
|
||||
|
||||
<div class="__ProvisionHidden__">
|
||||
<div class="__AppInfoHidden__">
|
||||
<h2>Provisioning</h2>
|
||||
Profile name: <strong>__ProfileName__</strong><br />
|
||||
</div>
|
||||
<div class="__ProvisionTitleHidden__">
|
||||
<h1><span class="__ExpStatus__">__ProfileName__</span></h1>
|
||||
</div>
|
||||
|
||||
Profile UUID: __ProfileUUID__<br />
|
||||
Profile Type: __ProfilePlatform__ __ProfileType__<br />
|
||||
Team: __TeamName__ (__TeamIds__)<br />
|
||||
Creation date: __CreationDateFormatted__<br />
|
||||
Expiration Date: <strong><span class="__ExpStatus__">__ExpirationDateFormatted__</span></strong><br />
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h2>Entitlements</h2>
|
||||
<div class="__EntitlementsWarningHidden__ warning">
|
||||
<strong>Entitlements extraction failed.</strong>
|
||||
</div>
|
||||
__EntitlementsFormatted__
|
||||
</div>
|
||||
|
||||
<div class="__ProvisionHidden__">
|
||||
<h2>Developer Certificates</h2>
|
||||
__DeveloperCertificatesFormatted__
|
||||
</div>
|
||||
|
||||
<div class="__ProvisionHidden__">
|
||||
<h2>Devices (__ProvisionedDevicesCount__)</h2>
|
||||
__ProvisionedDevicesFormatted__
|
||||
</div>
|
||||
|
||||
|
||||
<div class="__iTunesHidden__">
|
||||
<h2>iTunes Metadata</h2>
|
||||
iTunesId: __iTunesId__<br />
|
||||
@@ -69,15 +33,48 @@
|
||||
Purchased: __iTunesPurchaseDate__<br />
|
||||
Price: __iTunesPrice__<br />
|
||||
</div>
|
||||
|
||||
|
||||
<div>
|
||||
<h2>App Transport Security</h2>
|
||||
__AppTransportSecurity__
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h2>Entitlements</h2>
|
||||
<div class="warning __EntitlementsWarningHidden__">
|
||||
<strong>Entitlements extraction failed.</strong>
|
||||
</div>
|
||||
__EntitlementsDict__
|
||||
</div>
|
||||
|
||||
<div class="__ProvisionHidden__">
|
||||
<h2>Provisioning</h2>
|
||||
Profile name: <strong>__ProvisionProfileName__</strong><br />
|
||||
Profile UUID: __ProvisionProfileId__<br />
|
||||
Profile Type: __ProvisionProfilePlatform__ __ProvisionProfileType__<br />
|
||||
Team: __ProvisionTeamName__ (__ProvisionTeamIds__)<br />
|
||||
Creation date: __ProvisionCreateDate__<br />
|
||||
Expiration Date: <strong><span class="__ProvisionExpireStatus__">__ProvisionExpireDate__</span></strong><br />
|
||||
</div>
|
||||
|
||||
<div class="__ProvisionHidden__">
|
||||
<h2>Developer Certificates</h2>
|
||||
__ProvisionDevelopCertificates__
|
||||
</div>
|
||||
|
||||
<div class="__ProvisionHidden__">
|
||||
<h2>Devices (__ProvisionDeviceCount__)</h2>
|
||||
__ProvisionDeviceIds__
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h2>File info</h2>
|
||||
__FileName__<br />
|
||||
__FileInfo__<br />
|
||||
__FileSize__, Modified __FileModified__<br />
|
||||
</div>
|
||||
|
||||
<div class="footer">
|
||||
<p>__SrcAppName__ v__BundleShortVersionString__ (__BundleVersion__) (Github: <a href="__SrcLinkUrl__">__SrcLinkName__</a>)</p>
|
||||
<p>__SrcAppName__ v__SrcVersion__ (__SrcBuildVer__) (Github: <a href="__SrcLinkUrl__">__SrcLinkName__</a>)</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
BIN
screenshot.png
Normal file
BIN
screenshot.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 251 KiB |
@@ -1,5 +1,6 @@
|
||||
import Foundation
|
||||
import AppKit // NSImage
|
||||
import AssetCarReader // CarReader
|
||||
import os // OSLog
|
||||
|
||||
private let log = OSLog(subsystem: Bundle.main.bundleIdentifier!, category: "AppIcon")
|
||||
@@ -14,7 +15,7 @@ struct AppIcon {
|
||||
|
||||
/// Try multiple methods to extract image.
|
||||
/// This method will always return an image even if none is found, in which case it returns the default image.
|
||||
func extractImage(from appPlist: PlistDict?) -> NSImage {
|
||||
func extractImage(from appPlist: PlistDict) -> NSImage {
|
||||
// no need to unwrap the plist, and most .ipa should include the Artwork anyway
|
||||
if meta.type == .IPA {
|
||||
if let data = meta.zipFile!.unzipFile("iTunesArtwork") {
|
||||
@@ -50,6 +51,14 @@ struct AppIcon {
|
||||
let iconURL = Bundle.main.url(forResource: "defaultIcon", withExtension: "png")!
|
||||
return NSImage(contentsOf: iconURL)!
|
||||
}
|
||||
|
||||
/// Extract an image from `Assets.car`
|
||||
func imageFromAssetsCar(_ imageName: String) -> NSImage? {
|
||||
guard let data = meta.readPayloadFile("Assets.car") else {
|
||||
return nil
|
||||
}
|
||||
return CarReader(data)?.imageFromAssetsCar(imageName)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -59,8 +68,7 @@ extension AppIcon {
|
||||
/// Parse app plist to find the bundle icon filename.
|
||||
/// @param appPlist If `nil`, will load plist on the fly (used for thumbnail)
|
||||
/// @return Filenames which do not necessarily exist on filesystem. This may include `@2x` and/or no file extension.
|
||||
private func iconNamesFromPlist(_ appPlist: PlistDict?) -> [String] {
|
||||
let appPlist = appPlist == nil ? meta.readPlistApp()! : appPlist!
|
||||
private func iconNamesFromPlist(_ appPlist: PlistDict) -> [String] {
|
||||
// Check for CFBundleIcons (since 5.0)
|
||||
if let icons = unpackNameListFromPlistDict(appPlist["CFBundleIcons"]), !icons.isEmpty {
|
||||
return icons
|
||||
|
||||
@@ -31,7 +31,7 @@ struct MetaInfo {
|
||||
var zipFile: ZipFile? = nil
|
||||
|
||||
switch self.UTI {
|
||||
case "com.apple.itunes.ipa":
|
||||
case "com.apple.itunes.ipa", "com.opa334.trollstore.tipa", "dyn.ah62d4rv4ge81k4puqe":
|
||||
self.type = FileType.IPA;
|
||||
zipFile = ZipFile(self.url.path);
|
||||
case "com.apple.xcode.archive":
|
||||
|
||||
@@ -22,7 +22,7 @@ private func recursiveDict(_ dictionary: [String: Any], withReplacements replace
|
||||
return output
|
||||
}
|
||||
|
||||
extension HtmlGenerator {
|
||||
extension PreviewGenerator {
|
||||
/// @return List of ATS flags.
|
||||
private func formattedAppTransportSecurity(_ appPlist: PlistDict) -> String {
|
||||
if let value = appPlist["NSAppTransportSecurity"] as? PlistDict {
|
||||
@@ -57,15 +57,7 @@ extension HtmlGenerator {
|
||||
}
|
||||
|
||||
/// Process info stored in `Info.plist`
|
||||
mutating func procAppInfo(_ appPlist: PlistDict?) {
|
||||
guard let appPlist else {
|
||||
self.apply([
|
||||
"AppInfoHidden": "hiddenDiv",
|
||||
"ProvisionTitleHidden": "",
|
||||
])
|
||||
return
|
||||
}
|
||||
|
||||
mutating func procAppInfo(_ appPlist: PlistDict) {
|
||||
var platforms = (appPlist["UIDeviceFamily"] as? [Int])?.compactMap({
|
||||
switch $0 {
|
||||
case 1: return "iPhone"
|
||||
@@ -83,21 +75,18 @@ extension HtmlGenerator {
|
||||
|
||||
let extensionType = (appPlist["NSExtension"] as? PlistDict)?["NSExtensionPointIdentifier"] as? String
|
||||
self.apply([
|
||||
"AppInfoHidden": "",
|
||||
"ProvisionTitleHidden": "hiddenDiv",
|
||||
"AppName": appPlist["CFBundleDisplayName"] as? String ?? appPlist["CFBundleName"] as? String ?? "",
|
||||
"AppVersion": appPlist["CFBundleShortVersionString"] as? String ?? "",
|
||||
"AppBuildVer": appPlist["CFBundleVersion"] as? String ?? "",
|
||||
"AppId": appPlist["CFBundleIdentifier"] as? String ?? "",
|
||||
|
||||
"CFBundleName": appPlist["CFBundleDisplayName"] as? String ?? appPlist["CFBundleName"] as? String ?? "",
|
||||
"CFBundleShortVersionString": appPlist["CFBundleShortVersionString"] as? String ?? "",
|
||||
"CFBundleVersion": appPlist["CFBundleVersion"] as? String ?? "",
|
||||
"CFBundleIdentifier": appPlist["CFBundleIdentifier"] as? String ?? "",
|
||||
"AppExtensionTypeHidden": extensionType != nil ? "" : CLASS_HIDDEN,
|
||||
"AppExtensionType": extensionType ?? "",
|
||||
|
||||
"ExtensionTypeHidden": extensionType != nil ? "" : "hiddenDiv",
|
||||
"ExtensionType": extensionType ?? "",
|
||||
|
||||
"UIDeviceFamily": platforms ?? "",
|
||||
"DTSDKName": appPlist["DTSDKName"] as? String ?? "",
|
||||
"MinimumOSVersion": minVersion,
|
||||
"AppTransportSecurityFormatted": formattedAppTransportSecurity(appPlist),
|
||||
"AppDeviceFamily": platforms ?? "",
|
||||
"AppSDK": appPlist["DTSDKName"] as? String ?? "",
|
||||
"AppMinOS": minVersion,
|
||||
"AppTransportSecurity": formattedAppTransportSecurity(appPlist),
|
||||
])
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import Foundation
|
||||
|
||||
extension HtmlGenerator {
|
||||
extension PreviewGenerator {
|
||||
/// Search for app binary and run `codesign` on it.
|
||||
private func readEntitlements(_ meta: MetaInfo, _ bundleExecutable: String?) -> Entitlements {
|
||||
guard let bundleExecutable else {
|
||||
@@ -24,13 +24,13 @@ extension HtmlGenerator {
|
||||
}
|
||||
|
||||
/// Process compiled binary and provision plist to extract `Entitlements`
|
||||
mutating func procEntitlements(_ meta: MetaInfo, _ appPlist: PlistDict?, _ provisionPlist: PlistDict?) {
|
||||
var entitlements = readEntitlements(meta, appPlist?["CFBundleExecutable"] as? String)
|
||||
mutating func procEntitlements(_ meta: MetaInfo, _ appPlist: PlistDict, _ provisionPlist: PlistDict?) {
|
||||
var entitlements = readEntitlements(meta, appPlist["CFBundleExecutable"] as? String)
|
||||
entitlements.applyFallbackIfNeeded(provisionPlist?["Entitlements"] as? PlistDict)
|
||||
|
||||
self.apply([
|
||||
"EntitlementsWarningHidden": entitlements.hasError ? "" : "hiddenDiv",
|
||||
"EntitlementsFormatted": entitlements.html ?? "No Entitlements",
|
||||
"EntitlementsWarningHidden": entitlements.hasError ? "" : CLASS_HIDDEN,
|
||||
"EntitlementsDict": entitlements.html ?? "No Entitlements",
|
||||
])
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import Foundation
|
||||
|
||||
extension HtmlGenerator {
|
||||
extension PreviewGenerator {
|
||||
/// Calculate file / folder size.
|
||||
private func getFileSize(_ path: String) -> Int64 {
|
||||
var isDir: ObjCBool = false
|
||||
@@ -17,16 +17,11 @@ extension HtmlGenerator {
|
||||
|
||||
/// Process meta information about the file itself. Like file size and last modification.
|
||||
mutating func procFileInfo(_ url: URL) {
|
||||
let formattedValue : String
|
||||
if let attrs = try? FileManager.default.attributesOfItem(atPath: url.path) {
|
||||
let size = ByteCountFormatter.string(fromByteCount: getFileSize(url.path), countStyle: .file)
|
||||
formattedValue = "\(size), Modified \((attrs[.modificationDate] as! Date).mediumFormat())"
|
||||
} else {
|
||||
formattedValue = ""
|
||||
}
|
||||
let attrs = try? FileManager.default.attributesOfItem(atPath: url.path)
|
||||
self.apply([
|
||||
"FileName": escapeXML(url.lastPathComponent),
|
||||
"FileInfo": formattedValue,
|
||||
"FileSize": ByteCountFormatter.string(fromByteCount: getFileSize(url.path), countStyle: .file),
|
||||
"FileModified": (attrs?[.modificationDate] as? Date)?.mediumFormat() ?? "",
|
||||
])
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,14 @@
|
||||
import Foundation
|
||||
|
||||
extension HtmlGenerator {
|
||||
extension PreviewGenerator {
|
||||
/// Process meta information about the plugin. Like version and debug flag.
|
||||
mutating func procFooterInfo() {
|
||||
self.apply([
|
||||
"SrcAppName": "QLAppBundle",
|
||||
"SrcLinkUrl": "https://github.com/relikd/QLAppBundle",
|
||||
"SrcLinkName": "relikd/QLAppBundle",
|
||||
"BundleShortVersionString": Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "",
|
||||
"BundleVersion": Bundle.main.infoDictionary?["CFBundleVersion"] as? String ?? "",
|
||||
"SrcVersion": Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "",
|
||||
"SrcBuildVer": Bundle.main.infoDictionary?["CFBundleVersion"] as? String ?? "",
|
||||
])
|
||||
#if DEBUG
|
||||
self.data["SrcAppName"]! += " (debug)"
|
||||
@@ -26,7 +26,7 @@ extension MetaInfo {
|
||||
}
|
||||
|
||||
|
||||
extension HtmlGenerator {
|
||||
extension PreviewGenerator {
|
||||
|
||||
// MARK: - Certificates
|
||||
|
||||
@@ -114,7 +114,7 @@ extension HtmlGenerator {
|
||||
/// Process info stored in `embedded.mobileprovision`
|
||||
mutating func procProvision(_ provisionPlist: PlistDict?, isOSX: Bool) {
|
||||
guard let provisionPlist else {
|
||||
self.apply(["ProvisionHidden": "hiddenDiv"])
|
||||
self.apply(["ProvisionHidden": CLASS_HIDDEN])
|
||||
return
|
||||
}
|
||||
|
||||
@@ -125,21 +125,21 @@ extension HtmlGenerator {
|
||||
|
||||
self.apply([
|
||||
"ProvisionHidden": "",
|
||||
"ProfileName": provisionPlist["Name"] as? String ?? "",
|
||||
"ProfileUUID": provisionPlist["UUID"] as? String ?? "",
|
||||
"TeamName": provisionPlist["TeamName"] as? String ?? "<em>Team name not available</em>",
|
||||
"TeamIds": (provisionPlist["TeamIdentifier"] as? [String])?.joined(separator: ", ") ?? "<em>Team ID not available</em>",
|
||||
"CreationDateFormatted": creationDate?.formattedCreationDate() ?? "",
|
||||
"ExpirationDateFormatted": expireDate?.formattedExpirationDate() ?? "",
|
||||
"ExpStatus": ExpirationStatus(expireDate).cssClass(),
|
||||
"ProvisionProfileName": provisionPlist["Name"] as? String ?? "",
|
||||
"ProvisionProfileId": provisionPlist["UUID"] as? String ?? "",
|
||||
"ProvisionTeamName": provisionPlist["TeamName"] as? String ?? "<em>Team name not available</em>",
|
||||
"ProvisionTeamIds": (provisionPlist["TeamIdentifier"] as? [String])?.joined(separator: ", ") ?? "<em>Team ID not available</em>",
|
||||
"ProvisionCreateDate": creationDate?.formattedCreationDate() ?? "",
|
||||
"ProvisionExpireDate": expireDate?.formattedExpirationDate() ?? "",
|
||||
"ProvisionExpireStatus": ExpirationStatus(expireDate).cssClass(),
|
||||
|
||||
"ProfilePlatform": isOSX ? "Mac" : "iOS",
|
||||
"ProfileType": stringForProfileType(provisionPlist, isOSX: isOSX),
|
||||
"ProvisionProfilePlatform": isOSX ? "Mac" : "iOS",
|
||||
"ProvisionProfileType": stringForProfileType(provisionPlist, isOSX: isOSX),
|
||||
|
||||
"ProvisionedDevicesCount": devices.isEmpty ? "No Devices" : "\(devices.count) Device\(devices.count == 1 ? "" : "s")",
|
||||
"ProvisionedDevicesFormatted": devices.isEmpty ? "Distribution Profile" : formatAsTable(devices, header: ["", "UDID"]),
|
||||
"ProvisionDeviceCount": devices.isEmpty ? "No Devices" : "\(devices.count) Device\(devices.count == 1 ? "" : "s")",
|
||||
"ProvisionDeviceIds": devices.isEmpty ? "Distribution Profile" : formatAsTable(devices, header: ["", "UDID"]),
|
||||
|
||||
"DeveloperCertificatesFormatted": certs.isEmpty ? "No Developer Certificates" : formatAsTable(certs),
|
||||
"ProvisionDevelopCertificates": certs.isEmpty ? "No Developer Certificates" : formatAsTable(certs),
|
||||
])
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,7 @@ extension MetaInfo {
|
||||
}
|
||||
|
||||
|
||||
extension HtmlGenerator {
|
||||
extension PreviewGenerator {
|
||||
/// Concatenate all (sub)genres into a comma separated list.
|
||||
private func formattedGenres(_ itunesPlist: PlistDict) -> String {
|
||||
var genres: [String] = []
|
||||
@@ -35,7 +35,7 @@ extension HtmlGenerator {
|
||||
/// Process info stored in `iTunesMetadata.plist`
|
||||
mutating func procItunesMeta(_ itunesPlist: PlistDict?) {
|
||||
guard let itunesPlist else {
|
||||
self.apply(["iTunesHidden": "hiddenDiv"])
|
||||
self.apply(["iTunesHidden": CLASS_HIDDEN])
|
||||
return
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ extension HtmlGenerator {
|
||||
}
|
||||
self.apply([
|
||||
"iTunesHidden": "",
|
||||
"iTunesId": (itunesPlist["itemId"] as? Int)?.description ?? "", // description]
|
||||
"iTunesId": (itunesPlist["itemId"] as? Int)?.description ?? "",
|
||||
"iTunesName": itunesPlist["itemName"] as? String ?? "",
|
||||
"iTunesGenres": formattedGenres(itunesPlist),
|
||||
"iTunesReleaseDate": releaseDate?.mediumFormat() ?? "",
|
||||
@@ -1,16 +1,20 @@
|
||||
import Foundation
|
||||
|
||||
struct HtmlGenerator {
|
||||
let CLASS_HIDDEN = "hiddenDiv"
|
||||
|
||||
struct PreviewGenerator {
|
||||
var data: [String: String] = [:] // used for TAG replacements
|
||||
let meta: MetaInfo
|
||||
|
||||
init(_ meta: MetaInfo) {
|
||||
self.meta = meta
|
||||
let plistApp = meta.readPlistApp()
|
||||
guard let plistApp = meta.readPlistApp() else {
|
||||
return
|
||||
}
|
||||
let plistItunes = meta.readPlistItunes()
|
||||
let plistProvision = meta.readPlistProvision()
|
||||
|
||||
data["AppInfoTitle"] = stringForFileType(meta)
|
||||
data["QuickLookTitle"] = stringForFileType(meta)
|
||||
|
||||
procAppInfo(plistApp)
|
||||
procItunesMeta(plistItunes)
|
||||
@@ -20,9 +24,6 @@ struct HtmlGenerator {
|
||||
procFooterInfo()
|
||||
// App Icon (last, because the image uses a lot of memory)
|
||||
data["AppIcon"] = AppIcon(meta).extractImage(from: plistApp).withRoundCorners().asBase64()
|
||||
// insert CSS styles
|
||||
let cssURL = Bundle.main.url(forResource: "style", withExtension: "css")!
|
||||
data["CSS"] = try! String(contentsOf: cssURL, encoding: .utf8)
|
||||
}
|
||||
|
||||
mutating func apply(_ values: [String: String]) {
|
||||
@@ -39,33 +40,34 @@ struct HtmlGenerator {
|
||||
}
|
||||
|
||||
/// prepare html, replace values
|
||||
func applyHtmlTemplate() -> String {
|
||||
let templateURL = Bundle.main.url(forResource: "template", withExtension: "html")!
|
||||
let html = try! String(contentsOf: templateURL, encoding: .utf8)
|
||||
|
||||
// this is less efficient
|
||||
// for (key, value) in templateValues {
|
||||
// html = html.replacingOccurrences(of: "__\(key)__", with: value)
|
||||
// }
|
||||
|
||||
func generate(template html: String, css: String) -> String {
|
||||
let templateValues = data.merging(["CSS": css]) { (_, new) in new }
|
||||
return html.regexReplace("__([^ _]{1,40}?)__") { templateValues[$0] }
|
||||
}
|
||||
}
|
||||
|
||||
extension String {
|
||||
/// Replace regex-pattern with custom replacement.
|
||||
/// @param pattern must include a regex group. (e.g. "a(b)c")
|
||||
func regexReplace(_ pattern: String, with fn: (_ match: String) -> String?) -> String {
|
||||
var rv = ""
|
||||
var prevLoc = html.startIndex
|
||||
let regex = try! NSRegularExpression(pattern: "__[^ _]{1,40}?__")
|
||||
regex.enumerateMatches(in: html, range: NSRange(location: 0, length: html.count), using: { match, flags, stop in
|
||||
let start = html.index(html.startIndex, offsetBy: match!.range.lowerBound)
|
||||
let key = String(html[html.index(start, offsetBy: 2) ..< html.index(start, offsetBy: match!.range.length - 2)])
|
||||
var prevLoc = self.startIndex
|
||||
let regex = try! NSRegularExpression(pattern: pattern)
|
||||
regex.enumerateMatches(in: self, range: NSRange(location: 0, length: self.count), using: { match, flags, stop in
|
||||
let start = self.index(self.startIndex, offsetBy: match!.range.lowerBound)
|
||||
// append unrelated text up to this key
|
||||
rv.append(contentsOf: html[prevLoc ..< start])
|
||||
prevLoc = html.index(start, offsetBy: match!.range.length)
|
||||
rv.append(contentsOf: self[prevLoc ..< start])
|
||||
prevLoc = self.index(start, offsetBy: match!.range.length)
|
||||
// append key if exists (else remove template-key)
|
||||
if let value = data[key] {
|
||||
let key = String(self[Range(match!.range(at: 1), in: self)!])
|
||||
if let value = fn(key) {
|
||||
rv.append(value)
|
||||
} else {
|
||||
// os_log(.debug, log: log, "unknown template key: %{public}@", key)
|
||||
}
|
||||
})
|
||||
// append remaining text
|
||||
rv.append(contentsOf: html[prevLoc ..< html.endIndex])
|
||||
rv.append(contentsOf: self[prevLoc ..< self.endIndex])
|
||||
return rv
|
||||
}
|
||||
}
|
||||
@@ -175,7 +175,6 @@ func unzipFileEntry(_ path: String, _ entry: ZipEntry) -> Data? {
|
||||
}
|
||||
fp.seek(toFileOffset: UInt64(entry.offset))
|
||||
let file_record = ZIP_LocalFile(fp.readData(ofLength: ZIP_LocalFile.LENGTH))
|
||||
os_log(.debug, log: log, "header: %{public}@ vs %{public}@", String(describing: file_record), String(describing: entry))
|
||||
|
||||
// central directory size and local file size may differ! use local file for ground truth
|
||||
let dataOffset = Int(entry.offset) + ZIP_LocalFile.LENGTH + Int(file_record.fileNameLength) + Int(file_record.extraFieldLength)
|
||||
|
||||
Reference in New Issue
Block a user