diff --git a/.tx/config b/.tx/config index 870db41da..1d98eb6ac 100644 --- a/.tx/config +++ b/.tx/config @@ -85,8 +85,8 @@ type = STRINGS lang_map = pt_BR: pt-BR, pt_PT: pt-PT, zh_CN: zh-CN, zh_TW: zh-TW [o:transmissionbt:p:transmissionbt:r:mac-ql] -file_filter = macosx/QuickLookPlugin/.lproj/Localizable.strings -source_file = macosx/QuickLookPlugin/en.lproj/Localizable.strings +file_filter = macosx/QuickLookExtension/.lproj/Localizable.strings +source_file = macosx/QuickLookExtension/en.lproj/Localizable.strings source_lang = en type = STRINGS lang_map = pt_BR: pt-BR, pt_PT: pt-PT, zh_CN: zh-CN, zh_TW: zh-TW diff --git a/Transmission.xcodeproj/project.pbxproj b/Transmission.xcodeproj/project.pbxproj index acae3fac9..be841c57c 100644 --- a/Transmission.xcodeproj/project.pbxproj +++ b/Transmission.xcodeproj/project.pbxproj @@ -448,6 +448,14 @@ ED20B87C28589274005FA6BE /* common_defs.h in Headers */ = {isa = PBXBuildFile; fileRef = ED20B87B28589274005FA6BE /* common_defs.h */; }; ED20B87F285892C5005FA6BE /* crc32_multipliers.h in Headers */ = {isa = PBXBuildFile; fileRef = ED20B87D285892C5005FA6BE /* crc32_multipliers.h */; }; ED20B880285892C5005FA6BE /* crc32_tables.h in Headers */ = {isa = PBXBuildFile; fileRef = ED20B87E285892C5005FA6BE /* crc32_tables.h */; }; + ED5E0E7E2CD30B180071433B /* Quartz.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ED5E0E7D2CD30B180071433B /* Quartz.framework */; }; + ED5E0E8D2CD30B180071433B /* QuickLookExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = ED5E0E7C2CD30B180071433B /* QuickLookExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + ED5E0E9C2CD30E8F0071433B /* PreviewProvider.mm in Sources */ = {isa = PBXBuildFile; fileRef = ED5E0E962CD30E8F0071433B /* PreviewProvider.mm */; }; + ED5E0E9D2CD3134B0071433B /* libtransmission.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4D18389709DEC0030047D688 /* libtransmission.a */; }; + ED5E0EA02CD3147B0071433B /* libcurl.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 55869925257074EC00F77A43 /* libcurl.tbd */; }; + ED5E0EA22CD314FE0071433B /* style.css in Resources */ = {isa = PBXBuildFile; fileRef = ED5E0EA12CD314FE0071433B /* style.css */; }; + ED5E0EFA2CD315720071433B /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = ED5E0EF72CD315720071433B /* Localizable.strings */; }; + ED5E0F0F2CD31BC20071433B /* NSStringAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4DE5CC9C0980656F00BE280E /* NSStringAdditions.mm */; }; ED67FB422B70FCE400D8A037 /* settings.cc in Sources */ = {isa = PBXBuildFile; fileRef = ED67FB402B70FCE400D8A037 /* settings.cc */; }; ED67FB432B70FCE400D8A037 /* settings.h in Headers */ = {isa = PBXBuildFile; fileRef = ED67FB412B70FCE400D8A037 /* settings.h */; }; ED86936F2ADAE34D00342B1A /* DefaultAppHelper.mm in Sources */ = {isa = PBXBuildFile; fileRef = ED86936E2ADAE34D00342B1A /* DefaultAppHelper.mm */; }; @@ -611,6 +619,20 @@ remoteGlobalIDString = ED91F00B2CBDA5D3008388AA; remoteInfo = crc32c; }; + ED5E0E8B2CD30B180071433B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */; + proxyType = 1; + remoteGlobalIDString = ED5E0E7B2CD30B180071433B; + remoteInfo = QuickLookExtension; + }; + ED5E0E9E2CD3134B0071433B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4D18389609DEC0030047D688; + remoteInfo = libtransmission; + }; /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -636,6 +658,17 @@ name = "Copy Files to Wrapper"; runOnlyForDeploymentPostprocessing = 0; }; + ED5E0E8E2CD30B180071433B /* Embed Foundation Extensions */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 13; + files = ( + ED5E0E8D2CD30B180071433B /* QuickLookExtension.appex in Embed Foundation Extensions */, + ); + name = "Embed Foundation Extensions"; + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ @@ -1387,6 +1420,33 @@ ED20B87B28589274005FA6BE /* common_defs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = common_defs.h; sourceTree = ""; }; ED20B87D285892C5005FA6BE /* crc32_multipliers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = crc32_multipliers.h; path = lib/crc32_multipliers.h; sourceTree = ""; }; ED20B87E285892C5005FA6BE /* crc32_tables.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = crc32_tables.h; path = lib/crc32_tables.h; sourceTree = ""; }; + ED5E0E7C2CD30B180071433B /* QuickLookExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = QuickLookExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; }; + ED5E0E7D2CD30B180071433B /* Quartz.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Quartz.framework; path = System/Library/Frameworks/Quartz.framework; sourceTree = SDKROOT; }; + ED5E0E942CD30E8F0071433B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + ED5E0E952CD30E8F0071433B /* PreviewProvider.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PreviewProvider.h; sourceTree = ""; }; + ED5E0E962CD30E8F0071433B /* PreviewProvider.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = PreviewProvider.mm; sourceTree = ""; }; + ED5E0E972CD30E8F0071433B /* QuickLookExtension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = QuickLookExtension.entitlements; sourceTree = ""; }; + ED5E0EA12CD314FE0071433B /* style.css */ = {isa = PBXFileReference; lastKnownFileType = text.css; path = style.css; sourceTree = ""; }; + ED5E0EF92CD315720071433B /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = ""; }; + ED5E0EFC2CD3157E0071433B /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Localizable.strings; sourceTree = ""; }; + ED5E0EFD2CD3158A0071433B /* da */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = da; path = da.lproj/Localizable.strings; sourceTree = ""; }; + ED5E0EFE2CD315940071433B /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Localizable.strings; sourceTree = ""; }; + ED5E0EFF2CD315A90071433B /* eu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = eu; path = eu.lproj/Localizable.strings; sourceTree = ""; }; + ED5E0F002CD315B10071433B /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/Localizable.strings; sourceTree = ""; }; + ED5E0F012CD315B90071433B /* he */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = he; path = he.lproj/Localizable.strings; sourceTree = ""; }; + ED5E0F022CD315C50071433B /* hu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hu; path = hu.lproj/Localizable.strings; sourceTree = ""; }; + ED5E0F032CD315CD0071433B /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/Localizable.strings; sourceTree = ""; }; + ED5E0F042CD315D70071433B /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ja; path = ja.lproj/Localizable.strings; sourceTree = ""; }; + ED5E0F052CD315E10071433B /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/Localizable.strings; sourceTree = ""; }; + ED5E0F062CD315EC0071433B /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = pl.lproj/Localizable.strings; sourceTree = ""; }; + ED5E0F072CD315FE0071433B /* pt-PT */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-PT"; path = "pt-PT.lproj/Localizable.strings"; sourceTree = ""; }; + ED5E0F082CD316090071433B /* pt-BR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-BR"; path = "pt-BR.lproj/Localizable.strings"; sourceTree = ""; }; + ED5E0F092CD3161C0071433B /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/Localizable.strings; sourceTree = ""; }; + ED5E0F0A2CD316240071433B /* sv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sv; path = sv.lproj/Localizable.strings; sourceTree = ""; }; + ED5E0F0B2CD3162E0071433B /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = tr.lproj/Localizable.strings; sourceTree = ""; }; + ED5E0F0C2CD3163B0071433B /* uk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = uk; path = uk.lproj/Localizable.strings; sourceTree = ""; }; + ED5E0F0D2CD316450071433B /* zh-CN */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-CN"; path = "zh-CN.lproj/Localizable.strings"; sourceTree = ""; }; + ED5E0F0E2CD3164D0071433B /* zh-TW */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-TW"; path = "zh-TW.lproj/Localizable.strings"; sourceTree = ""; }; ED67FB402B70FCE400D8A037 /* settings.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = settings.cc; sourceTree = ""; }; ED67FB412B70FCE400D8A037 /* settings.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; path = settings.h; sourceTree = ""; }; ED86936D2ADAE34D00342B1A /* DefaultAppHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DefaultAppHelper.h; sourceTree = ""; }; @@ -1609,6 +1669,16 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + ED5E0E792CD30B180071433B /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ED5E0E7E2CD30B180071433B /* Quartz.framework in Frameworks */, + ED5E0E9D2CD3134B0071433B /* libtransmission.a in Frameworks */, + ED5E0EA02CD3147B0071433B /* libcurl.tbd in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ @@ -1748,6 +1818,7 @@ C3D9062127B7E3C900EF2386 /* libpsl.a */, C1846B9E294F7A3400A98F30 /* libwildmat.a */, ED91F00C2CBDA5D3008388AA /* libcrc32c.a */, + ED5E0E7C2CD30B180071433B /* QuickLookExtension.appex */, ); name = Products; sourceTree = ""; @@ -1757,6 +1828,7 @@ children = ( A22CEF9E21CDC44400C5C1BA /* Transmission.entitlements */, 4DDBB70A09E16B3200284745 /* GUI */, + ED5E0E992CD30E8F0071433B /* QuickLookExtension */, A2F35BC315C5A0A100EBF632 /* QuickLookPlugin */, 4D1838DC09DEC04A0047D688 /* libtransmission */, 4DDBB71F09E16BFE00284745 /* CLI */, @@ -2115,6 +2187,7 @@ A2F35BBB15C5A0A100EBF632 /* QuickLook.framework */, A2F35BE215C5A7F900EBF632 /* Foundation.framework */, A2F35BC115C5A0A100EBF632 /* CoreFoundation.framework */, + ED5E0E7D2CD30B180071433B /* Quartz.framework */, ); name = Frameworks; sourceTree = ""; @@ -2458,6 +2531,20 @@ path = "third-party/crc32c"; sourceTree = ""; }; + ED5E0E992CD30E8F0071433B /* QuickLookExtension */ = { + isa = PBXGroup; + children = ( + ED5E0EF72CD315720071433B /* Localizable.strings */, + ED5E0EA12CD314FE0071433B /* style.css */, + ED5E0E942CD30E8F0071433B /* Info.plist */, + ED5E0E952CD30E8F0071433B /* PreviewProvider.h */, + ED5E0E962CD30E8F0071433B /* PreviewProvider.mm */, + ED5E0E972CD30E8F0071433B /* QuickLookExtension.entitlements */, + ); + name = QuickLookExtension; + path = macosx/QuickLookExtension; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ @@ -2753,12 +2840,14 @@ 8D11072E0486CEB800E47090 /* Frameworks */, A24F191B0A3A792300C9C145 /* Copy Files to Frameworks */, A2EB2E7615C8CF1C00FBD5B4 /* Copy Files to Wrapper */, + ED5E0E8E2CD30B180071433B /* Embed Foundation Extensions */, ); buildRules = ( ); dependencies = ( A2EB2E7515C8CCE900FBD5B4 /* PBXTargetDependency */, 4D1838E609DEC1170047D688 /* PBXTargetDependency */, + ED5E0E8C2CD30B180071433B /* PBXTargetDependency */, ); name = Transmission; productInstallPath = "$(HOME)/Applications"; @@ -3030,6 +3119,26 @@ productReference = ED91F00C2CBDA5D3008388AA /* libcrc32c.a */; productType = "com.apple.product-type.library.static"; }; + ED5E0E7B2CD30B180071433B /* QuickLookExtension */ = { + isa = PBXNativeTarget; + buildConfigurationList = ED5E0E932CD30B180071433B /* Build configuration list for PBXNativeTarget "QuickLookExtension" */; + buildPhases = ( + ED5E0E782CD30B180071433B /* Sources */, + ED5E0E792CD30B180071433B /* Frameworks */, + ED5E0E7A2CD30B180071433B /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ED5E0E9F2CD3134B0071433B /* PBXTargetDependency */, + ); + name = QuickLookExtension; + packageProductDependencies = ( + ); + productName = QuickLookExtension; + productReference = ED5E0E7C2CD30B180071433B /* QuickLookExtension.appex */; + productType = "com.apple.product-type.app-extension"; + }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ @@ -3056,6 +3165,9 @@ ED91F00B2CBDA5D3008388AA = { CreatedOnToolsVersion = 16.0; }; + ED5E0E7B2CD30B180071433B = { + CreatedOnToolsVersion = 16.1; + }; }; }; buildConfigurationList = 4DF0C59A089918A300DD8943 /* Build configuration list for PBXProject "Transmission" */; @@ -3090,6 +3202,7 @@ projectRoot = ""; targets = ( 8D1107260486CEB800E47090 /* Transmission */, + ED5E0E7B2CD30B180071433B /* QuickLookExtension */, A2F35BB815C5A0A100EBF632 /* QuickLookPlugin */, 4D18389609DEC0030047D688 /* libtransmission */, 4DDBB71809E16BAE00284745 /* transmissioncli */, @@ -3162,6 +3275,15 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + ED5E0E7A2CD30B180071433B /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ED5E0EFA2CD315720071433B /* Localizable.strings in Resources */, + ED5E0EA22CD314FE0071433B /* style.css in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ @@ -3658,6 +3780,15 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + ED5E0E782CD30B180071433B /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ED5E0F0F2CD31BC20071433B /* NSStringAdditions.mm in Sources */, + ED5E0E9C2CD30E8F0071433B /* PreviewProvider.mm in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ @@ -3756,6 +3887,16 @@ target = ED91F00B2CBDA5D3008388AA /* crc32c */; targetProxy = ED91F3942CBDA9BD008388AA /* PBXContainerItemProxy */; }; + ED5E0E8C2CD30B180071433B /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = ED5E0E7B2CD30B180071433B /* QuickLookExtension */; + targetProxy = ED5E0E8B2CD30B180071433B /* PBXContainerItemProxy */; + }; + ED5E0E9F2CD3134B0071433B /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 4D18389609DEC0030047D688 /* libtransmission */; + targetProxy = ED5E0E9E2CD3134B0071433B /* PBXContainerItemProxy */; + }; /* End PBXTargetDependency section */ /* Begin PBXVariantGroup section */ @@ -4118,6 +4259,33 @@ name = InfoPlist.strings; sourceTree = ""; }; + ED5E0EF72CD315720071433B /* Localizable.strings */ = { + isa = PBXVariantGroup; + children = ( + ED5E0EF92CD315720071433B /* en */, + ED5E0EFC2CD3157E0071433B /* de */, + ED5E0EFD2CD3158A0071433B /* da */, + ED5E0EFE2CD315940071433B /* es */, + ED5E0EFF2CD315A90071433B /* eu */, + ED5E0F002CD315B10071433B /* fr */, + ED5E0F012CD315B90071433B /* he */, + ED5E0F022CD315C50071433B /* hu */, + ED5E0F032CD315CD0071433B /* it */, + ED5E0F042CD315D70071433B /* ja */, + ED5E0F052CD315E10071433B /* nl */, + ED5E0F062CD315EC0071433B /* pl */, + ED5E0F072CD315FE0071433B /* pt-PT */, + ED5E0F082CD316090071433B /* pt-BR */, + ED5E0F092CD3161C0071433B /* ru */, + ED5E0F0A2CD316240071433B /* sv */, + ED5E0F0B2CD3162E0071433B /* tr */, + ED5E0F0C2CD3163B0071433B /* uk */, + ED5E0F0D2CD316450071433B /* zh-CN */, + ED5E0F0E2CD3164D0071433B /* zh-TW */, + ); + name = Localizable.strings; + sourceTree = ""; + }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ @@ -5329,6 +5497,117 @@ }; name = Release; }; + ED5E0E8F2CD30B180071433B /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_ENTITLEMENTS = macosx/QuickLookExtension/QuickLookExtension.entitlements; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = dwarf; + GENERATE_INFOPLIST_FILE = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + ., + ); + INFOPLIST_FILE = macosx/QuickLookExtension/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = QuickLookExtension; + INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2024 The Transmission Project. All rights reserved."; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@executable_path/../../../../Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = 12.0; + MARKETING_VERSION = 1.0; + OTHER_CPLUSPLUSFLAGS = ( + "$(inherited)", + "-fmodules", + "-fcxx-modules", + ); + PRODUCT_BUNDLE_IDENTIFIER = org.m0k.transmission.QuickLookExtension; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + SYSTEM_HEADER_SEARCH_PATHS = ( + "$(inherited)", + "third-party/fmt/include", + "third-party/small/include", + ); + }; + name = Debug; + }; + ED5E0E902CD30B180071433B /* Release - Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_ENTITLEMENTS = macosx/QuickLookExtension/QuickLookExtension.entitlements; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + ., + ); + INFOPLIST_FILE = macosx/QuickLookExtension/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = QuickLookExtension; + INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2024 The Transmission Project. All rights reserved."; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@executable_path/../../../../Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = 12.0; + MARKETING_VERSION = 1.0; + OTHER_CPLUSPLUSFLAGS = ( + "$(inherited)", + "-fmodules", + "-fcxx-modules", + ); + PRODUCT_BUNDLE_IDENTIFIER = org.m0k.transmission.QuickLookExtension; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + SYSTEM_HEADER_SEARCH_PATHS = ( + "$(inherited)", + "third-party/fmt/include", + "third-party/small/include", + ); + }; + name = "Release - Debug"; + }; + ED5E0E912CD30B180071433B /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_ENTITLEMENTS = macosx/QuickLookExtension/QuickLookExtension.entitlements; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + ., + ); + INFOPLIST_FILE = macosx/QuickLookExtension/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = QuickLookExtension; + INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2024 The Transmission Project. All rights reserved."; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@executable_path/../../../../Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = 12.0; + MARKETING_VERSION = 1.0; + OTHER_CPLUSPLUSFLAGS = ( + "$(inherited)", + "-fmodules", + "-fcxx-modules", + ); + PRODUCT_BUNDLE_IDENTIFIER = org.m0k.transmission.QuickLookExtension; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + SYSTEM_HEADER_SEARCH_PATHS = ( + "$(inherited)", + "third-party/fmt/include", + "third-party/small/include", + ); + }; + name = Release; + }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ @@ -5532,6 +5811,16 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Debug; }; + ED5E0E932CD30B180071433B /* Build configuration list for PBXNativeTarget "QuickLookExtension" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + ED5E0E8F2CD30B180071433B /* Debug */, + ED5E0E902CD30B180071433B /* Release - Debug */, + ED5E0E912CD30B180071433B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; /* End XCConfigurationList section */ }; rootObject = 29B97313FDCFA39411CA2CEA /* Project object */; diff --git a/macosx/CMakeLists.txt b/macosx/CMakeLists.txt index a0a00c031..ed8c35815 100644 --- a/macosx/CMakeLists.txt +++ b/macosx/CMakeLists.txt @@ -28,6 +28,7 @@ add_link_options( # equivalent of XCODE_ATTRIBUTE_DEAD_CODE_STRIPPING YES for this directory $<$:-dead_strip>) +add_subdirectory(QuickLookExtension) add_subdirectory(QuickLookPlugin) add_subdirectory(VDKQueue) diff --git a/macosx/QuickLookExtension/CMakeLists.txt b/macosx/QuickLookExtension/CMakeLists.txt new file mode 100644 index 000000000..8043d2106 --- /dev/null +++ b/macosx/QuickLookExtension/CMakeLists.txt @@ -0,0 +1,117 @@ +set(MAC_QL_BUNDLE_NAME QuickLookExtension) + +add_library(${TR_NAME}-mac-qlappex MODULE) + +target_sources(${TR_NAME}-mac-qlappex + PRIVATE + ../NSStringAdditions.mm + PreviewProvider.mm) + +set(LINGUAS + da + de + en + es + eu + fr + he + hu + it + ja + nl + pl + pt-BR + pt-PT + ru + sv + tr + uk + zh-CN + zh-TW) + +if(ENABLE_NLS) + set(ENABLED_LINGUAS ${LINGUAS}) +else() + set(ENABLED_LINGUAS en) +endif() + +set(LANG_STRINGS_FILES + Localizable.strings) + +set(RESOURCES + style.css) +source_group(Resources + FILES ${RESOURCES}) + +set_source_files_properties( + ${RESOURCES} + PROPERTIES + MACOSX_PACKAGE_LOCATION Resources) + +foreach(LANG ${ENABLED_LINGUAS}) + set(${LANG}_STRINGS_FILES) + set(STRINGS_FILES_RESOURCES_DIR Resources) + if(NOT CMAKE_GENERATOR STREQUAL Xcode) + string(APPEND STRINGS_FILES_RESOURCES_DIR /${LANG}.lproj) + endif() + foreach(F ${LANG_STRINGS_FILES}) + list(APPEND ${LANG}_STRINGS_FILES ${LANG}.lproj/${F}) + list(APPEND RESOURCES ${${LANG}_STRINGS_FILES}) + set_source_files_properties( + ${${LANG}_STRINGS_FILES} + PROPERTIES + MACOSX_PACKAGE_LOCATION ${STRINGS_FILES_RESOURCES_DIR}) + endforeach() + source_group(Resources/${LANG}.lproj + FILES ${${LANG}_STRINGS_FILES}) +endforeach() + +target_sources(${TR_NAME}-mac-qlappex + PRIVATE + ${RESOURCES}) + +set_target_properties( + ${TR_NAME}-mac-qlappex + PROPERTIES + BUNDLE ON + BUNDLE_EXTENSION appex + INSTALL_RPATH "@loader_path/../../../../MacOS;@loader_path/../../../../Frameworks" + XCODE_ATTRIBUTE_MACOSX_DEPLOYMENT_TARGET "12.0" + MACOSX_BUNDLE ON + MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/Info.plist.in" + OUTPUT_NAME ${MAC_QL_BUNDLE_NAME}) + +target_compile_options( + ${TR_NAME}-mac-qlappex + PUBLIC + "-mmacosx-version-min=12.0") + +target_link_options( + ${TR_NAME}-mac-qlappex + PUBLIC + "-mmacosx-version-min=12.0") + +target_include_directories(${TR_NAME}-mac-qlappex + PRIVATE + ..) + +target_link_libraries(${TR_NAME}-mac-qlappex + PRIVATE + ${TR_NAME} + "-framework Foundation" + "-framework CoreFoundation" + "-framework CoreServices" + "-framework Quartz" + "-framework QuickLook") + +install( + TARGETS ${TR_NAME}-mac-qlappex + DESTINATION Applications/${MAC_BUNDLE_NAME}.app/Contents/PlugIns) + +install(CODE + "list(APPEND CMAKE_MODULE_PATH \"${PROJECT_SOURCE_DIR}/cmake\") + include(TrMacros) + include(GetPrerequisites) + tr_fixup_bundle_item( + \"\$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/Applications/${MAC_BUNDLE_NAME}.app\" + \"Contents/PlugIns/${MAC_QL_BUNDLE_NAME}.appex/Contents/MacOS/${MAC_QL_BUNDLE_NAME}\" \"\")") diff --git a/macosx/QuickLookExtension/Info.plist b/macosx/QuickLookExtension/Info.plist new file mode 100644 index 000000000..5b733569c --- /dev/null +++ b/macosx/QuickLookExtension/Info.plist @@ -0,0 +1,24 @@ + + + + + NSExtension + + NSExtensionAttributes + + QLIsDataBasedPreview + + QLSupportedContentTypes + + org.bittorrent.torrent + + QLSupportsSearchableItems + + + NSExtensionPointIdentifier + com.apple.quicklook.preview + NSExtensionPrincipalClass + PreviewProvider + + + diff --git a/macosx/QuickLookExtension/Info.plist.in b/macosx/QuickLookExtension/Info.plist.in new file mode 100644 index 000000000..2b3782848 --- /dev/null +++ b/macosx/QuickLookExtension/Info.plist.in @@ -0,0 +1,50 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleDisplayName + QuickLookExtension + CFBundleExecutable + QuickLookExtension + CFBundleIdentifier + org.m0k.transmission.QuickLookExtension + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + QuickLookExtension + CFBundlePackageType + XPC! + CFBundleShortVersionString + 1.0 + CFBundleSupportedPlatforms + + MacOSX + + CFBundleVersion + 1 + LSMinimumSystemVersion + 12.0 + NSExtension + + NSExtensionAttributes + + QLIsDataBasedPreview + + QLSupportedContentTypes + + org.bittorrent.torrent + + QLSupportsSearchableItems + + + NSExtensionPointIdentifier + com.apple.quicklook.preview + NSExtensionPrincipalClass + PreviewProvider + + NSHumanReadableCopyright + Copyright © 2024 The Transmission Project. All rights reserved. + + diff --git a/macosx/QuickLookExtension/PreviewProvider.h b/macosx/QuickLookExtension/PreviewProvider.h new file mode 100644 index 000000000..6e6299028 --- /dev/null +++ b/macosx/QuickLookExtension/PreviewProvider.h @@ -0,0 +1,10 @@ +// This file Copyright © Transmission authors and contributors. +// It may be used under the MIT (SPDX: MIT) license. +// License text can be found in the licenses/ folder. + +#import +#import + +@interface PreviewProvider : QLPreviewProvider + +@end diff --git a/macosx/QuickLookExtension/PreviewProvider.mm b/macosx/QuickLookExtension/PreviewProvider.mm new file mode 100644 index 000000000..36ff26ea6 --- /dev/null +++ b/macosx/QuickLookExtension/PreviewProvider.mm @@ -0,0 +1,290 @@ +// This file Copyright © Transmission authors and contributors. +// It may be used under the MIT (SPDX: MIT) license. +// License text can be found in the licenses/ folder. + +#import "PreviewProvider.h" + +#include +#include +#include + +#include +#include + +#import "NSStringAdditions.h" + +static NSUInteger const kIconWidth = 16; + +namespace +{ + +class FileTreeNode +{ + public: + FileTreeNode() = default; + ~FileTreeNode() = default; + + auto MaybeCreateChild(std::string_view child_name) + { + return children_.try_emplace(std::string{ child_name }); + } + + private: + FileTreeNode(FileTreeNode const&) = delete; + FileTreeNode& operator=(FileTreeNode&) = delete; + + std::unordered_map children_; +}; + +} // namespace + +NSString* generateIconData(UTType* type, NSUInteger width, NSMutableDictionary* allImgProps) +{ + // We need to do this once per file type, per image size + NSString* iconFileName = [NSString stringWithFormat:@"%@.%ld.tiff", type.identifier, width]; + + if (!allImgProps[iconFileName]) + { + NSImage* icon = [NSWorkspace.sharedWorkspace iconForContentType:type]; + + NSRect const iconFrame = NSMakeRect(0.0, 0.0, width, width); + NSImage* renderedIcon = [[NSImage alloc] initWithSize:iconFrame.size]; + [renderedIcon lockFocus]; + [icon drawInRect:iconFrame]; + [renderedIcon unlockFocus]; + + NSData* iconData = renderedIcon.TIFFRepresentation; + + QLPreviewReplyAttachment* imageAttachment = [[QLPreviewReplyAttachment alloc] initWithData:iconData contentType:UTTypePNG]; + + allImgProps[iconFileName] = imageAttachment; + } + + return [@"cid:" stringByAppendingString:iconFileName]; +} + +@implementation PreviewProvider + +- (void)providePreviewForFileRequest:(QLFilePreviewRequest*)request + completionHandler:(void (^)(QLPreviewReply* _Nullable reply, NSError* _Nullable error))handler +{ + QLPreviewReply* reply = [[QLPreviewReply alloc] + initWithDataOfContentType:UTTypeHTML + contentSize:CGSizeMake(1200, 800) + dataCreationBlock:^NSData* _Nullable(QLPreviewReply* _Nonnull replyToUpdate, NSError* __autoreleasing _Nullable* _Nullable error) { + NSString* previewHTML = [self generateHTMLPreviewFor:request.fileURL andReply:replyToUpdate]; + + return [previewHTML dataUsingEncoding:NSUTF8StringEncoding]; + }]; + + handler(reply, nil); +} + +- (NSString*)generateHTMLPreviewFor:(NSURL*)url andReply:(QLPreviewReply* _Nonnull)replyToUpdate +{ + // Try to parse the torrent file + auto metainfo = tr_torrent_metainfo{}; + if (!metainfo.parse_torrent_file(url.fileSystemRepresentation)) + { + return nil; + } + + NSBundle* bundle = NSBundle.mainBundle; + + NSURL* styleURL = [bundle URLForResource:@"style" withExtension:@"css"]; + NSString* styleContents = [NSString stringWithContentsOfURL:styleURL encoding:NSUTF8StringEncoding error:NULL]; + + NSMutableString* htmlString = [NSMutableString string]; + [htmlString appendFormat:@"", styleContents]; + + NSMutableDictionary* attachments = [NSMutableDictionary dictionary]; + + NSString* name = @(metainfo.name().c_str()); + + auto const n_files = metainfo.file_count(); + auto const is_multifile = n_files > 1; + UTType* fileType = is_multifile ? UTTypeFolder : [UTType typeWithFilenameExtension:name.pathExtension]; + + NSUInteger const width = 32; + [htmlString appendFormat:@"

