4 Commits

Author SHA1 Message Date
relikd
879a12f912 feat: support for .tipa 2025-10-30 19:06:08 +01:00
relikd
e4d421d4e0 doc: add Console instructions to readme 2025-10-30 18:52:33 +01:00
relikd
e2f65b540a chore: rm os_log 2025-10-30 18:42:02 +01:00
relikd
5788b098e9 chore: add screenshot 2025-10-30 18:34:43 +01:00
10 changed files with 58 additions and 20 deletions

View File

@@ -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>

View File

@@ -21,7 +21,6 @@
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 */; };
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 */; };
@@ -41,6 +40,7 @@
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 */; };
547F52F92EB2CBAB002B6D5F /* Date+Format.swift in Sources */ = {isa = PBXBuildFile; fileRef = 547F52F82EB2CBAB002B6D5F /* Date+Format.swift */; };
54AE5BFF2EB3DB1000B4CFC7 /* ThumbnailProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54AE5BFD2EB3DB1000B4CFC7 /* ThumbnailProvider.swift */; };
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 */; };
@@ -85,6 +85,7 @@
5405CF642EA1376B00613856 /* Zip.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Zip.swift; sourceTree = "<group>"; };
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>"; };
543FE5772EB3DAA20059F98B /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
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; };
54442C222E378BAF008A870E /* Quartz.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Quartz.framework; path = System/Library/Frameworks/Quartz.framework; sourceTree = SDKROOT; };
@@ -98,9 +99,6 @@
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; };
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>"; };
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>"; };
@@ -114,6 +112,9 @@
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; };
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>"; };
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>"; };
@@ -196,7 +197,7 @@
54D3A6F42EA46069001EF4F6 /* resources */,
54442C6F2E378BDD008A870E /* App */,
54442C782E378BE0008A870E /* QLPreview */,
545820202EB29B3D0043A0B3 /* QLThumbnail */,
54AE5BFE2EB3DB1000B4CFC7 /* QLThumbnail */,
54442C212E378BAF008A870E /* Frameworks */,
54442BF52E378B71008A870E /* Products */,
);
@@ -215,6 +216,7 @@
54442C212E378BAF008A870E /* Frameworks */ = {
isa = PBXGroup;
children = (
543FE5772EB3DAA20059F98B /* Foundation.framework */,
54E087572EB148E700979D91 /* WebKit.framework */,
54E087552EB148DF00979D91 /* Security.framework */,
54E087532EB148DB00979D91 /* QuickLook.framework */,
@@ -253,12 +255,12 @@
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>";
@@ -458,8 +460,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;
@@ -533,7 +535,7 @@
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1086;
CURRENT_PROJECT_VERSION = 1120;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = UY657LKNHJ;
ENABLE_STRICT_OBJC_MSGSEND = YES;
@@ -556,7 +558,7 @@
GCC_WARN_UNUSED_VARIABLE = YES;
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
MACOSX_DEPLOYMENT_TARGET = 10.15;
MARKETING_VERSION = 1.0.0;
MARKETING_VERSION = 1.1.0;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
@@ -603,7 +605,7 @@
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1086;
CURRENT_PROJECT_VERSION = 1120;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = UY657LKNHJ;
ENABLE_NS_ASSERTIONS = NO;
@@ -621,7 +623,7 @@
GCC_WARN_UNUSED_VARIABLE = YES;
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
MACOSX_DEPLOYMENT_TARGET = 10.15;
MARKETING_VERSION = 1.0.0;
MARKETING_VERSION = 1.1.0;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = de.relikd.QLAppBundle;

View File

@@ -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/>

View File

@@ -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 {

View File

@@ -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>

View File

@@ -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,7 +17,7 @@ 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) {
@@ -39,3 +38,4 @@ class ThumbnailProvider: QLThumbnailProvider {
reply.setFlavor(meta.type == .Archive ? 12 : 0) // .archive looks like "in development"
}
}

View File

@@ -6,7 +6,7 @@
QLAppBundle
===========
A QuickLook plugin for app bundles (`.ipa`, `.appex`, `.xcarchive`).
A QuickLook plugin for app bundles (`.ipa`, `.tipa`, `.appex`, `.xcarchive`).
![screenshot](screenshot.png)
@@ -31,6 +31,14 @@ Also, I've removed support for provisioning profiles (`.mobileprovision`, `.prov
## Development notes
### Debug
You can show Console logs with `subsystem:de.relikd.QLAppBundle`
### Compile errors
If you encounter compile errors like:
```
@@ -43,6 +51,8 @@ or
Could not build Objective-C module 'ExtensionFoundation'
```
or `ThumbnailProvider` is throwing lots of errors for undefined classes:
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.

BIN
screenshot.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 251 KiB

View File

@@ -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":

View File

@@ -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)