feat: thumbnail icon
This commit is contained in:
@@ -21,6 +21,18 @@
|
|||||||
545459C52EA469EA002892E5 /* template.html in Resources */ = {isa = PBXBuildFile; fileRef = 54D3A6F32EA4603B001EF4F6 /* template.html */; };
|
545459C52EA469EA002892E5 /* template.html in Resources */ = {isa = PBXBuildFile; fileRef = 54D3A6F32EA4603B001EF4F6 /* template.html */; };
|
||||||
545459C72EA4773A002892E5 /* AppIcon+Car.swift in Sources */ = {isa = PBXBuildFile; fileRef = 545459C62EA4773A002892E5 /* AppIcon+Car.swift */; };
|
545459C72EA4773A002892E5 /* AppIcon+Car.swift in Sources */ = {isa = PBXBuildFile; fileRef = 545459C62EA4773A002892E5 /* AppIcon+Car.swift */; };
|
||||||
545459C92EA47C37002892E5 /* Plist.swift in Sources */ = {isa = PBXBuildFile; fileRef = 545459C82EA47C37002892E5 /* Plist.swift */; };
|
545459C92EA47C37002892E5 /* Plist.swift in Sources */ = {isa = PBXBuildFile; fileRef = 545459C82EA47C37002892E5 /* Plist.swift */; };
|
||||||
|
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, ); }; };
|
||||||
|
54581FE42EB29A2B0043A0B3 /* CoreUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 54D3A6F52EA4610B001EF4F6 /* CoreUI.framework */; };
|
||||||
|
54581FEF2EB29A570043A0B3 /* Shared.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5405CF5D2EA1199B00613856 /* Shared.swift */; };
|
||||||
|
54581FF02EB29A5E0043A0B3 /* AppIcon.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54D3A6ED2EA39CC6001EF4F6 /* AppIcon.swift */; };
|
||||||
|
54581FF12EB29A620043A0B3 /* AppIcon+Car.swift in Sources */ = {isa = PBXBuildFile; fileRef = 545459C62EA4773A002892E5 /* AppIcon+Car.swift */; };
|
||||||
|
54581FF72EB29A820043A0B3 /* Zip.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5405CF642EA1376B00613856 /* Zip.swift */; };
|
||||||
|
54581FFD2EB29AB70043A0B3 /* Plist.swift in Sources */ = {isa = PBXBuildFile; fileRef = 545459C82EA47C37002892E5 /* Plist.swift */; };
|
||||||
|
545820032EB29B0A0043A0B3 /* RoundedIcon.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54D3A6EF2EA3F49F001EF4F6 /* RoundedIcon.swift */; };
|
||||||
|
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 */; };
|
5469E11D2EA5930C00D46CE7 /* Entitlements.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5469E11C2EA5930C00D46CE7 /* Entitlements.swift */; };
|
||||||
54D3A6EC2EA31B52001EF4F6 /* AppCategories.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54D3A6EB2EA31B52001EF4F6 /* AppCategories.swift */; };
|
54D3A6EC2EA31B52001EF4F6 /* AppCategories.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54D3A6EB2EA31B52001EF4F6 /* AppCategories.swift */; };
|
||||||
54D3A6EE2EA39CC6001EF4F6 /* AppIcon.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54D3A6ED2EA39CC6001EF4F6 /* AppIcon.swift */; };
|
54D3A6EE2EA39CC6001EF4F6 /* AppIcon.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54D3A6ED2EA39CC6001EF4F6 /* AppIcon.swift */; };
|
||||||
@@ -38,6 +50,13 @@
|
|||||||
remoteGlobalIDString = 54442C1F2E378BAF008A870E;
|
remoteGlobalIDString = 54442C1F2E378BAF008A870E;
|
||||||
remoteInfo = QLPreview;
|
remoteInfo = QLPreview;
|
||||||
};
|
};
|
||||||
|
54581FD82EB29A0B0043A0B3 /* PBXContainerItemProxy */ = {
|
||||||
|
isa = PBXContainerItemProxy;
|
||||||
|
containerPortal = 54442BEC2E378B71008A870E /* Project object */;
|
||||||
|
proxyType = 1;
|
||||||
|
remoteGlobalIDString = 54581FCE2EB29A0B0043A0B3;
|
||||||
|
remoteInfo = QLThumbnail;
|
||||||
|
};
|
||||||
/* End PBXContainerItemProxy section */
|
/* End PBXContainerItemProxy section */
|
||||||
|
|
||||||
/* Begin PBXCopyFilesBuildPhase section */
|
/* Begin PBXCopyFilesBuildPhase section */
|
||||||
@@ -47,6 +66,7 @@
|
|||||||
dstPath = "";
|
dstPath = "";
|
||||||
dstSubfolderSpec = 13;
|
dstSubfolderSpec = 13;
|
||||||
files = (
|
files = (
|
||||||
|
54581FDA2EB29A0B0043A0B3 /* QLThumbnail.appex in Embed Foundation Extensions */,
|
||||||
54442C302E378BAF008A870E /* QLPreview.appex in Embed Foundation Extensions */,
|
54442C302E378BAF008A870E /* QLPreview.appex in Embed Foundation Extensions */,
|
||||||
);
|
);
|
||||||
name = "Embed Foundation Extensions";
|
name = "Embed Foundation Extensions";
|
||||||
@@ -71,9 +91,13 @@
|
|||||||
54442C772E378BE0008A870E /* QLPreview.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = QLPreview.entitlements; 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>"; };
|
545459C62EA4773A002892E5 /* AppIcon+Car.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AppIcon+Car.swift"; sourceTree = "<group>"; };
|
||||||
545459C82EA47C37002892E5 /* Plist.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Plist.swift; sourceTree = "<group>"; };
|
545459C82EA47C37002892E5 /* Plist.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Plist.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>"; };
|
5469E11C2EA5930C00D46CE7 /* Entitlements.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Entitlements.swift; sourceTree = "<group>"; };
|
||||||
5485EE362EB1460C009E3905 /* Network.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Network.framework; path = System/Library/Frameworks/Network.framework; sourceTree = SDKROOT; };
|
5485EE362EB1460C009E3905 /* Network.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Network.framework; path = System/Library/Frameworks/Network.framework; sourceTree = SDKROOT; };
|
||||||
54D3A6E52EA31B13001EF4F6 /* ThumbnailGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThumbnailGenerator.swift; sourceTree = "<group>"; };
|
|
||||||
54D3A6EB2EA31B52001EF4F6 /* AppCategories.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppCategories.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>"; };
|
54D3A6ED2EA39CC6001EF4F6 /* AppIcon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppIcon.swift; sourceTree = "<group>"; };
|
||||||
54D3A6EF2EA3F49F001EF4F6 /* RoundedIcon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoundedIcon.swift; sourceTree = "<group>"; };
|
54D3A6EF2EA3F49F001EF4F6 /* RoundedIcon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoundedIcon.swift; sourceTree = "<group>"; };
|
||||||
@@ -110,6 +134,16 @@
|
|||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
54581FCC2EB29A0B0043A0B3 /* Frameworks */ = {
|
||||||
|
isa = PBXFrameworksBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
54581FD12EB29A0B0043A0B3 /* QuickLookThumbnailing.framework in Frameworks */,
|
||||||
|
54581FD22EB29A0B0043A0B3 /* Quartz.framework in Frameworks */,
|
||||||
|
54581FE42EB29A2B0043A0B3 /* CoreUI.framework in Frameworks */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
/* End PBXFrameworksBuildPhase section */
|
/* End PBXFrameworksBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXGroup section */
|
/* Begin PBXGroup section */
|
||||||
@@ -124,7 +158,6 @@
|
|||||||
545459C82EA47C37002892E5 /* Plist.swift */,
|
545459C82EA47C37002892E5 /* Plist.swift */,
|
||||||
5405CF642EA1376B00613856 /* Zip.swift */,
|
5405CF642EA1376B00613856 /* Zip.swift */,
|
||||||
5469E11C2EA5930C00D46CE7 /* Entitlements.swift */,
|
5469E11C2EA5930C00D46CE7 /* Entitlements.swift */,
|
||||||
54D3A6E52EA31B13001EF4F6 /* ThumbnailGenerator.swift */,
|
|
||||||
5405CF5B2EA1191A00613856 /* PreviewGenerator.swift */,
|
5405CF5B2EA1191A00613856 /* PreviewGenerator.swift */,
|
||||||
);
|
);
|
||||||
path = src;
|
path = src;
|
||||||
@@ -138,6 +171,7 @@
|
|||||||
541051562E37AFC10083670B /* src */,
|
541051562E37AFC10083670B /* src */,
|
||||||
54442C6F2E378BDD008A870E /* QLApps */,
|
54442C6F2E378BDD008A870E /* QLApps */,
|
||||||
54442C782E378BE0008A870E /* QLPreview */,
|
54442C782E378BE0008A870E /* QLPreview */,
|
||||||
|
545820202EB29B3D0043A0B3 /* QLThumbnail */,
|
||||||
54442C212E378BAF008A870E /* Frameworks */,
|
54442C212E378BAF008A870E /* Frameworks */,
|
||||||
54442BF52E378B71008A870E /* Products */,
|
54442BF52E378B71008A870E /* Products */,
|
||||||
);
|
);
|
||||||
@@ -148,6 +182,7 @@
|
|||||||
children = (
|
children = (
|
||||||
54442BF42E378B71008A870E /* QLApps.app */,
|
54442BF42E378B71008A870E /* QLApps.app */,
|
||||||
54442C202E378BAF008A870E /* QLPreview.appex */,
|
54442C202E378BAF008A870E /* QLPreview.appex */,
|
||||||
|
54581FCF2EB29A0B0043A0B3 /* QLThumbnail.appex */,
|
||||||
);
|
);
|
||||||
name = Products;
|
name = Products;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -166,6 +201,7 @@
|
|||||||
54D3A6FC2EA465A9001EF4F6 /* CoreServices.framework */,
|
54D3A6FC2EA465A9001EF4F6 /* CoreServices.framework */,
|
||||||
54D3A6FA2EA46588001EF4F6 /* CoreGraphics.framework */,
|
54D3A6FA2EA46588001EF4F6 /* CoreGraphics.framework */,
|
||||||
54442C222E378BAF008A870E /* Quartz.framework */,
|
54442C222E378BAF008A870E /* Quartz.framework */,
|
||||||
|
54581FD02EB29A0B0043A0B3 /* QuickLookThumbnailing.framework */,
|
||||||
);
|
);
|
||||||
name = Frameworks;
|
name = Frameworks;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -192,6 +228,16 @@
|
|||||||
path = QLPreview;
|
path = QLPreview;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
545820202EB29B3D0043A0B3 /* QLThumbnail */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
5458201D2EB29B3D0043A0B3 /* Info.plist */,
|
||||||
|
5458201E2EB29B3D0043A0B3 /* QLThumbnail.entitlements */,
|
||||||
|
5458201F2EB29B3D0043A0B3 /* ThumbnailProvider.swift */,
|
||||||
|
);
|
||||||
|
path = QLThumbnail;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
54D3A6F42EA46069001EF4F6 /* resources */ = {
|
54D3A6F42EA46069001EF4F6 /* resources */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@@ -226,6 +272,7 @@
|
|||||||
);
|
);
|
||||||
dependencies = (
|
dependencies = (
|
||||||
54442C2F2E378BAF008A870E /* PBXTargetDependency */,
|
54442C2F2E378BAF008A870E /* PBXTargetDependency */,
|
||||||
|
54581FD92EB29A0B0043A0B3 /* PBXTargetDependency */,
|
||||||
);
|
);
|
||||||
name = QLApps;
|
name = QLApps;
|
||||||
packageProductDependencies = (
|
packageProductDependencies = (
|
||||||
@@ -253,6 +300,25 @@
|
|||||||
productReference = 54442C202E378BAF008A870E /* QLPreview.appex */;
|
productReference = 54442C202E378BAF008A870E /* QLPreview.appex */;
|
||||||
productType = "com.apple.product-type.app-extension";
|
productType = "com.apple.product-type.app-extension";
|
||||||
};
|
};
|
||||||
|
54581FCE2EB29A0B0043A0B3 /* QLThumbnail */ = {
|
||||||
|
isa = PBXNativeTarget;
|
||||||
|
buildConfigurationList = 54581FDE2EB29A0B0043A0B3 /* Build configuration list for PBXNativeTarget "QLThumbnail" */;
|
||||||
|
buildPhases = (
|
||||||
|
54581FCB2EB29A0B0043A0B3 /* Sources */,
|
||||||
|
54581FCC2EB29A0B0043A0B3 /* Frameworks */,
|
||||||
|
54581FCD2EB29A0B0043A0B3 /* Resources */,
|
||||||
|
);
|
||||||
|
buildRules = (
|
||||||
|
);
|
||||||
|
dependencies = (
|
||||||
|
);
|
||||||
|
name = QLThumbnail;
|
||||||
|
packageProductDependencies = (
|
||||||
|
);
|
||||||
|
productName = QLThumbnail;
|
||||||
|
productReference = 54581FCF2EB29A0B0043A0B3 /* QLThumbnail.appex */;
|
||||||
|
productType = "com.apple.product-type.app-extension";
|
||||||
|
};
|
||||||
/* End PBXNativeTarget section */
|
/* End PBXNativeTarget section */
|
||||||
|
|
||||||
/* Begin PBXProject section */
|
/* Begin PBXProject section */
|
||||||
@@ -269,6 +335,9 @@
|
|||||||
54442C1F2E378BAF008A870E = {
|
54442C1F2E378BAF008A870E = {
|
||||||
CreatedOnToolsVersion = 16.4;
|
CreatedOnToolsVersion = 16.4;
|
||||||
};
|
};
|
||||||
|
54581FCE2EB29A0B0043A0B3 = {
|
||||||
|
CreatedOnToolsVersion = 16.4;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
buildConfigurationList = 54442BEF2E378B71008A870E /* Build configuration list for PBXProject "QLApps" */;
|
buildConfigurationList = 54442BEF2E378B71008A870E /* Build configuration list for PBXProject "QLApps" */;
|
||||||
@@ -287,6 +356,7 @@
|
|||||||
targets = (
|
targets = (
|
||||||
54442BF32E378B71008A870E /* QLApps */,
|
54442BF32E378B71008A870E /* QLApps */,
|
||||||
54442C1F2E378BAF008A870E /* QLPreview */,
|
54442C1F2E378BAF008A870E /* QLPreview */,
|
||||||
|
54581FCE2EB29A0B0043A0B3 /* QLThumbnail */,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
/* End PBXProject section */
|
/* End PBXProject section */
|
||||||
@@ -312,6 +382,14 @@
|
|||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
54581FCD2EB29A0B0043A0B3 /* Resources */ = {
|
||||||
|
isa = PBXResourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
545820232EB29B4C0043A0B3 /* defaultIcon.png in Resources */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
/* End PBXResourcesBuildPhase section */
|
/* End PBXResourcesBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXSourcesBuildPhase section */
|
/* Begin PBXSourcesBuildPhase section */
|
||||||
@@ -340,6 +418,20 @@
|
|||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
54581FCB2EB29A0B0043A0B3 /* Sources */ = {
|
||||||
|
isa = PBXSourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
54581FFD2EB29AB70043A0B3 /* Plist.swift in Sources */,
|
||||||
|
54581FEF2EB29A570043A0B3 /* Shared.swift in Sources */,
|
||||||
|
54581FF02EB29A5E0043A0B3 /* AppIcon.swift in Sources */,
|
||||||
|
54581FF72EB29A820043A0B3 /* Zip.swift in Sources */,
|
||||||
|
545820032EB29B0A0043A0B3 /* RoundedIcon.swift in Sources */,
|
||||||
|
545820222EB29B3D0043A0B3 /* ThumbnailProvider.swift in Sources */,
|
||||||
|
54581FF12EB29A620043A0B3 /* AppIcon+Car.swift in Sources */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
/* End PBXSourcesBuildPhase section */
|
/* End PBXSourcesBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXTargetDependency section */
|
/* Begin PBXTargetDependency section */
|
||||||
@@ -348,6 +440,11 @@
|
|||||||
target = 54442C1F2E378BAF008A870E /* QLPreview */;
|
target = 54442C1F2E378BAF008A870E /* QLPreview */;
|
||||||
targetProxy = 54442C2E2E378BAF008A870E /* PBXContainerItemProxy */;
|
targetProxy = 54442C2E2E378BAF008A870E /* PBXContainerItemProxy */;
|
||||||
};
|
};
|
||||||
|
54581FD92EB29A0B0043A0B3 /* PBXTargetDependency */ = {
|
||||||
|
isa = PBXTargetDependency;
|
||||||
|
target = 54581FCE2EB29A0B0043A0B3 /* QLThumbnail */;
|
||||||
|
targetProxy = 54581FD82EB29A0B0043A0B3 /* PBXContainerItemProxy */;
|
||||||
|
};
|
||||||
/* End PBXTargetDependency section */
|
/* End PBXTargetDependency section */
|
||||||
|
|
||||||
/* Begin PBXVariantGroup section */
|
/* Begin PBXVariantGroup section */
|
||||||
@@ -404,7 +501,7 @@
|
|||||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
COPY_PHASE_STRIP = NO;
|
COPY_PHASE_STRIP = NO;
|
||||||
CURRENT_PROJECT_VERSION = 773;
|
CURRENT_PROJECT_VERSION = 842;
|
||||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||||
DEVELOPMENT_TEAM = UY657LKNHJ;
|
DEVELOPMENT_TEAM = UY657LKNHJ;
|
||||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
@@ -475,7 +572,7 @@
|
|||||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
COPY_PHASE_STRIP = NO;
|
COPY_PHASE_STRIP = NO;
|
||||||
CURRENT_PROJECT_VERSION = 773;
|
CURRENT_PROJECT_VERSION = 842;
|
||||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||||
DEVELOPMENT_TEAM = UY657LKNHJ;
|
DEVELOPMENT_TEAM = UY657LKNHJ;
|
||||||
ENABLE_NS_ASSERTIONS = NO;
|
ENABLE_NS_ASSERTIONS = NO;
|
||||||
@@ -617,6 +714,62 @@
|
|||||||
};
|
};
|
||||||
name = Release;
|
name = Release;
|
||||||
};
|
};
|
||||||
|
54581FDB2EB29A0B0043A0B3 /* Debug */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
CODE_SIGN_ENTITLEMENTS = QLThumbnail/QLThumbnail.entitlements;
|
||||||
|
CODE_SIGN_STYLE = Manual;
|
||||||
|
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_NSHumanReadableCopyright = "";
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/../Frameworks",
|
||||||
|
"@executable_path/../../../../Frameworks",
|
||||||
|
);
|
||||||
|
MACOSX_DEPLOYMENT_TARGET = 15.5;
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = de.relikd.QLApps.QLThumbnail;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
|
SKIP_INSTALL = YES;
|
||||||
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
|
SWIFT_INCLUDE_PATHS = "$(SRCROOT)/PrivateFrameworks/CoreUI.framework $(inherited)";
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
};
|
||||||
|
name = Debug;
|
||||||
|
};
|
||||||
|
54581FDC2EB29A0B0043A0B3 /* Release */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
CODE_SIGN_ENTITLEMENTS = QLThumbnail/QLThumbnail.entitlements;
|
||||||
|
CODE_SIGN_STYLE = Manual;
|
||||||
|
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_NSHumanReadableCopyright = "";
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/../Frameworks",
|
||||||
|
"@executable_path/../../../../Frameworks",
|
||||||
|
);
|
||||||
|
MACOSX_DEPLOYMENT_TARGET = 15.5;
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = de.relikd.QLApps.QLThumbnail;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
|
SKIP_INSTALL = YES;
|
||||||
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
|
SWIFT_INCLUDE_PATHS = "$(SRCROOT)/PrivateFrameworks/CoreUI.framework $(inherited)";
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
};
|
||||||
|
name = Release;
|
||||||
|
};
|
||||||
/* End XCBuildConfiguration section */
|
/* End XCBuildConfiguration section */
|
||||||
|
|
||||||
/* Begin XCConfigurationList section */
|
/* Begin XCConfigurationList section */
|
||||||
@@ -647,6 +800,15 @@
|
|||||||
defaultConfigurationIsVisible = 0;
|
defaultConfigurationIsVisible = 0;
|
||||||
defaultConfigurationName = Release;
|
defaultConfigurationName = Release;
|
||||||
};
|
};
|
||||||
|
54581FDE2EB29A0B0043A0B3 /* Build configuration list for PBXNativeTarget "QLThumbnail" */ = {
|
||||||
|
isa = XCConfigurationList;
|
||||||
|
buildConfigurations = (
|
||||||
|
54581FDB2EB29A0B0043A0B3 /* Debug */,
|
||||||
|
54581FDC2EB29A0B0043A0B3 /* Release */,
|
||||||
|
);
|
||||||
|
defaultConfigurationIsVisible = 0;
|
||||||
|
defaultConfigurationName = Release;
|
||||||
|
};
|
||||||
/* End XCConfigurationList section */
|
/* End XCConfigurationList section */
|
||||||
};
|
};
|
||||||
rootObject = 54442BEC2E378B71008A870E /* Project object */;
|
rootObject = 54442BEC2E378B71008A870E /* Project object */;
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import WebKit // WebView
|
|||||||
import os // OSLog
|
import os // OSLog
|
||||||
|
|
||||||
// show Console logs with subsystem:de.relikd.QLApps
|
// show Console logs with subsystem:de.relikd.QLApps
|
||||||
private let log = OSLog(subsystem: Bundle.main.bundleIdentifier!, category: "main")
|
private let log = OSLog(subsystem: Bundle.main.bundleIdentifier!, category: "preview-plugin")
|
||||||
|
|
||||||
class PreviewViewController: NSViewController, QLPreviewingController {
|
class PreviewViewController: NSViewController, QLPreviewingController {
|
||||||
|
|
||||||
|
|||||||
24
QLThumbnail/Info.plist
Normal file
24
QLThumbnail/Info.plist
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>NSExtension</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSExtensionAttributes</key>
|
||||||
|
<dict>
|
||||||
|
<key>QLSupportedContentTypes</key>
|
||||||
|
<array>
|
||||||
|
<string>com.apple.itunes.ipa</string>
|
||||||
|
<string>com.apple.application-and-system-extension</string>
|
||||||
|
<string>com.apple.xcode.archive</string>
|
||||||
|
</array>
|
||||||
|
<key>QLThumbnailMinimumDimension</key>
|
||||||
|
<integer>16</integer>
|
||||||
|
</dict>
|
||||||
|
<key>NSExtensionPointIdentifier</key>
|
||||||
|
<string>com.apple.quicklook.thumbnail</string>
|
||||||
|
<key>NSExtensionPrincipalClass</key>
|
||||||
|
<string>$(PRODUCT_MODULE_NAME).ThumbnailProvider</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
10
QLThumbnail/QLThumbnail.entitlements
Normal file
10
QLThumbnail/QLThumbnail.entitlements
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>com.apple.security.app-sandbox</key>
|
||||||
|
<true/>
|
||||||
|
<key>com.apple.security.files.user-selected.read-only</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
43
QLThumbnail/ThumbnailProvider.swift
Normal file
43
QLThumbnail/ThumbnailProvider.swift
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
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 {
|
||||||
|
/// call private method `setIconFlavor:`
|
||||||
|
/// see https://medium.com/swlh/calling-ios-and-macos-hidden-api-in-style-1a924f244ad1
|
||||||
|
fileprivate func setFlavor(_ flavor: Int) {
|
||||||
|
typealias setIconFlavorMethod = @convention(c) (NSObject, Selector, NSInteger) -> Bool
|
||||||
|
let selector = NSSelectorFromString("setIconFlavor:")
|
||||||
|
let imp = self.method(for: selector)
|
||||||
|
let method = unsafeBitCast(imp, to: setIconFlavorMethod.self)
|
||||||
|
_ = method(self, selector, flavor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ThumbnailProvider: QLThumbnailProvider {
|
||||||
|
|
||||||
|
// TODO: sadly, this does not seem to work for .xarchive and .appex
|
||||||
|
// Probably overwritten by Apple somehow
|
||||||
|
|
||||||
|
override func provideThumbnail(for request: QLFileThumbnailRequest, _ handler: @escaping (QLThumbnailReply?, Error?) -> Void) {
|
||||||
|
let meta = QuickLookInfo(request.fileURL)
|
||||||
|
let icon = AppIcon(meta)
|
||||||
|
let plistApp = meta.readPlistApp()
|
||||||
|
let img = icon.extractImage(from: plistApp).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
|
||||||
|
img.draw(in: CGRect(origin: .zero, size: request.maximumSize))
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
// defer in case `setFlavor` fails
|
||||||
|
defer {
|
||||||
|
handler(reply, nil)
|
||||||
|
}
|
||||||
|
// 0: Plain transparent, 1: Shadow, 2: Book, 3: Movie, 4: Address, 5: Image,
|
||||||
|
// 6: Gloss, 7: Slide, 8: Square, 9: Border, 11: Calendar, 12: Pattern
|
||||||
|
reply.setFlavor(meta.type == .Archive ? 12 : 0) // .archive looks like "in development"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,162 +0,0 @@
|
|||||||
import Foundation
|
|
||||||
|
|
||||||
////#import "Shared.h"
|
|
||||||
//#import "AppIcon.h"
|
|
||||||
//
|
|
||||||
//// makro to stop further processing
|
|
||||||
//#define ALLOW_EXIT if (QLThumbnailRequestIsCancelled(thumbnail)) { return noErr; }
|
|
||||||
//
|
|
||||||
////Layout constants
|
|
||||||
//#define BADGE_MARGIN 10.0
|
|
||||||
//#define MIN_BADGE_WIDTH 40.0
|
|
||||||
//#define BADGE_HEIGHT 75.0
|
|
||||||
//#define BADGE_MARGIN_X 60.0
|
|
||||||
//#define BADGE_MARGIN_Y 80.0
|
|
||||||
//
|
|
||||||
////Drawing constants
|
|
||||||
//#define BADGE_BG_COLOR [NSColor lightGrayColor]
|
|
||||||
//#define BADGE_VALID_COLOR [NSColor colorWithCalibratedRed:(0/255.0) green:(98/255.0) blue:(25/255.0) alpha:1]
|
|
||||||
//#define BADGE_EXPIRING_COLOR [NSColor colorWithCalibratedRed:(146/255.0) green:(95/255.0) blue:(28/255.0) alpha:1]
|
|
||||||
//#define BADGE_EXPIRED_COLOR [NSColor colorWithCalibratedRed:(141/255.0) green:(0/255.0) blue:(7/255.0) alpha:1]
|
|
||||||
//#define BADGE_FONT [NSFont boldSystemFontOfSize:64]
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//OSStatus GenerateThumbnailForURL(void *thisInterface, QLThumbnailRequestRef thumbnail, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options, CGSize maxSize);
|
|
||||||
//void CancelThumbnailGeneration(void *thisInterface, QLThumbnailRequestRef thumbnail);
|
|
||||||
//
|
|
||||||
///* -----------------------------------------------------------------------------
|
|
||||||
// Generate a thumbnail for file
|
|
||||||
//
|
|
||||||
// This function's job is to create thumbnail for designated file as fast as possible
|
|
||||||
// ----------------------------------------------------------------------------- */
|
|
||||||
//
|
|
||||||
//// MARK: .ipa .xcarchive
|
|
||||||
//
|
|
||||||
//OSStatus renderAppIcon(QuickLookInfo meta, QLThumbnailRequestRef thumbnail) {
|
|
||||||
// AppIcon *icon = [AppIcon load:meta];
|
|
||||||
// if (!icon.canExtractImage) {
|
|
||||||
// return noErr;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // set magic flag to draw icon without additional markers
|
|
||||||
// static const NSString *IconFlavor;
|
|
||||||
// if (@available(macOS 10.15, *)) {
|
|
||||||
// IconFlavor = @"icon";
|
|
||||||
// } else {
|
|
||||||
// IconFlavor = @"IconFlavor";
|
|
||||||
// }
|
|
||||||
// NSDictionary *propertiesDict = nil;
|
|
||||||
// if (meta.type == FileTypeArchive) {
|
|
||||||
// // 0: Plain transparent, 1: Shadow, 2: Book, 3: Movie, 4: Address, 5: Image,
|
|
||||||
// // 6: Gloss, 7: Slide, 8: Square, 9: Border, 11: Calendar, 12: Pattern
|
|
||||||
// propertiesDict = @{IconFlavor : @(12)}; // looks like "in development"
|
|
||||||
// } else {
|
|
||||||
// propertiesDict = @{IconFlavor : @(0)}; // no border, no anything
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// NSImage *appIcon = [[icon extractImage:nil] withRoundCorners];
|
|
||||||
// ALLOW_EXIT
|
|
||||||
//
|
|
||||||
// // image-only icons can be drawn efficiently by calling `SetImage` directly.
|
|
||||||
// QLThumbnailRequestSetImageWithData(thumbnail, (__bridge CFDataRef)[appIcon TIFFRepresentation], (__bridge CFDictionaryRef)propertiesDict);
|
|
||||||
// return noErr;
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//// MARK: .provisioning
|
|
||||||
//
|
|
||||||
//OSStatus renderProvision(QuickLookInfo meta, QLThumbnailRequestRef thumbnail, BOOL iconMode) {
|
|
||||||
// NSDictionary *propertyList = readPlistProvision(meta);
|
|
||||||
// ALLOW_EXIT
|
|
||||||
//
|
|
||||||
// NSUInteger devicesCount = arrayOrNil(propertyList[@"ProvisionedDevices"]).count;
|
|
||||||
// NSDate *expirationDate = dateOrNil(propertyList[@"ExpirationDate"]);
|
|
||||||
//
|
|
||||||
// NSImage *appIcon = nil;
|
|
||||||
// if (iconMode) {
|
|
||||||
// NSURL *iconURL = [[NSBundle bundleWithIdentifier:kPluginBundleId] URLForResource:@"blankIcon" withExtension:@"png"];
|
|
||||||
// appIcon = [[NSImage alloc] initWithContentsOfURL:iconURL];
|
|
||||||
// } else {
|
|
||||||
// appIcon = [[NSWorkspace sharedWorkspace] iconForFileType:meta.UTI];
|
|
||||||
// [appIcon setSize:NSMakeSize(512, 512)];
|
|
||||||
// }
|
|
||||||
// ALLOW_EXIT
|
|
||||||
//
|
|
||||||
// NSRect renderRect = NSMakeRect(0.0, 0.0, appIcon.size.width, appIcon.size.height);
|
|
||||||
//
|
|
||||||
// // Font attributes
|
|
||||||
// NSColor *outlineColor;
|
|
||||||
// switch (expirationStatus(expirationDate)) {
|
|
||||||
// case ExpirationStatusExpired: outlineColor = BADGE_EXPIRED_COLOR; break;
|
|
||||||
// case ExpirationStatusExpiring: outlineColor = BADGE_EXPIRING_COLOR; break;
|
|
||||||
// case ExpirationStatusValid: outlineColor = BADGE_VALID_COLOR; break;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// NSMutableParagraphStyle *paragraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
|
|
||||||
// paragraphStyle.lineBreakMode = NSLineBreakByTruncatingTail;
|
|
||||||
// paragraphStyle.alignment = NSTextAlignmentCenter;
|
|
||||||
//
|
|
||||||
// NSDictionary *fontAttrs = @{
|
|
||||||
// NSFontAttributeName : BADGE_FONT,
|
|
||||||
// NSForegroundColorAttributeName : outlineColor,
|
|
||||||
// NSParagraphStyleAttributeName: paragraphStyle
|
|
||||||
// };
|
|
||||||
//
|
|
||||||
// // Badge size & placement
|
|
||||||
// int badgeX = renderRect.origin.x + BADGE_MARGIN_X;
|
|
||||||
// int badgeY = renderRect.origin.y + renderRect.size.height - BADGE_HEIGHT - BADGE_MARGIN_Y;
|
|
||||||
// if (!iconMode) {
|
|
||||||
// badgeX += 75;
|
|
||||||
// badgeY -= 10;
|
|
||||||
// }
|
|
||||||
// int badgeNumX = badgeX + BADGE_MARGIN;
|
|
||||||
// NSPoint badgeTextPoint = NSMakePoint(badgeNumX, badgeY);
|
|
||||||
//
|
|
||||||
// NSString *badge = [NSString stringWithFormat:@"%lu",(unsigned long)devicesCount];
|
|
||||||
// NSSize badgeNumSize = [badge sizeWithAttributes:fontAttrs];
|
|
||||||
// int badgeWidth = badgeNumSize.width + BADGE_MARGIN * 2;
|
|
||||||
// NSRect badgeOutlineRect = NSMakeRect(badgeX, badgeY, MAX(badgeWidth, MIN_BADGE_WIDTH), BADGE_HEIGHT);
|
|
||||||
//
|
|
||||||
// // Do as much work as possible before the `CreateContext`. We can try to quit early before that!
|
|
||||||
// CGContextRef _context = QLThumbnailRequestCreateContext(thumbnail, renderRect.size, false, NULL);
|
|
||||||
// if (_context) {
|
|
||||||
// NSGraphicsContext *_graphicsContext = [NSGraphicsContext graphicsContextWithCGContext:(void *)_context flipped:NO];
|
|
||||||
// [NSGraphicsContext setCurrentContext:_graphicsContext];
|
|
||||||
// [appIcon drawInRect:renderRect];
|
|
||||||
//
|
|
||||||
// NSBezierPath *badgePath = [NSBezierPath bezierPathWithRoundedRect:badgeOutlineRect xRadius:10 yRadius:10];
|
|
||||||
// [badgePath setLineWidth:8.0];
|
|
||||||
// [BADGE_BG_COLOR set];
|
|
||||||
// [badgePath fill];
|
|
||||||
// [outlineColor set];
|
|
||||||
// [badgePath stroke];
|
|
||||||
//
|
|
||||||
// [badge drawAtPoint:badgeTextPoint withAttributes:fontAttrs];
|
|
||||||
//
|
|
||||||
// QLThumbnailRequestFlushContext(thumbnail, _context);
|
|
||||||
// CFRelease(_context);
|
|
||||||
// }
|
|
||||||
// return noErr;
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//// MARK: Main Entry
|
|
||||||
//
|
|
||||||
//OSStatus GenerateThumbnailForURL(void *thisInterface, QLThumbnailRequestRef thumbnail, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options, CGSize maxSize) {
|
|
||||||
// @autoreleasepool {
|
|
||||||
// QuickLookInfo meta = initQLInfo(contentTypeUTI, url);
|
|
||||||
//
|
|
||||||
// if (meta.type == FileTypeProvision) {
|
|
||||||
// NSDictionary *optionsDict = (__bridge NSDictionary *)options;
|
|
||||||
// BOOL iconMode = ([optionsDict objectForKey:(NSString *)kQLThumbnailOptionIconModeKey]) ? YES : NO;
|
|
||||||
// return renderProvision(meta, thumbnail, iconMode);
|
|
||||||
// } else {
|
|
||||||
// return renderAppIcon(meta, thumbnail);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// return noErr;
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
//void CancelThumbnailGeneration(void *thisInterface, QLThumbnailRequestRef thumbnail) {
|
|
||||||
// // Implement only if supported
|
|
||||||
//}
|
|
||||||
Reference in New Issue
Block a user