%@

", + generateIconData(fileType, width, attachments), + width, + width, + name]; + + NSString* fileSizeString = [NSString stringForFileSize:metainfo.total_size()]; + if (is_multifile) + { + NSString* fileCountString = [NSString + localizedStringWithFormat:NSLocalizedStringFromTableInBundle(@"%lu files", nil, bundle, "quicklook file count"), n_files]; + fileSizeString = [NSString stringWithFormat:@"%@, %@", fileCountString, fileSizeString]; + } + [htmlString appendFormat:@"

%@

", fileSizeString]; + + auto const date_created = metainfo.date_created(); + NSString* dateCreatedString = date_created > 0 ? + [NSDateFormatter localizedStringFromDate:[NSDate dateWithTimeIntervalSince1970:date_created] dateStyle:NSDateFormatterLongStyle + timeStyle:NSDateFormatterShortStyle] : + nil; + auto const& creator = metainfo.creator(); + NSString* creatorString = !std::empty(creator) ? @(creator.c_str()) : nil; + if ([creatorString isEqualToString:@""]) + { + creatorString = nil; + } + NSString* creationString = nil; + if (dateCreatedString && creatorString) + { + creationString = [NSString + stringWithFormat:NSLocalizedStringFromTableInBundle(@"Created on %@ with %@", nil, bundle, "quicklook creation info"), + dateCreatedString, + creatorString]; + } + else if (dateCreatedString) + { + creationString = [NSString + stringWithFormat:NSLocalizedStringFromTableInBundle(@"Created on %@", nil, bundle, "quicklook creation info"), dateCreatedString]; + } + else if (creatorString) + { + creationString = [NSString + stringWithFormat:NSLocalizedStringFromTableInBundle(@"Created with %@", nil, bundle, "quicklook creation info"), creatorString]; + } + if (creationString) + { + [htmlString appendFormat:@"

%@

", creationString]; + } + + auto const& commentStr = metainfo.comment(); + if (!std::empty(commentStr)) + { + NSString* comment = @(commentStr.c_str()); + if (![comment isEqualToString:@""]) + [htmlString appendFormat:@"

%@

", comment]; + } + + NSMutableArray* lists = [NSMutableArray array]; + + auto const n_webseeds = metainfo.webseed_count(); + if (n_webseeds > 0) + { + NSMutableString* listSection = [NSMutableString string]; + [listSection appendString:@""]; + + NSString* headerTitleString = n_webseeds == 1 ? + NSLocalizedStringFromTableInBundle(@"1 Web Seed", nil, bundle, "quicklook web seed header") : + [NSString localizedStringWithFormat:NSLocalizedStringFromTableInBundle(@"%lu Web Seeds", nil, bundle, "quicklook web seed header"), + n_webseeds]; + [listSection appendFormat:@"", headerTitleString]; + + for (size_t i = 0; i < n_webseeds; ++i) + { + [listSection appendFormat:@"", metainfo.webseed(i).c_str()]; + } + + [listSection appendString:@"
%@
%s
"]; + + [lists addObject:listSection]; + } + + auto const& announce_list = metainfo.announce_list(); + if (!std::empty(announce_list)) + { + NSMutableString* listSection = [NSMutableString string]; + [listSection appendString:@""]; + + auto const n = std::size(announce_list); + NSString* headerTitleString = n == 1 ? + NSLocalizedStringFromTableInBundle(@"1 Tracker", nil, bundle, "quicklook tracker header") : + [NSString localizedStringWithFormat:NSLocalizedStringFromTableInBundle(@"%lu Trackers", nil, bundle, "quicklook tracker header"), n]; + [listSection appendFormat:@"", headerTitleString]; + + // TODO: handle tiers? + for (auto const& tracker : announce_list) + { + [listSection appendFormat:@"", tracker.announce.c_str()]; + } + + [listSection appendString:@"
%@
%s
"]; + + [lists addObject:listSection]; + } + + if (is_multifile) + { + NSMutableString* listSection = [NSMutableString string]; + [listSection appendString:@""]; + + NSString* fileTitleString = [NSString + localizedStringWithFormat:NSLocalizedStringFromTableInBundle(@"%lu Files", nil, bundle, "quicklook file header"), n_files]; + [listSection appendFormat:@"", fileTitleString]; + + FileTreeNode root{}; + + for (auto const& [path, size] : metainfo.files().sorted_by_path()) + { + FileTreeNode* curNode = &root; + size_t level = 0; + + auto subpath = std::string_view{ path }; + auto path_vec = std::vector{}; + auto token = std::string_view{}; + while (tr_strv_sep(&subpath, &token, '/')) + { + path_vec.emplace_back(token); + } + size_t const last = path_vec.size() - 1; + + for (auto const& part : path_vec) + { + auto [it, inserted] = curNode->MaybeCreateChild(part); + if (inserted) + { + NSString* pathPart = @(it->first.c_str()); + UTType* pathType = nil; + NSString* fileSize = nil; + if (level < last) + { + // This node is a directory. + pathType = UTTypeFolder; + fileSize = @""; + } + else + { + // This node is a leaf file. + pathType = [UTType typeWithFilenameExtension:pathPart.pathExtension]; + fileSize = [NSString stringForFileSize:size]; + } + + [listSection appendFormat:@"", + level * kIconWidth, + generateIconData(pathType, kIconWidth, attachments), + kIconWidth, + kIconWidth, + pathPart, + fileSize]; + } + + curNode = &it->second; + level++; + } + } + + [listSection appendString:@"
%@
%@%@
"]; + + [lists addObject:listSection]; + } + + if (lists.count > 0) + { + [htmlString appendFormat:@"

%@", [lists componentsJoinedByString:@"
"]]; + } + + [htmlString appendString:@""]; + + replyToUpdate.attachments = attachments; + + return htmlString; +} + +@end diff --git a/macosx/QuickLookExtension/QuickLookExtension.entitlements b/macosx/QuickLookExtension/QuickLookExtension.entitlements new file mode 100644 index 000000000..f2ef3ae02 --- /dev/null +++ b/macosx/QuickLookExtension/QuickLookExtension.entitlements @@ -0,0 +1,10 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.files.user-selected.read-only + + + diff --git a/macosx/QuickLookExtension/da.lproj/Localizable.strings b/macosx/QuickLookExtension/da.lproj/Localizable.strings new file mode 100644 index 000000000..8337ba564 --- /dev/null +++ b/macosx/QuickLookExtension/da.lproj/Localizable.strings @@ -0,0 +1,27 @@ +/* quicklook file header */ +"%lu Files" = "%lu Filer"; + +/* quicklook file count */ +"%lu files" = "%lu filer"; + +/* quicklook tracker header */ +"%lu Trackers" = "%lu Trackere"; + +/* quicklook web seed header */ +"%lu Web Seeds" = "%lu Webseeds"; + +/* quicklook tracker header */ +"1 Tracker" = "1 Tracker"; + +/* quicklook web seed header */ +"1 Web Seed" = "1 webseed"; + +/* quicklook creation info */ +"Created on %@" = "Oprettet %@"; + +/* quicklook creation info */ +"Created on %@ with %@" = "Oprettet %1$@ med %2$@"; + +/* quicklook creation info */ +"Created with %@" = "Oprettet med %@"; + diff --git a/macosx/QuickLookExtension/de.lproj/Localizable.strings b/macosx/QuickLookExtension/de.lproj/Localizable.strings new file mode 100644 index 000000000..764bb6d6b --- /dev/null +++ b/macosx/QuickLookExtension/de.lproj/Localizable.strings @@ -0,0 +1,27 @@ +/* quicklook file header */ +"%lu Files" = "%lu Dateien"; + +/* quicklook file count */ +"%lu files" = "%lu Dateien"; + +/* quicklook tracker header */ +"%lu Trackers" = "%lu Tracker"; + +/* quicklook web seed header */ +"%lu Web Seeds" = "%lu Web-Verteiler"; + +/* quicklook tracker header */ +"1 Tracker" = "1 Tracker"; + +/* quicklook web seed header */ +"1 Web Seed" = "1 Web-Verteiler"; + +/* quicklook creation info */ +"Created on %@" = "Erstellt am %@"; + +/* quicklook creation info */ +"Created on %@ with %@" = "Erstellt am %1$@ mit %2$@"; + +/* quicklook creation info */ +"Created with %@" = "Erstellt mit %@"; + diff --git a/macosx/QuickLookExtension/en.lproj/Localizable.strings b/macosx/QuickLookExtension/en.lproj/Localizable.strings new file mode 100644 index 000000000..2abdafada --- /dev/null +++ b/macosx/QuickLookExtension/en.lproj/Localizable.strings @@ -0,0 +1,27 @@ +/* quicklook file header */ +"%lu Files" = "%lu Files"; + +/* quicklook file count */ +"%lu files" = "%lu files"; + +/* quicklook tracker header */ +"%lu Trackers" = "%lu Trackers"; + +/* quicklook web seed header */ +"%lu Web Seeds" = "%lu Web Seeds"; + +/* quicklook tracker header */ +"1 Tracker" = "1 Tracker"; + +/* quicklook web seed header */ +"1 Web Seed" = "1 Web Seed"; + +/* quicklook creation info */ +"Created on %@" = "Created on %@"; + +/* quicklook creation info */ +"Created on %@ with %@" = "Created on %1$@ with %2$@"; + +/* quicklook creation info */ +"Created with %@" = "Created with %@"; + diff --git a/macosx/QuickLookExtension/es.lproj/Localizable.strings b/macosx/QuickLookExtension/es.lproj/Localizable.strings new file mode 100644 index 000000000..9ab0bc7ef --- /dev/null +++ b/macosx/QuickLookExtension/es.lproj/Localizable.strings @@ -0,0 +1,27 @@ +/* quicklook file header */ +"%lu Files" = "%lu Archivos"; + +/* quicklook file count */ +"%lu files" = "%lu archivos"; + +/* quicklook tracker header */ +"%lu Trackers" = "%lu Trackers"; + +/* quicklook web seed header */ +"%lu Web Seeds" = "%lu Semillas Web"; + +/* quicklook tracker header */ +"1 Tracker" = "1 Tracker"; + +/* quicklook web seed header */ +"1 Web Seed" = "1 Semilla Web"; + +/* quicklook creation info */ +"Created on %@" = "Creado el %@"; + +/* quicklook creation info */ +"Created on %@ with %@" = "Creado el %1$@ con %2$@"; + +/* quicklook creation info */ +"Created with %@" = "Creado con %@"; + diff --git a/macosx/QuickLookExtension/eu.lproj/Localizable.strings b/macosx/QuickLookExtension/eu.lproj/Localizable.strings new file mode 100644 index 000000000..cf29a1d0d --- /dev/null +++ b/macosx/QuickLookExtension/eu.lproj/Localizable.strings @@ -0,0 +1,27 @@ +/* quicklook file header */ +"%lu Files" = "%lu Fitxategiak"; + +/* quicklook file count */ +"%lu files" = "%lu fitxategiak"; + +/* quicklook tracker header */ +"%lu Trackers" = "%lu Aztarnariak"; + +/* quicklook web seed header */ +"%lu Web Seeds" = "%lu Web Igorleak"; + +/* quicklook tracker header */ +"1 Tracker" = "Aztarnari 1"; + +/* quicklook web seed header */ +"1 Web Seed" = "1 Web hazia"; + +/* quicklook creation info */ +"Created on %@" = "%@ Sortua "; + +/* quicklook creation info */ +"Created on %@ with %@" = "Honekin %2$@ %1$@ Sortua "; + +/* quicklook creation info */ +"Created with %@" = "%@ Honekin sortua"; + diff --git a/macosx/QuickLookExtension/fr.lproj/Localizable.strings b/macosx/QuickLookExtension/fr.lproj/Localizable.strings new file mode 100644 index 000000000..1afad2ad4 --- /dev/null +++ b/macosx/QuickLookExtension/fr.lproj/Localizable.strings @@ -0,0 +1,27 @@ +/* quicklook file header */ +"%lu Files" = "%lu fichiers"; + +/* quicklook file count */ +"%lu files" = "%lu fichiers"; + +/* quicklook tracker header */ +"%lu Trackers" = "%lu traceurs"; + +/* quicklook web seed header */ +"%lu Web Seeds" = "%lu semences Web"; + +/* quicklook tracker header */ +"1 Tracker" = "1 traceur"; + +/* quicklook web seed header */ +"1 Web Seed" = "1 semence Web"; + +/* quicklook creation info */ +"Created on %@" = "Créé le %@"; + +/* quicklook creation info */ +"Created on %@ with %@" = "Créé le %1$@ avec %2$@"; + +/* quicklook creation info */ +"Created with %@" = "Créé avec %@"; + diff --git a/macosx/QuickLookExtension/he.lproj/Localizable.strings b/macosx/QuickLookExtension/he.lproj/Localizable.strings new file mode 100644 index 000000000..4bfc30350 --- /dev/null +++ b/macosx/QuickLookExtension/he.lproj/Localizable.strings @@ -0,0 +1,27 @@ +/* quicklook file header */ +"%lu Files" = "%lu קבצים"; + +/* quicklook file count */ +"%lu files" = "%lu קבצים"; + +/* quicklook tracker header */ +"%lu Trackers" = "%lu עוקבים"; + +/* quicklook web seed header */ +"%lu Web Seeds" = "%lu זורעי רשת"; + +/* quicklook tracker header */ +"1 Tracker" = "עוקב אחד"; + +/* quicklook web seed header */ +"1 Web Seed" = "זורע רשת אחד"; + +/* quicklook creation info */ +"Created on %@" = "נוצר ב־%@"; + +/* quicklook creation info */ +"Created on %@ with %@" = "נוצר ב־%1$@ עם %2$@"; + +/* quicklook creation info */ +"Created with %@" = "נוצר עם %@"; + diff --git a/macosx/QuickLookExtension/hu.lproj/Localizable.strings b/macosx/QuickLookExtension/hu.lproj/Localizable.strings new file mode 100644 index 000000000..67973edad --- /dev/null +++ b/macosx/QuickLookExtension/hu.lproj/Localizable.strings @@ -0,0 +1,27 @@ +/* quicklook file header */ +"%lu Files" = "%lu Fájl"; + +/* quicklook file count */ +"%lu files" = "%lu Fájl"; + +/* quicklook tracker header */ +"%lu Trackers" = "%lu Tracker"; + +/* quicklook web seed header */ +"%lu Web Seeds" = "%lu Web seed"; + +/* quicklook tracker header */ +"1 Tracker" = "1 Tracker"; + +/* quicklook web seed header */ +"1 Web Seed" = "1 Web seed"; + +/* quicklook creation info */ +"Created on %@" = "Létrehozva ekkor: %@"; + +/* quicklook creation info */ +"Created on %@ with %@" = "Létrehozva ekkor: %1$@, ezzel: %2$@"; + +/* quicklook creation info */ +"Created with %@" = "Létrehozva ezzel: %@"; + diff --git a/macosx/QuickLookExtension/it.lproj/Localizable.strings b/macosx/QuickLookExtension/it.lproj/Localizable.strings new file mode 100644 index 000000000..095c5ed01 --- /dev/null +++ b/macosx/QuickLookExtension/it.lproj/Localizable.strings @@ -0,0 +1,27 @@ +/* quicklook file header */ +"%lu Files" = "%lu file"; + +/* quicklook file count */ +"%lu files" = "%lu file"; + +/* quicklook tracker header */ +"%lu Trackers" = "%lu server traccia"; + +/* quicklook web seed header */ +"%lu Web Seeds" = "%lu seeder web"; + +/* quicklook tracker header */ +"1 Tracker" = "1 server traccia"; + +/* quicklook web seed header */ +"1 Web Seed" = "1 seeder web"; + +/* quicklook creation info */ +"Created on %@" = "Creato il %@"; + +/* quicklook creation info */ +"Created on %@ with %@" = "Creato il %1$@ con %2$@"; + +/* quicklook creation info */ +"Created with %@" = "Creato con %@"; + diff --git a/macosx/QuickLookExtension/ja.lproj/Localizable.strings b/macosx/QuickLookExtension/ja.lproj/Localizable.strings new file mode 100644 index 000000000..145bb2875 --- /dev/null +++ b/macosx/QuickLookExtension/ja.lproj/Localizable.strings @@ -0,0 +1,27 @@ +/* quicklook file header */ +"%lu Files" = "%luファイル"; + +/* quicklook file count */ +"%lu files" = "%luファイル"; + +/* quicklook tracker header */ +"%lu Trackers" = "%luトラッカー"; + +/* quicklook web seed header */ +"%lu Web Seeds" = "%luウェブシード"; + +/* quicklook tracker header */ +"1 Tracker" = "1トラッカー"; + +/* quicklook web seed header */ +"1 Web Seed" = "1ウェブシード"; + +/* quicklook creation info */ +"Created on %@" = "作成日 %@"; + +/* quicklook creation info */ +"Created on %@ with %@" = "作成日 %1$@ / 作成 %2$@"; + +/* quicklook creation info */ +"Created with %@" = "作成 %@"; + diff --git a/macosx/QuickLookExtension/nl.lproj/Localizable.strings b/macosx/QuickLookExtension/nl.lproj/Localizable.strings new file mode 100644 index 000000000..127396159 --- /dev/null +++ b/macosx/QuickLookExtension/nl.lproj/Localizable.strings @@ -0,0 +1,27 @@ +/* quicklook file header */ +"%lu Files" = "%lu bestanden"; + +/* quicklook file count */ +"%lu files" = "%lu bestanden"; + +/* quicklook tracker header */ +"%lu Trackers" = "%lu trackers"; + +/* quicklook web seed header */ +"%lu Web Seeds" = "%lu webseeds"; + +/* quicklook tracker header */ +"1 Tracker" = "1 tracker"; + +/* quicklook web seed header */ +"1 Web Seed" = "1 webseed"; + +/* quicklook creation info */ +"Created on %@" = "Gemaakt op %@"; + +/* quicklook creation info */ +"Created on %@ with %@" = "Gemaakt op %1$@ met %2$@"; + +/* quicklook creation info */ +"Created with %@" = "Gemaakt met %@"; + diff --git a/macosx/QuickLookExtension/pl.lproj/Localizable.strings b/macosx/QuickLookExtension/pl.lproj/Localizable.strings new file mode 100644 index 000000000..012f55685 --- /dev/null +++ b/macosx/QuickLookExtension/pl.lproj/Localizable.strings @@ -0,0 +1,27 @@ +/* quicklook file header */ +"%lu Files" = "%lu pliki(-ów)"; + +/* quicklook file count */ +"%lu files" = "%lu pliki(-ów)"; + +/* quicklook tracker header */ +"%lu Trackers" = "%lu serwery(-ów) śledzące(-ych)"; + +/* quicklook web seed header */ +"%lu Web Seeds" = "%lu wysyłające(-ych) w sieci"; + +/* quicklook tracker header */ +"1 Tracker" = "1 serwer śledzący"; + +/* quicklook web seed header */ +"1 Web Seed" = "1 wysyłający w sieci"; + +/* quicklook creation info */ +"Created on %@" = "Utworzony dnia %@"; + +/* quicklook creation info */ +"Created on %@ with %@" = "Utworzony dnia %1$@ przez: %2$@"; + +/* quicklook creation info */ +"Created with %@" = "Utworzony za pomocą: %@"; + diff --git a/macosx/QuickLookExtension/pt-BR.lproj/Localizable.strings b/macosx/QuickLookExtension/pt-BR.lproj/Localizable.strings new file mode 100644 index 000000000..bf497c2ab --- /dev/null +++ b/macosx/QuickLookExtension/pt-BR.lproj/Localizable.strings @@ -0,0 +1,27 @@ +/* quicklook file header */ +"%lu Files" = "%lu Arquivos"; + +/* quicklook file count */ +"%lu files" = "%lu arquivos"; + +/* quicklook tracker header */ +"%lu Trackers" = "%lu Rastreadores"; + +/* quicklook web seed header */ +"%lu Web Seeds" = "%lu Semeadores da Web"; + +/* quicklook tracker header */ +"1 Tracker" = "1 Rastreador"; + +/* quicklook web seed header */ +"1 Web Seed" = "1 Semeador Web"; + +/* quicklook creation info */ +"Created on %@" = "Criado em %@"; + +/* quicklook creation info */ +"Created on %@ with %@" = "Criado em %1$@ com %2$@"; + +/* quicklook creation info */ +"Created with %@" = "Criado com %@"; + diff --git a/macosx/QuickLookExtension/pt-PT.lproj/Localizable.strings b/macosx/QuickLookExtension/pt-PT.lproj/Localizable.strings new file mode 100644 index 000000000..3f4f037a1 --- /dev/null +++ b/macosx/QuickLookExtension/pt-PT.lproj/Localizable.strings @@ -0,0 +1,27 @@ +/* quicklook file header */ +"%lu Files" = "%lu Ficheiros"; + +/* quicklook file count */ +"%lu files" = "%lu ficheiros"; + +/* quicklook tracker header */ +"%lu Trackers" = "%lu Trackers"; + +/* quicklook web seed header */ +"%lu Web Seeds" = "%lu Seeds web"; + +/* quicklook tracker header */ +"1 Tracker" = "1 Tracker"; + +/* quicklook web seed header */ +"1 Web Seed" = "1 Seed Web"; + +/* quicklook creation info */ +"Created on %@" = "Criado a %@"; + +/* quicklook creation info */ +"Created on %@ with %@" = "Criado a %1$@ com o %2$@"; + +/* quicklook creation info */ +"Created with %@" = "Criado com %@"; + diff --git a/macosx/QuickLookExtension/ru.lproj/Localizable.strings b/macosx/QuickLookExtension/ru.lproj/Localizable.strings new file mode 100644 index 000000000..1001c714d --- /dev/null +++ b/macosx/QuickLookExtension/ru.lproj/Localizable.strings @@ -0,0 +1,27 @@ +/* quicklook file header */ +"%lu Files" = "%lu файлов"; + +/* quicklook file count */ +"%lu files" = "%lu файлов"; + +/* quicklook tracker header */ +"%lu Trackers" = "%lu трекеров"; + +/* quicklook web seed header */ +"%lu Web Seeds" = "%lu сайтов раздачи"; + +/* quicklook tracker header */ +"1 Tracker" = "1 трекер"; + +/* quicklook web seed header */ +"1 Web Seed" = "1 сайт раздачи"; + +/* quicklook creation info */ +"Created on %@" = "Создан %@"; + +/* quicklook creation info */ +"Created on %@ with %@" = "Создан %1$@, с использованием %2$@"; + +/* quicklook creation info */ +"Created with %@" = "Создан с использованием %@"; + diff --git a/macosx/QuickLookExtension/style.css b/macosx/QuickLookExtension/style.css new file mode 100644 index 000000000..18c6bff34 --- /dev/null +++ b/macosx/QuickLookExtension/style.css @@ -0,0 +1,106 @@ +:root { + color-scheme: light dark; + + --bg-color: rgb(255, 255, 255); + --fg-color: rgb(0, 0, 0); + + --header-text-color: rgb(50, 50, 50); + --header-underline-color: rgb(230, 230, 230); + + --row-fg-color: rgb(40, 40, 40); + + --alt-row-bg-color: rgb(245, 245, 245); + --alt-col-fg-color: rgb(133, 133, 133); +} + +@media (prefers-color-scheme: dark) { + :root { + --bg-color: rgb(30, 30, 30); + --fg-color: rgb(255, 255, 255); + + --header-text-color: rgb(200, 200, 200); + --header-underline-color: rgb(55, 55, 55); + + --row-fg-color: rgb(225, 225, 225); + + --alt-row-bg-color: rgb(40, 40, 40); + --alt-col-fg-color: rgb(155, 155, 155); + } +} + +html { + background: var(--bg-color); + color: var(--fg-color); + + font-family: -apple-system, BlinkMacSystemFont, system-ui; + text-align: left; +} + +table { + width: 100%; + border-spacing: 0; +} + +/* Sticky Table Header Row */ +tr:has(th) { + top: 0; + position: sticky; + + background: var(--bg-color); +} + +th { + padding-top: 8px; + + color: var(--header-text-color); + border-bottom: 1px solid var(--header-underline-color); + + font-weight: 500; + text-align: left; +} + +tr:has(td):nth-child(odd) { + background: var(--alt-row-bg-color); +} + +td { + color: var(--row-fg-color); +} + +td.grey { + color: var(--alt-col-fg-color); +} + +td:first-child { + padding-left: 8px; + + border-top-left-radius: 5px; + border-bottom-left-radius: 5px; +} + +td:last-child { + padding-right: 8px; + + border-top-right-radius: 5px; + border-bottom-right-radius: 5px; +} + +td:nth-child(1) { + text-align: left; + + max-width: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +td:nth-child(2) { + text-align: right; + + width: 80px; +} + +img.icon { + margin-right: 8px; + vertical-align: text-bottom; +} diff --git a/macosx/QuickLookExtension/sv.lproj/Localizable.strings b/macosx/QuickLookExtension/sv.lproj/Localizable.strings new file mode 100644 index 000000000..a094519f5 --- /dev/null +++ b/macosx/QuickLookExtension/sv.lproj/Localizable.strings @@ -0,0 +1,27 @@ +/* quicklook file header */ +"%lu Files" = "%lu filer"; + +/* quicklook file count */ +"%lu files" = "%lu filer"; + +/* quicklook tracker header */ +"%lu Trackers" = "%lu spårare"; + +/* quicklook web seed header */ +"%lu Web Seeds" = "%lu webbdistributioner"; + +/* quicklook tracker header */ +"1 Tracker" = "1 spårare"; + +/* quicklook web seed header */ +"1 Web Seed" = "1 webbdistribution"; + +/* quicklook creation info */ +"Created on %@" = "Skapades den %@"; + +/* quicklook creation info */ +"Created on %@ with %@" = "Skapades den %1$@ med %2$@"; + +/* quicklook creation info */ +"Created with %@" = "Skapades med %@"; + diff --git a/macosx/QuickLookExtension/tr.lproj/Localizable.strings b/macosx/QuickLookExtension/tr.lproj/Localizable.strings new file mode 100644 index 000000000..9505e2ee9 --- /dev/null +++ b/macosx/QuickLookExtension/tr.lproj/Localizable.strings @@ -0,0 +1,27 @@ +/* quicklook file header */ +"%lu Files" = "%lu Dosya"; + +/* quicklook file count */ +"%lu files" = "%lu dosya"; + +/* quicklook tracker header */ +"%lu Trackers" = "%lu İzleyici"; + +/* quicklook web seed header */ +"%lu Web Seeds" = "%lu Web Beslemesi"; + +/* quicklook tracker header */ +"1 Tracker" = "1 İzleyici"; + +/* quicklook web seed header */ +"1 Web Seed" = "1 Web Beslemesi"; + +/* quicklook creation info */ +"Created on %@" = "%@ üzerinde oluşturuldu"; + +/* quicklook creation info */ +"Created on %@ with %@" = "%1$@ üzerinde %2$@ ile oluşturuldu"; + +/* quicklook creation info */ +"Created with %@" = "%@ ile oluşturuldu"; + diff --git a/macosx/QuickLookExtension/uk.lproj/Localizable.strings b/macosx/QuickLookExtension/uk.lproj/Localizable.strings new file mode 100644 index 000000000..d8c919c20 --- /dev/null +++ b/macosx/QuickLookExtension/uk.lproj/Localizable.strings @@ -0,0 +1,27 @@ +/* quicklook file header */ +"%lu Files" = "%lu Файлів"; + +/* quicklook file count */ +"%lu files" = "%lu файлів"; + +/* quicklook tracker header */ +"%lu Trackers" = "%lu Відстежувачів"; + +/* quicklook web seed header */ +"%lu Web Seeds" = "%lu Висівів"; + +/* quicklook tracker header */ +"1 Tracker" = "1 Відстежувач"; + +/* quicklook web seed header */ +"1 Web Seed" = "1 Висів"; + +/* quicklook creation info */ +"Created on %@" = "Створено %@"; + +/* quicklook creation info */ +"Created on %@ with %@" = "Створено %1$@ з %2$@"; + +/* quicklook creation info */ +"Created with %@" = "Створено з %@"; + diff --git a/macosx/QuickLookExtension/zh-CN.lproj/Localizable.strings b/macosx/QuickLookExtension/zh-CN.lproj/Localizable.strings new file mode 100644 index 000000000..bfbdfaef6 --- /dev/null +++ b/macosx/QuickLookExtension/zh-CN.lproj/Localizable.strings @@ -0,0 +1,27 @@ +/* quicklook file header */ +"%lu Files" = "%lu 个文件"; + +/* quicklook file count */ +"%lu files" = "%lu 文件"; + +/* quicklook tracker header */ +"%lu Trackers" = "%lu 个 Tracker"; + +/* quicklook web seed header */ +"%lu Web Seeds" = "%lu 个网络种子"; + +/* quicklook tracker header */ +"1 Tracker" = "1 个 Tracker"; + +/* quicklook web seed header */ +"1 Web Seed" = "1 个网络种子"; + +/* quicklook creation info */ +"Created on %@" = "创建于 %@"; + +/* quicklook creation info */ +"Created on %@ with %@" = "由 %2$@ 创建于 %1$@"; + +/* quicklook creation info */ +"Created with %@" = "由 %@ 创建"; + diff --git a/macosx/QuickLookExtension/zh-TW.lproj/Localizable.strings b/macosx/QuickLookExtension/zh-TW.lproj/Localizable.strings new file mode 100644 index 000000000..e20080045 --- /dev/null +++ b/macosx/QuickLookExtension/zh-TW.lproj/Localizable.strings @@ -0,0 +1,27 @@ +/* quicklook file header */ +"%lu Files" = "%lu 個檔案"; + +/* quicklook file count */ +"%lu files" = "%lu 個檔案"; + +/* quicklook tracker header */ +"%lu Trackers" = "%lu 個追蹤器"; + +/* quicklook web seed header */ +"%lu Web Seeds" = "%lu 個網路種子"; + +/* quicklook tracker header */ +"1 Tracker" = "1 個追蹤器"; + +/* quicklook web seed header */ +"1 Web Seed" = "1 個網路種子"; + +/* quicklook creation info */ +"Created on %@" = "建立於 %@"; + +/* quicklook creation info */ +"Created on %@ with %@" = "由 %2$@ 建立於 %1$@"; + +/* quicklook creation info */ +"Created with %@" = "由 %@ 建立"; +